2015-hacklu-bookstore

本文详细介绍了如何利用2015 Hacklu Bookstore二进制文件中的格式化字符串漏洞和堆溢出漏洞进行攻击。通过精心构造的输入,实现了对内存的任意读写,利用堆chunk的重叠来控制dest,最终通过修改返回地址执行one_gadget。同时,文章分享了在过程中学到的知识,包括ida的使用技巧和堆管理的理解。
摘要由CSDN通过智能技术生成

首先提供题目的二进制文件:2015_hacklu

预览:

程序为64位,然后没有relro,没有pie,给调试带来很大方便。放进ida看看基本功能:

可以看到程序开始的时候已经在堆申请了三个堆块,且大小固定为0x80。

这里感觉怪怪的,s可以输入0x80个字符。。。。应该会有用处。

可以看到程序最后有一个格式化字符串漏洞,我们通过经验得知,通过精心构造格式化字符串可以实现任意地址读写功能。所以我们的问题关注点应该暂时放到如何构造格式化字符串中。

接着往下看,看完后发现实际上程序功能很简单,就两个小功能,一个输入任意字节的输入功能,一个free()功能(uaf没什么用。)。

暂时有用的漏洞就是格式化字符串漏洞任意溢出漏洞

漏洞如何利用:

  1. 以格式化字符串漏洞为主线索来逆向推理分析,如何控制dest???,我们发现程序中好像没有可以控制dest的功能(任意溢出漏洞虽然可以覆盖到,但是之后dest会被更新为固定的字符串)。。。真让人头秃,只有自己构造了。。。。然后发现最后一个功能里的v5指向的chunk的位置还未固定(malloc()从bins里找chunk,而bins里的chunk是可控的),所以我们可以利用任意溢出漏洞更改v7指向的chunk的大小为0x150,然后free(),再通过程序的malloc(0x140)来实现chunkoverlapping,从而使v5指向的地址位于dest地址前面,然后利用填充v5的机会构造dest。这里还需要注意的地方是free(2)的时候,因为大小属于small chunk所以会有两道检查,一个是防止和后一块合并,所以必须伪造后后一块,并使其prev_inuse位为1,另一个是后一块的prev_inuse位要为1。

  2. 相信大家都能注意到,就是程序运行了一次就结束了,而我们至少需要两次运行,一次leak,一次change,所以这里需要利用第一次的机会来将fini_arry0改为main_addr,并且泄露libc地址(main函数返回到__libc_start_main中,可以在格式化字符串前来下断点,通过查看栈的数据来查看偏移,进而获得libc地址。),现在还有一个问题是fini_arry0怎么输入进栈并且确定偏移???这里需要打破常规思维,需要改的数据可以不在格式化字符串里,只要偏移可以确定就行!,这时候就想到了之前的那个s给了0x80的空间,我们可以将fini_arry0输入到s里然后通过调试确定偏移。

  3. 如果我们这时候继续往下做的时候做到最后会发现一个问题:改过got表之后程序已经几乎结束,不会再调用函数了,所以改了也没用,所以我们只能改main函数返回地址为one_gadget了,这时候我们就要确定泄露一个和返回地址的地址相对偏移不变的值,经过观察发现有一个存在,然后泄露他。

  4. 第二次返回时我们的任务就变成了改ret_addr为one_gadget即可。只需要改后面的三个字节即可(可通过调试发现)。

exp如下:

#coding:utf-8

from pwn import *

context(arch='amd64',os='linux')
#context.log_level='debug'
p=process('./books')
P=ELF('./books')
libc=ELF('./libc.so.6')
#gdb.attach(p,'b *0x400c8e')
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值