ROP-Ret2syscall详解
利用原理
ret2syscall,即控制程序执行系统调用,获取 shell。
可以理解为拼接成一个系统调用的栈。
在eax
、ebx
、ecx
、edx
中带入指定的参数拼接成关键的系统函数,最后在寻找int 0x80
的地址,从而执行这些函数.
顺序 | |
---|---|
32位 | eax->edx->ecx->ebx |
64位 | rdi->rsi->rdx->rcx->r8->r9 |
解题步骤
- 先使用cyclic测试出溢出点
- 确定要调用的系统函数
- 使用RODgatet先查找是否有/bin/sh的gadgets,如果有就直接使用execve
- 如果没有就要调用read函数实现用户输入/bin/sh存入内存,再使用execve
- 再使用工具RODgatgets查找各寄存器、
/bin/sh
、int 0x80
所在的地址1
2
3ROPgadget --binary ./rop --only "pop|ret" |grep "eax"
ROPgadget --binary ./rop --string "/bin/sh"
ROPgadget --binary ./rop --only "int" - 然后构造payload中依次对该地址传值
1
2
3
4payload = "a"*112
payload += p32(eax_ret)+p32(0x0b)
payload += p32(edx_ecx_ebx_ret)+p32(0x0)+p32(0x0)+p32(sh_ret)
payload += p32(sys_call) - 如果没有/bin/sh就要先调用read函数(详情见统函数页笔记)
- 各寄存器中传入read的参数
- 再在各寄存器中传入如execve函数的参数
- 最后在用户输入中传入/bin/sh到read的的buf参数,即buf值的地址
例题
Rop[简单系统调用]
思路
比较容易 参照上面解题步骤即可。
EXP
1 | from pwn import * |
Ret2sys[多系统函数调用]
思路
- 由于程序中并没有
/bin/sh
这个字符串,如果执行系统调用必须要手动将/bin/sh
写入到程序bss
段中 - 构造payload可以使用read函数,在内存地址中读取之后用户输入的/bin/sh
先找到eax,ebx,ecx,edx
以及int 0x80
的地址 - 对eax,ebx,ecx,edx填充read函数的参数(在bss段找到一个有权限的地址,带入到ebx中)
- 再次对eax,ebx,ecx,edx填充,这次使用execve函数,执行之前read函数读取的内容所在的地址内的值 即”/bin/sh\x00”
- 执行payload,进行溢出,再次向程序中发送数据 即“/bin/sh\x00”
EXP
1 | from pwn import * |
Ret2sys[64位寄存器]
思路
- 与32位不同,需要注意以下几点
- 存储参数的寄存器名不同
- ret返回的函数名不同
- 32位为int 0x80,64位为syscall ret
EXP
1 | from pwn import * |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 偏有宸机!
评论