利用__libc_csu_init的通用gadgets
简介
在__libc_csu_init
中有以下gadgets,可以帮助我们摆好很多寄存器,或者用来花式rop。
1 | mov rdx, r13 |
恰好能让rdx和rsi的值被r13和r14控制,而且若能让rbx为0, r12可以调用特定的shellcode,
一般拿来充当ret,找到ROP下一句的位置填进去
而刚好还有如下gadgets
1 | pop rbx |
例题
ciscn_s_3
分析
发现vul()是在执行一个read(0, [rsp+buf], 0x400)和write(1, [rsp+buf], 0x30)
读入了0x400个数据显然有缓冲区溢出。
checksec发现只开了NX。
发现gadgets()中存在
mov rax, 0xf ; ret;
和mov rax, 0x3b ; ret;
查阅资料得知0x3b是execve()的系统调用号,而vul()中刚好有syscall指令,所以这道题的思路就是将rdi的值变成’/bin/sh\x00’,rsi和rdx的值变成0。
(另一种做法是利用0xf是sigreturn的系统调用号,布置好sigreturnFrame,走srop也可getshell)
‘/bin/sh\x00’我们可以通过输入得到,所以现在要做的就是leak出rsp的值。
在write函数输出0x30个值的时候,前0x20个数据不用管,而接下来的0x8刚好就是栈上的一个地址。
这个时候进gdb调试,输入AAAAA,然后find AAAAA,找到此时栈顶的指针,和刚刚leak出的那个栈上的地址进行计算,算出偏移量0x118。把’/bin/sh\x00’放到rdi里只需要找到pop rdi; ret;这个gadget就行了。
接下来就是利用__libc_csu_init里的gadgets来将rsi和rdx置0就行了。
call [r12+rbx*8]这里,我们让他和后面的ROP连在一起,可以利用0x40059a的gadgets将r12的值改成原先栈顶的值。然后经过简单计算,为了和后面的ROP连在一起,这里应该是栈顶+0x58,我取了个巧,把rbx的值改成了0xb,这样也能刚好接上后面的ROP链。
exp
1 | from pwn import * |