一道另类而简单粗暴的题解

本贴最后更新于 1626 天前,其中的信息可能已经时异事殊

上周看到帖子《解密有奖活动》这个形式上类似 CTF 的题,有感而发,跟风也出了一道题。由于以前没出过这类题,所以出的比较简单粗暴,本来可以更优雅的。但解决这道题仍然需要解题人有一定的耐心和基础知识储备。

现在帖子沉下去了,看来没人打算解了,那这 250 积分就送给我自己了 😂

下面我将从一个小白的视角,分析并解决这个题目。

1. 密文在哪里?

有上一个解密帖子的经验,先把帖子正文复制到 vim 里面看下,看看有没有特殊字符(并没有)。看来密文藏在别的地方。

0.png

正巧发现社区提供了查看帖子 Markdown 的功能,点开看看

1.png

咦,发现了一段 HTML 注释(看上去全是空白字符,还挺长),看来这就是密文了,先保存到本地文件中再说。

2. 密文该怎么解?

sed 's/\(.\)/\1\n/g' some_text | sort | uniq -c

先处理一下,看看都包含哪些字符。

2.png

看来还真的只有 \n\t 三种空白字符。到这里已经没有思路了,用三种字符做编码,可能的方式有太多,难道要一个个去尝试?作为一个从来没打过 CTF 的小白,完全不知道接下来该怎么办。

诶,对了,帖子里不是有一个提示么?看一看,或许会有启发。

密文其实是一段可以执行的代码

额,这不等于没说嘛,不还是得先解码再执行。。等一下,如果这段代码可以直接执行呢?

这时,Google 就派上用场了。搜索一下,有没有仅用空白字符编程的语言。

3.png

还真有。这个语言的名字就叫 Whitespace。点进 Wiki 简单看了下,这个语言大概就是用三种空白字符组成一系列指令来操作栈和堆,还有一些数学计算和 I/O 相关的指令。但是用这种语言写的代码对人类似乎并不友好,很难读。能不读还是先不读吧。执行一下看看结果再说。万一我的猜想不对,这不是一段 Whitespace 代码呢。

相信这个存在了已经快 20 个年头的语言一定有很多现成开源的解释器实现了。我希望找到一个可以在线直接用的,省得下源码到本地自己编译了。

4.png

完美,一下子就找到了。那就试试第一个吧。

5.png

点新建文件,把那串空白字符复制进去,可以看到这个在线 IDE 做的有模有样,空格用淡粉色显示,Tab 用蓝紫色显示(但我并不觉得代码的可读性提高了多少)。

点执行,满怀期待地看输出结果。只见程序输出了“请输入密码”字样。看来我之前的猜想是正确的,但距离正确答案还有一步之遥。先得知道密码是什么。

3. 密码是什么?

先随便输入一些东西,看看会输出什么。

6.png

看来密码不是“helloworld”(能是这种密码就见鬼了),这也意味着我需要从程序中破解出密码了。

如果能读懂这段 Whitespace 代码,那应该就能知道密码是什么。然而,就算出题人没有刻意对代码做过混淆,我也不想为了一道谜题,特意去学一门比汇编还难读的奇葩语言。

那我们就从另外一个方向下手。不管是什么语言写的程序,验证密码这一行为,无非是将用户输入的字符串和一个现成的字符串做比较。对于这道题而言,那个现成的字符串,多半会事先放在内存的某个位置,而且对于这种简单的程序,应该不会做 Hash 之类的处理。

重新运行程序,当程序暂停等待我们输入时,看一看 Whitespace VM 的内存使用情况。

7.png

栈里面就一个 0,没有关注价值,主要看堆内存。

我发现,堆内存中有大量数值比较小的连续单元,用 0 隔开,而且都在可打印 ASCII 的范围,且 32 这个值(对应 ASCII 的空格)多次出现。所以我大胆的猜测,这些多半是是明文存储的字符串。

接下来我打算把他们转换成对应的 ASCII 字符,然后进行观察。简单处理了一下,搞成一个 C 语言的脚本:

#include <stdio.h>

int main() {
    char a[] = { 112, 108, 101, 97, 115, 101, 32, 105, 110, 112, 117, 116, 32, 112, 97, 115, 115, 119, 111, 114, 100, 58, 32, 0 };
    char b[] = { 99, 111, 110, 118, 111, 108, 117, 116, 105, 111, 110, 0};
    char c[] = { 115, 117, 99, 99, 101, 115, 115, 33, 0 };
    char d[] = { 102, 97, 105, 108, 33, 0 };
    printf("%s\n%s\n%s\n%s\n", a, b, c, d);
}

执行结果:

please input password: 
convolution
success!
fail!

这个 "convolution" 在里面显得格格不入,想必它就是密码了,而且输入以后,程序应该会输出 "success!"。

8.png

经验证,我的猜想是正确的。由于题目里说,答案是一个长度为 11 字符的单词,那它显然应该是刚才得到的密码 "convolution"。至此,题解完毕。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...