cve-2020-0022
CVE-2020-0022 复现
还差最后的rop部分
本文所用到的文件放在github
准备
调试相关
测试用的电脑系统是Ubuntu18.04 蓝牙设备 intel 8265
安装完必要的驱动以及工具之后需要修复一个小问题
1 | Wel, FWIW, I changed the following two settings in /etc/default/bluetooth : |
在调试的时候如果出现一些奇奇怪怪的问题(大多数是因为还没有彻底断开连接?),可以尝试下重新开关下蓝牙开关
1 | sudo hciconfig hci0 down |
测试手机是红米note5
MIUI10 9.9.3 开发版本
android9 补丁版本 2019-09-05
因为miui上边有两个蓝牙相关的程序,所以我们需要确定在miui上边到底是哪个程序
1 | whyred:/ # ps -A |grep blue |
我用了一个比较暴力的方法去找的所在程序
1 | whyred:/system # find . -type f |xargs strings -f |grep reassemble_and_dispatch |
经过确定之后发现实际用到的是libbluetooth_qti,程序是com.android.bluetooth。后来调试的时候发现附加上应用之后,暂停应用时间过长的话,com.android.bluetooth 会超时,然后被杀掉。再看文章,发现作者使用了gdb脚本来进行调试(分析),于是我抄了一份脚本
1 |
|
start.sh
1 |
|
attach.sh
1 | set sysroot . |
gdbinit 文件
这里还有一个问题,可能是我的机器性能太差,pwndbg之类的插件并不能正常使用,如果加载了这些插件程序在调试时就会被超时kill
协议相关
HCI(Host Controller Interface) 实现了对控制器的统一接口,使得Host(可以简单的理解成主机上的软件)和Controller(硬件控制器)之间的通讯简单了起来,他们之间的通讯是通过HCI Packet进行的。包括
- HCI Command host->controller
- HCI Event controller->host
- HCI Data host<->controller 这个包又分为 ACL(异步传输,不可靠) SCO (同步传输,可靠)
通讯抓包如下
我们用到的结构体如下
其中handle中包含handle , PB ,BC 三个字端
PB字段
- 00 host->controller 10 controller->host 首包 经过测试发现10 00在ubuntu上 效果是一样的:)
- 01 controller<->host 续包
包中各个关系如下
漏洞分析
相关文章分析的也都挺详细了,
主要问题是这里packet->len已经被修正了为真正需要拷贝的长度了,但是下边又减去了hci_hdr的长度
如果这时候真正需要拷贝的长度<4
,就会发生整数溢出,导致传入memcpy的size是个负数,如果大于4,那么就会得到4字节未初始化的内存
exploit
memcpy bug
这个漏洞可以实现RCE,是用到了memcpy的一个bug
具体的分析在参考文章中也有,我这里再啰嗦一遍
考虑这么一种情况
(count+(dst&0xf))>MAXINT64
1 | prfm PLDL1KEEP, [src] |
走一遍流程可以看到,这种特殊情况下memcpy是不会陷入拷贝死循环的
同时dst我们都能够控制&0xf的部分
在上述情况,memcpy会先拷贝[src,src+0x40)到[dst,dst+0x40) 之后 会拷贝 [srcend-0x40,srcend)到[dstend-0x40,dstend)
dstend = dst+count < dst(count 溢出成负数了),这样相当于我们能够溢出两部分,一部分是向后溢出,另外一部分是向前修改
leak
在memcpy bug中我们发现能够前向溢出0x40 后向溢出0x40
看源码可以发现,当有续包的时候,原来的数据会被free掉,如果没有则会进入reassembled
经过调试我们可以发现,直接进入reassembled
的包暂时不会被free,并且同样大小的包是在一块的(可以看参考文章基于jemalloc的Android漏洞利用技巧
)
我们可以提前布置好数据,使用mempcy前向覆盖掉头部的一些长度控制信息,来实现leak内存数据
1 | 第一个包 |
leak code address and heap address
code address
这里使用了0x38 + 2 + 13 大小的堆块进行泄漏
从leak中发现了如下几个地方比较常见
0x74b3d2a898(几率较大)
1 | ➜ myexploit ./maps_find.py ./maps 0x74b3d2a898 |
另外一次leak
1 | ➜ myexploit ./maps_find.py ./maps1 0x7c565aa898 |
0x7415a25bf0
1 | ➜ myexploit ./maps_find.py ./maps 0x7415a25bf0 |
heap address
来看这一句
我们自己写一个来试试
可以看到一项是一个堆块
返回来看bluetooth_qti.so
那么,我们利用上述手法即可泄漏出真实堆地址(只是不稳定
pc control
调试中发现,发送0x38畸形数据会有很大的几率触发以下代码
1 | .text:000000000013B9EC LDR X8, [X8,#8] |
1 | .text:00000000000E93C4 LDR X8, [X19] |
此时 x8是x19指向的内容 x19指向当前包 只要我们能够准确知道上述两个地址,那么就能够控制pc了,之后就可以用rop来操作了
以及crash2.c中的方式会触发一个类似的代码
参考文章
CVE-2020-0022 an Android 8.0-9.0 Bluetooth Zero-Click RCE – BlueFrag
CVE-2020-0022 蓝牙漏洞初探(上)一个bug引发的血案