XCTF 2018 Final - Railgun Writeup
Railgun
You can get the binary from here
程序主要的逻辑是一个挖 coin 然后使用 railgun 发射 coin 来打 boss 的游戏。(强行睿智
程序初始化会将 flag+padding 用随机生成的 RSA 公钥加密。每一个 Boss 都是一个随机的 AES key,用一个 coin 打败 Boss 并再使用一个 coin 可以得到用 RSA 私钥解密用户输入并用 AES_ECB 加密 RSA 结果的最后半字节。 在这个过程中用户已知的变量有 n, e, pow(flag+padding, e, n)。
UAF
程序在功能 6 accelerator attack 中可以消耗 200 个 coin 直接击败 Boss9,这里存在一个 UAF。Boss9 在被 free 掉之后依然可以和正常的 Boss 一样被打败然后进行 AES_ECB 加密。
Bypass AES_ecb
利用 accelerator attack 中的 UAF,再利用 comment 功能,指定注释长度为 16 就可以 malloc 到之前 free 掉的 Boss9,这样就可以控制一个 AES key。
RSA LSB Oracle Attack
之后进入密码学时间
已知 n, e;
flagCipher = pow(flag+padding, e, n)
击杀 Boss 可以获得 AES_ecb(pow(input, d, n) % 16, Boss)
因为 Boss9 已经被控制了,所以相当于返回的是 pow(input, d, n) % 16
使用 RSA LSB Oracle Attack
假设攻击者已知 x 个最后半字节,设未知部分为 a,已知部分是 b,则有 \(f = a * 16^{x} + b\)
令 \(y = 16^{-x}\ \text{mod}\ n, Y = y^{e}\ \text{mod}\ n\)
输入 \(\text{flagCipher} * Y\), 则会返回 \(fy = a + b * 16^{-x}\ \text{mod}\ n\ \text{mod}\ 16\)
因为 \(b * 16^{-x}\ \text{mod}\ 16\) 已知,所以可以求出 \(a\ \text{mod}\ 16\)
Exploit
利用 UAF 控制 Boss9 的内容,然后用 RSA LSB Oracle Attack 逐半字节攻击出 flag
1 | from pwn import * |
Trick
- 程序中存在一个检查不严格导致的整数下溢,当你拥有一个 coin 时对一个 Boss 连续使用两个 coins 可以使你的 coin 数下溢变成 255,并且只要你两个两个的用,硬币就永远都用不完。这个 trick 可以极大的加速你的攻击脚本。(毕竟是个攻防题
- 在远端利用 UAF 时,由于环境因素,在执行 comment 中的 malloc 时,即使大小合适,也不一定能每次都拿到 Boss9 的那个块(虽然在本地测试的时候几乎每次都能通)。所以建议多 comment 几次来提高成功率。(连续申请十次的话基本每次都能通的)