提示:
1. 本题两个 flag 均由远程服务器提供.
2. 本题两个 flag 均为有意义的字符串.
3. 与服务器交互时请使用 UNIX 换行符.
4. 这不是 HTTP 协议啊喂 (╯‵□′)╯︵┻━┻, nc 命令请了解一下.
The CWK History Symposium 会议上的一篇论文 On the missing heritages of CWK 里写道, “…CWK 并没有将他的修为与财富留给子嗣, 因为当时的 FLXG 并没有被世人所理解. 在无人知晓的时候, CWK 远游四海, 于一个孤岛上独自一人建立了一座巍峨宏伟的神庙, 并将有关 FLXG 的宝藏全部埋葬于此. 然后他又利用不为人知的技术, 使这座荒岛看起来平平无奇, 并且还能避开如今的 FLXG 雷达的探测. 根据当时联合国粮食与农业组织 (FAO) 的记录, 那几年太平洋西部海岸洋葱产量锐减. 我们由此推测 CWK 应该使用了当时比较冷门的一个西方魔法, 可以从洋葱中提取能量从而隐藏海域…”
当我偶然翻到这篇 paper 的时候, 脑子里电光火石般想起来, 自己曾经在滑稽大学图书馆中借走的一本 信息安全导论 中夹着的那一张羊皮纸. 这一瞬间, 我感觉自己的内心里充满了 flag… 没错, 一定是这样的. 这张古老的羊皮纸就是 CWK 留给滑稽大学最宝贵的遗产, 前往 FLXG 神庙的地图!
不愧是 CCF (China CWK Federation) 推荐的 A 类会议, 我一边想, 一边往下读, “…CWK 在神庙里设计了试炼, 只有通过的人才有资格成为他的继承人…据说神庙的设计图被 CWK 用法力嵌入到了指向神庙的地图里. 关于 CWK 的其他许多传闻逐渐都得到了验证, 而这张宝贵的地图却依旧只是传闻, 在历史上从未出现过…”
读至此处, 我心中热血沸腾, 恨不得立马出发, 去 FLXG 神庙一探究竟. 可是转念一想, CWK 出的题目往往都很坑, 又有些踌躇不前. 正好, 最近似乎滑稽大学要举办一个啥比赛, 不若投石问路, 让那些好奇的选手们先去探个险, 看看他们能不能从神庙中站着出来…
Tor,nc with proxy,LSB,抠图
得到一张webp格式的图片。使用官方工具分析得知此 webp 图片为无损压缩。使用 dwebp 转换为 png 格式。注意,如果有选手使用第三方工具转换而导致后续步骤无法进行,请不要抱怨题目有非预期的错误,相反,您应该给这些第三方工具提 issue。
得到 png 后,使用 stegsolve 查看通道。发现绿色通道的 LSB 有明显的隐写痕迹。右下角有一个洋葱地址,中间的神庙区域有明显规律性条纹。实际上这个条纹是因为出题人故意使用 Base64 编码一遍,使得原来二进制中的规律部分更为明显。
我不知道为什么很多人都把这个地址和端口号当作 HTTP 协议。没有任何说明的情况下,一个端口并不应该默认为使用 HTTP 协议。这又不是 80 或者 8080 端口..。正确做法应该是使用 nc 连上去,会发现这实际上是一个类似于 pwnable 的一个交互方式。
至于如何使用洋葱,这里不再详述,请参考官网教程。一般的洋葱客户端会提供一个 9150 或者 9050 端口的 SOCKS 5 代理服务。使用 nc 的参数或者 proxychains-ng 均可接入。
连入后发现提示输入 CRC32。如果输入 webp 图片的 CRC32 会进一步提示设计图纸被藏在图片里。
所以我们转向绿色通道中的神庙区域。思路应该比较明显,需要把这片区域的像素抠出来。
为降低难度,这片区域已经用纯黑色的边框包围,并且保证了区域内没有纯黑色的像素点。一个最简单的做法是,使用 Photoshop 手动选择一小部分,选区 -> 扩大选区,可以将这片区域内的像素点全部选中。查看一下统计信息,可以发现这片区域内有 249024 个像素点。很明显可以被 8 整除。这是一个正面的提示。然后将这片区域粘贴到一个新的全黑色的背景图片上。保存。然后就可以写 python 脚本处理绿色通道的 LSB 了。
(此处省略处理脚本)
脚本得到的是一个 Base64 的字符串。解码后是一个 ELF 文件。在远程输入 Base64 字符串或者 ELF 的 CRC32 均可得到第一个 flxg。
https://gist.github.com/pzread/2ae0bb3aa5fe0dc69fcf3257c41db944 ,bit flipping attack
这道题其实是出题人学习去年 HTICON 里一个技巧的成果 (话说马上又要 HITCON 了)。有两个人做出来有点出人意料(可能有非预期了),不过因为控制好了 SECCOMP,再怎么非预期也不会造成预期之外的危害 23333333
这道题功能很简单。首先输入用户名,判断不能为 root,拼接上 hash 后再使用随机的密钥和 IV 做 AES CBC 加密。另一个函数需要输入结果,然后通过密钥和 IV 解密,再比对 hash 正确性。之后判断用户名是否为 root,如果是 root 就直接给 flag。
这题有几个漏洞:
- 首先有整数溢出,溢出的后果是 double free。控制 free 的整数只有 8 位,所以 free 被拒绝 128 次后就可以随便 free 了。
- 其次内存拷贝用的是 strcpy,这个会造成越界。
- 然后就是密码学上的,bit flipping attack。通过更改 IV 可以更改解密后第一个分组的内容。
- 最后就是 HITCON 的奇技*巧,二进制中的 memcmp 实际上是 strcmp。
double free 不是用来利用的。实际上要注意到 init 里面会调用 mallopt,设置了这个函数会将 free 的 buffer 填充为 0xAA。而这次 malloc 的 buffer 很小,使用了 tcache 后所以需要 free 七次才行。
然后通过 strcpy,将 0xAA 复制到目标数组。通过 bit flipping attack 得到 root 的用户名和第一个 0xAA。然后需要绕过 hash 检测。所以我们不停的尝试,直到 hash 以 0x00 开头。这样 strcmp 比较两个空字符串会直接返回 0。
exp 见 poc.py,代码见 trial.c
关于如何做到将 memcmp 偷天换日到 strcmp,可以看 HITCON 的那篇 gist。基本原理就是内核计算 PHDR 的偏移错误,所以可以放上两个 PHDR,真 PHDR 中的 PT_DYNAMIC 中 DT_SYMTAB 被修改了。所以 ld.so 解析函数的时候会使用后面的 DT_SYMTAB,而一般的反汇编工具会使用 ELF Spec 下的 DT_SYMTAB。
更详细一点的介绍在这里,http://h3ysatan.blogspot.com/2018/02/quick-notes-hitcon-ctf-2017-qual-elf.html。
果然翻车了, 有个特别简单的非预期解... 排查后发现是 UB 导致的编译器优化把一个边界检查给优化没了... 辣鸡 GCC (╯‵□′)╯︵┻━┻ 换成 clang 编译就没这么多事了...