coolshell 谜题通关

一、前言

周末在微博上看到 coolshell 博主陈皓搞了一个编程小游戏的页面,过关制的。感觉很有趣,就打开看了看。有空没空搞了3天才算搞定,感觉眼界开阔了一些,但是对每一关涉及到的知识都了解的太浅,这里仅仅记录一下通关过程,至于涉及到的知识会在最近学习一下:)

首先,游戏地址是:coolshell 大闯关

游戏规则很简单。每一关都需要得到一个结果,把这个结果填进 url 即可进入下一关。下面是通关攻略(强烈建议自己先试试,每一关如果20分钟都没思路就可以看看攻略了)

二、通关过程

0. first.html

这一关由两部分组成:

  1. 一段乱七八糟的符号
  2. 一个提示语:My brain has been fucked

当我打开这个页面的时候,感觉这啥玩意啊。难道是正则表达式提取?于是看了看+号,依次是1个,2个,3个……然后又找了各种规律找不到,很是郁 闷。于是就去干别的了。等我无聊的时候打开了这个页面的源代码,灵光一现发现上面不是纯文本,而是一段 code,那提示语应该跟 code 相关吧?于是就在网上开始搜,百度必应不出意料的呵呵呵(原谅我一直黑,但这是事实啊。。),于是用 google 开始搜,(⊙o⊙)…然后发现 fuck 被 google 过滤了,和简单,把安全过滤去掉就好了(中文版 google 是不能去掉安全过滤的,你懂的。所以切换到中文繁体,然后在右下方的设置里面去掉安全过滤之后拉到最下面保存即可)。然后看了几个网页,进了英文版的 wikipedia,然后答案就很明显了。原来有门编程语言叫做 brainfuck。之后就很 easy 了,可以看看这是静态还是动态的,静态的就找个编译器和解释器,动态的直接在网上找个解释器就好。我随手搜了个在线运行的网站,把代码贴进去。执行结果是welcome,于是下一关就被打开了。

总结一下:

  • brainfuck wiki
  • 找一个在线执行 brainfuck 代码的网站,比如这个brainfuck
  • 贴进去点击 Run,看输出就哦了
1. welcome.html

这关很简单的其实,根据等比数列,可以首先得到一个数字:18 * 108=1944。然后试一下,发现这个1944对了。但是还有其他答案,应该是在那句话里。这次聪明了直接 google,然后直接知道是42。然后发现也对了,但是没有进入下一关。从 X * Y 那个来看,难道是求一下乘积?尝试着 1944 * 42 = 81648。然后就过关了= =

总结一下:

  • 生命、宇宙以及任何事情的终极答案——42,为什么?你丫不会 google 啊
2. 81648.html

一个硕大的键盘,鼠标滑过图片发现可以点击。然后会进入一个 wiki,大概看看介绍,这个布局是为了提高打字速度设计的,跟目前的布局也是一一对应的,然后自己人肉翻译一下即可,得到下面的代码:

1 main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

发现原来是一段 C 代码,用 gcc 编译执行后,输出 unix,得解。

总结一下:

  • 为打字出现的Dvorak Simplified Keyboard和目前使用的QWERTY键盘布局
  • 那段代码很有厉害,可自行 google 一下
3. unix.html

出来一个二维码,用微信扫一下发现是一个字典。结合二维码下面那一段话,就非常简单了。写段程序翻译一下即可。随手写了一个:

 1 #include<stdio.h>
 2 #include<ctype.h>
 3 #include<string.h>  4 #include<stdlib.h>  5  6 #define N 1000  7 char a[] = "abcdefghijklmnopqrstuvwxyz";  8 char b[] = "pvwdgazxubqfsnrhocitlkeymj";  9 char ci[N]; 10 11 char find(char c) { 12 int i; 13 for(i = 0; i < 26; i++) { 14 if(c == b[i]) { 15 break; 16 } 17 } 18 return a[i]; 19 } 20 21 int main() { 22 char *str = "Wxgcg txgcg ui p ixgff, txgcg ui p epm. I gyhgwt mrl lig txg ixgff wrsspnd tr irfkg txui hcrvfgs, nre, hfgpig tcm liunz txg crt13 ra \"ixgff\" tr gntgc ngyt fgkgf."; 23 24 int len = strlen(str); 25 for(int i = 0; i < len; ++i) { 26 char c = str[i]; 27 if(isalpha(c) && islower(c)) { 28 ci[i] = find(c); 29 } else { 30 ci[i] = c; 31 } 32 } 33 34 printf("%s\n", ci); 35 return 0; 36 }/*output: 37 Where there is a shell, there is a way. I expect you use the shell command to solve this problem, now, please try using the rot13 of "shell" to enter next level. 38 */

