也是今天刚搞懂,先写了再说
使用的原因
其实csu指的是每个程序一定会有的函数: libc_csu_init
我们以这个ctf-challenge中的例子学习ret2csu
这是IDA逆向之后的csu函数的一部分
也是我们所需要的部分
我们可以看到下面的pop可以帮我们控制寄存器,
同时,上面的mov也可以补充下面无法控制的部分寄存器
当然,你应该也发现了我的示例里有两个脚本,exp1没有使用csu,
而是直接控制了寄存器,这是因为在这个示例里rdx的值足够大(大于8),也就足够输出我们需要的got表值了。如果在其他情况下,那exp1则是无效的。
还有一点就是,我的示例里用的是我本地的libc,而不是附件里面的,如果你无法打通,请参考ret2libc相关知识,将脚本适当调整(在栈上fmt学习也用到了)
控制csu泄露got表
1 | csu1 = 0x40061A |
r13、r14、r15根据这一部分的csu
其实就是在控制rdx、rsi、rdi,同时如果我们让rbx为0,那我们call时就自然调用的是r12的函数,也就是我设定的write
cmp要求我们要rbx跟rbp最后一样,否则将会再次调用,这不符合我们的预期。一开始我们让rbx为0,有个add之后我们的rbx变为了1,所以我们rbp也取1。
前面的b’a’是为了溢出,第二个呢?
第二个是因为不再次运行这个部分的程序
只保留retn,一共7*8个字节
这样我们就填充retn为我们所需要的main的地址(为了再次调用函数,我这里图省事就没再用csu了)
同时也输出了我们所需要的got表地址
进而得到libc基址
最后
后面的部分其实就是正常的使用寄存器控制参数调用system函数了,难度不高