Checkm8 漏洞研究

更新中… 一句话描述漏洞:对USB请求处理不当造成的UAF漏洞。淘宝卖了一个二手iPhone6,决定研究一下checkm8这个漏洞。checkra1n虽然可以越狱iPhone6,但是ipwndfu不支持iPhone6,于是我又买了一个iPhone7。

上手尝试

在分析这个漏洞之前,先对checkm8有一个感性直观的认识,我们首先动动手,做俩实验:分别是使用checkra1n越狱,以及使用ipwndfu提取固化在处理器芯片中的固件代码(SecureROM)。不过在动手之前,先阅读以下写给科技爱好者的文章和广大网友对这个漏洞的讨论:

checkra1n 越狱

使用checkra1n,基本就是傻瓜操作。不过与普通越狱不同的是,在使用这个工具越狱后,并不需要安装cydia,即可在爱思助手直接开始ssh通道。ssh通道这个功能是将手机的22端口通过usb映射到电脑主机的端口,第一次用可能会迷糊。默认的用户名密码是:root:alpine,如果不熟悉越狱和ssh流程,可以参考如下文章:

另外发现ssh虽然开启,也可以由外部连入本机的22端口,但是并不能本机自己连自己,即并不能在手机上安装一个ssh客户端软件来访问自己的shell,这里苹果做了限制,绕过方式是修改ssh服务端口并重启,参考如下:

ipwndfu 提取 SecureROM

使用ipwndfu完成dump固件。但是其并不是对任何iPhone都支持,在readme中可见支持说明:

current SoC support: s5l8947x, s5l8950x, s5l8955x, s5l8960x, t8002, t8004, t8010, t8011, t8015
future SoC support: s5l8940x, s5l8942x, s5l8945x, s5l8747x, t7000, t7001, s7002, s8000, s8001, s8003, t8012

这些SoC版本对应的苹果设备型号可以参考:https://www.theiphonewiki.com/,可见iPhone6是t7000,iPhone7是t8010,所以这个工具目前是支持iPhone7的,于是我就又买了一个iPhone7。首先将iPhone7置于DFU模式,方法参考iPhone 进恢复模式和 DFU 模式有什么区别?,iPhone 7 或 iPhone 7 Plus 进入DFU 模式的方法:

  1. 保持设备处于开机或恢复模式下,插入数据线(建议使用自带原装数据线)连接电脑。
  2. 先按下设备的音量减小键不要松开,再按下设备的开机键不要松开,直到设备屏幕熄灭再过4秒左右松开设备的开机键,但不要松开音量减小键,直到爱思助手显示“DFU 模式”字样再将音量减小键松开。

然后在ipwndfu目录./ipwndfu -p完成后门的植入,但是报错The device has no langid,如下:

  sudo ./ipwndfu -p
*** checkm8 exploit by axi0mX ***
Found: CPID:8010 CPRV:11 CPFM:03 SCEP:01 BDID:08 ECID:000A201422E10026 IBFL:3C SRTG:[iBoot-2696.0.0.1.33]
Traceback (most recent call last):
  File "./ipwndfu", line 73, in <module>
    checkm8.exploit()
  File "/mnt/hgfs/桌面/pwn/checkm8/ipwndfu/checkm8.py", line 510, in exploit
    if 'PWND:[checkm8]' not in device.serial_number:
  File "/mnt/hgfs/桌面/pwn/checkm8/ipwndfu/usb/core.py", line 830, in serial_number
    self._serial_number = util.get_string(self, self.iSerialNumber)
  File "/mnt/hgfs/桌面/pwn/checkm8/ipwndfu/usb/util.py", line 298, in get_string
    raise ValueError("The device has no langid")
ValueError: The device has no langid

在ipwndfu的issue中大部分回答是添加sudo权限,但是没有卵用。最终参考这个Umiiii哥们的建议,的确我的本地环境也是mac上的libusb版本1.0.22,使用如下命令升级成1.0.23即可成功。

  brew upgrade libusb

然后即可成功,如果执行后仍然报错或者手机直接回到了正常模式可以重新尝试几次应该就可以成功了。

  sudo ./ipwndfu -p
*** checkm8 exploit by axi0mX ***
Found: CPID:8010 CPRV:11 CPFM:03 SCEP:01 BDID:08 ECID:000A201422E10026 IBFL:3C SRTG:[iBoot-2696.0.0.1.33]
Device is now in pwned DFU Mode.
(0.96 seconds)

成功之后即可在电脑的【关于本机】-> 【系统报告】的USB设备详细信息中看到手机的USB序列号已经被更改:

image

然后即可dump固件:

  sudo ./ipwndfu --dump-rom