发现输出需要用到 rot13,这是啥?!google 一下就知道了,原来就是一个简单的加密工具,因为英文字母有26个,13对,所以正好可以一一对应。然后 google 一下使用方法就可以了,或者懒得直接找一个在线 rot13转换的工具,输入 shell 后得到结果:furyy

总结一下:

4. furyy.html

因为以前在玩正则表达式的游戏时遇到个这个模式,瞬间就知道这个是考察正则的了。根据那个单词,知道是回文字符串。根据图示知道需要找出能匹配左边8个单词的模式,然后提示语说在源码中有东西。打开源代码拉到最下面有一大段文本,保存到一个文件中。

这时候思路已经很明显了,用找出来的模式去匹配这段文本。那么,首先就需要找出这个模式,如果以前学过正则表达式的话,应该是很 easy 的。如果不太会,在下面总结的时候我会推荐一个讲解正则表达式很好的地方,配套有一个练习的地方(额,难度略高)。

找出来这个模式也很简单,人肉看下就是:

  • 第一个字符是大写或者数字
  • 第二个字符是大写或者数字
  • 第三个字符是小写
  • 第二个字符
  • 第一个字符

所以,考察的就是最简单的正则表达式,其中回文也可以用正则中的()来匹配。这样答案就出来了:

([A-Z])([0-9])[a-z]\2\1|([0-9])([A-Z])[a-z]\4\3

然后有输入了,有处理过程了,执行一下即可得到输出:

egrep -o '([A-Z])([0-9])[a-z]\2\1|([0-9])([A-Z])[a-z]\4\3' palindrome

然后就可以得到答案:

E1v1E
4FaF4
9XrX9
O3i3O
0MaM0
4GbG4
M5l5M
0WeW0
Y0s0Y

这几个都是回文串,我们根据 cat 是最中间小写字母的原则拿出来,得到答案:variables

总结一下:

5. variables.html

妈蛋这个页面让我困了大半天,不知道想表达什么意思。我以为是那个数字有特殊的含义,google 了半天找到看起来靠谱的英文。好像是美国哪个州的 zipcode 啥的,填进去各种404,让我很是崩溃。。。 最后也没搞定,是看了网上已经出来的攻略才知道。。(这次写攻略才发现那句提示有点作用,让你 keep try...)

原来需要拿那个数字替换 url 中的2014,于是我就替换了,大概替换了10多次,还是需要替换。。估计要写个程序的样子,于是用 shell 写了个 while 循环,里面就是一个简单的 curl 命令,最后得到了答案:tree

总结一下:

  • 善于观察,这道题如果仔细看说不定会找到思路,,,,不过嘛,,,,,,,,,,遇到我这种智商的就,,,,,,,不说了,擦泪去
6. tree.html

这道题就简单了,就是一个树。扫了一眼就知道题意是由中序和后序还原树,然后求得最深路径。于是写了一段代码,特么由于好久没碰指针,各种凌乱,吭哧吭哧花了将近1个小时才搞定,,,真是弱爆了。。。。

 1 #include<iostream>
 2 #include<ctype.h>
 3 #include<stdio.h>  4 #include<string.h>  5 using namespace std;  6  7 struct Node  8 {  9 char value; 10 Node *left; 11 Node *right; 12 }; 13 14 string t_in, t_post; 15 char in[100], post[100]; 16 char deep[100], final[100]; 17 int maxlen; 18 19 void init() { 20 int p = 0; 21 for(int i = 0; i < t_in.length(); i++) { 22 if(isalnum(t_in[i])) 23 in[p++] = t_in[i]; 24 } 25 26 p = 0; 27 for(int i = 0; i < t_post.length(); i++) { 28 if(isalnum(t_post[i])) 29 post[p++] = t_post[i]; 30 } 31 } 32 33 Node* build(char *in, char *post, int len) { 34 if(len == 0) 35 return NULL; 36 37 Node *cur = new Node; 38 cur->value = post[len - 1]; 39 int lenp = strchr(in, cur->value) - in; 40 cur->left = build(in, post, lenp); 

转载于:https://www.cnblogs.com/lsleilei/p/4926179.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值