32位的ROP
这个在栈基础中提到过,此处写出是为了和64位的形成对比。通过在返回地址上写上函数PLT的地址来实现跳转到函数,调用函数时压入参数后会压入eip(返回地址),然后32位程序参数在栈上,所以结构如下图:
| 栈底-高地址-> | c |
|---|---|
| b | |
| a | |
| 实际调用函数中的返回地址eip | dddd |
| 原返回地址(r) | system的plt表地址 |
| 原ebp (s) | aaaa |
| aaaaaaaaaaaaaaa… | |
| 栈顶-低地址-> | … |
system的参数为a处,所以构造为
payload = flat([cyclic(0xn),p32(system_addr),cyclic(0x4),p32(binsh_addr)])
64位的ROP
而在64位程序中,参数由rdi,rsi,rdx,rcx,r8,r9来寄存前六个参数,多的才会存放到栈上,而当我们执行汇编指令pop rdi时,就会将栈顶的值赋给赋给rdi,所以只需要我们将我们需要修改的参数值写在pop rdi上面(靠近栈底的方向),再加上函数,即可实现给rdi赋值并且调用函数使用这个值。
| 栈底-高地址-> | |
|---|---|
| 函数地址 | |
| 参数 | |
| 原返回地址(r) | pop rdi;ret的地址 |
| 原rbp (s) | aaaaaaaa |
| aaaaaaaaaaaaaaa… | |
| 栈顶-低地址-> | … |
在虚拟机中有工具ROPgadget可以直接进行搜索,如下图
在图中搜索的是$0,这个在linux中相当于/bin/sh
也就是system("$0") == system("/bin/sh")
ROPgadget --binary 文件名 | grep '需要的汇编指令'
ROPgadget --binary 文件名 --string '\字符串'
即构造为
flat([cyclic(0xn),p64(pop_rdi_addr),p64(binsh_addr),p64(system_addr)])
本文对比介绍了32位和64位程序中的Return Oriented Programming (ROP)技术。在32位程序中,通过在返回地址上写入函数PLT地址实现跳转,参数在栈上。而在64位程序中,参数由寄存器存储,通过poprdi指令修改rdi寄存器并调用函数。文中还提到了利用ROPgadget工具寻找相关gadgets的方法,并展示了如何构造payload。
ROP&spm=1001.2101.3001.5002&articleId=110298613&d=1&t=3&u=797936efd8424b458afa48636f522a70)
719

被折叠的 条评论
为什么被折叠?