Saved: SecureROM-t8010si-2696.0.0.1.33-ROMRELEASE.dump

可以与https://securerom.fun/这里下载的固件进行比对,经测试,固件是一致的。

漏洞分析

iBoot源码泄露事件

这是一切的开始。

让我们来看一条2018年2月8日的新闻:史上最大源码泄露事件:iOS 关键源代码被匿名公布在 GitHub 上,再来看看当时的中国网民怎么说:

可见大部分网民还是吃瓜,因为不懂不了解,也就无法明白这份代码对于理解并破解iPhone的重要性。可以这么说,此次iboot源码的泄露是黑客发现checkm8这个漏洞的起点。但是苹果当时的回应是:iOS 9源代码被泄露 苹果:该源代码已过时 不必担忧。我们事后诸葛亮的来看这个事,可以说是大型打脸现场了,因为泄露的代码至今仍然没有过时。当年苹果公司说他们不在乎,泄露的都是过时的老代码,没有价值,可是他们当时是怎么做的呢?GitHub泄露苹果iBoot源代码?苹果:全网删,谢谢。真的都是江湖人,江湖事呀。那这份泄露的代码在哪呢?虽然在github找到不到了,不过,互联网是有记忆的,网民是万能的:

这份泄露的代码主要是iBoot,相当于PC的BIOS层面的代码,不是做底层的程序员一般是看不明白。不过我们大概也猜到了,这些代码主要负责的就是iPhone的启动过程。启动,你会想到什么呢?

iPhone的操作模式

刚才的两个小实验中,我们将iPhone经过按键的操作进入了DFU模式,其实iPhone还有一种模式叫恢复模式,这些称之为iPhone的操作模式:

其实我们在其他设备上也有类似的操作,比如Android的recovery、fastboot、9008,PC的BIOS配置,Windows的安全模式,Mac的恢复模式等。这些操作都可以理解为进入了一个小系统,这些小系统可能为主系统的运行提供一些必要的支持,也可能作为备用系统以防主系统遭遇不测。我们一般通过在开机过程中按照顺序或者时间的要求按下一些按键,进入这些小系统。换句话说我们没有成功启动主系统,而启动了小系统,对,就是启动。那么这里每一个小系统都有着对应的代码实体,iPhone的DFU和恢复模式的代码实体又在哪呢?是不是iBoot呢?带着这个疑问让我们来看一下,苹果公司泄露的代码能不能回答这个问题。

泄露源码分析

当我打开泄露的源码,大致浏览了一下目录,我惊呆了:

➜  tree -N -L 2
.
├── Makefile
├── apps
│   ├── EmbeddedIOP
│   ├── SecureROM
│   └── iBoot
├── arch
│   ├── arm
│   └── arm64

原来泄露的不只有iBoot,还有SecureROM!其实认真看苹果源码泄露事件的国外报道:Breakthrough: iBoot And SecureROM Source Code Has Leaked, Could Lead To Permanent Bootrom iPhone Jailbreak,他们是明确说了iBoot和SecureROM(也就是BootROM)的代码都泄露了,只不过是国内的媒体都只说了iBoot。接下来就是优秀源码阅读时间,不过无论是iBoot还是SecureROM,都是那种天地初开之时的底层代码。对于陌生的代码,可以从代码的运行顺序,目录结构,编译方法,文档说明,对比同类代码,以及他人的分析文章等方面综合理解。

利用understand工具分析,当进入DFU时,基本的初始化过程如图:

image

/drivers/usb/usb_core.c

image

接下来就是DFU的回调函数

DFU模块的UAF

USB基础

身为安全研究员我们是更喜欢看见一条条实在的报文,根据网上的资料了解到USB协议还是相当复杂的,简单的可以认为USB的传输的报文结构是分层的:一个transfer(传输)由一个或多个transaction(事务)构成,一个transaction(事务)由一个或多个packet(包)构成,一个packet(包)由一个或多个sync(域)构成。

  1. USB的数据通讯首先是基于传输(transfer)的,传输的类型有:中断传输、批量传输、同步传输、控制传输。
  2. 一次传输由一个或多个事务(transaction)构成,事务可以分为:in事务、out事务、setup事务。
  3. 一个事务由一个或多个包(packet)构成,包可分为:令牌包(setup)、数据包(data)、握手包(ack)、特殊包。
  4. 一个包由多个域构成,域可分为:同步域(sync)、标识域(pid)、地址域(addr)、端点域(endp)、帧号域(fram)、数据域(data)、校验域(crc)。

image

漏洞利用

破解iPhone

越狱

解锁

调试

JTAG相关