原文地址:https://medium.com/@cji_/hunting-for-ios-kernel-symbols-e48a446bb00

0x001 前言

上周,Google Project Zero的Ian Beer在Twitter上发文,他将通过task_for_pid_0或tfp0提供对内核内存的读、写访问,以帮助研究人员更深入研究iOS 11内核安全性。

这消息一出,可能人们更多的关注会放在新系统的越狱上面,但我想借此机会再研究一下移动安全。

Ian Beer昨日已将poc代码放在Project Zero的主页上Issue 1417: iOS/MacOS kernel double free due to IOSurfaceRootUserClient not respecting MIG ownership rules,包含有CVE-2016-7612CVE-2016-7633两个漏洞。正当我准备好开始我的工作时,便遇到一个问题。Ian Beer放出来的poc代码中为几个设备添加了内核符号,但这几个设备我手头上并没有。运气比较好,他提供了有关如何找到符号的详细说明。

本文旨在介绍查找iOS符号的过程,因为我没有找到关于如何执行此操作的任何其他文档,因此我想为其他人(以及将来的我自己)记录此过程,希望对你添加对设备的支持也能有所帮助。

0x002 查找内核符号地址

查找符号的第一步是获取目标iOS版本的kernelcache。我是通过访问ipsw.me并下载了我的iPad Mini 2的11.1.2固件,同样也可以下载任何已经在symbols.c中定义了符号的设备。

在解压缩.ipsw文件之后,我下载一份joker工具。这是一个命令行工具,在阅读该工具的帮助页以后,设定好-j和-m选项并处理kernelcache文件,转储所有可用的符号。输出包含我需要的这些符号的地址:

KSYMBOL_OSARRAY_GET_META_CLASS
    KSYMBOL_IOUSERCLIENT_GET_META_CLASS
    KSYMBOL_IOUSERCLIENT_GET_TARGET_AND_TRAP_FOR_INDEX
    KSYMBOL_CSBLOB_GET_CD_HASH
    KSYMBOL_KALLOC_EXTERNAL
    KSYMBOL_KFREE
    KSYMBOL_OSSERIALIZER_SERIALIZE
    KSYMBOL_KPRINTF
    KSYMBOL_UUID_COPY

在用IDA Pro加载kernelcache文件之前,我们还需要解密kernelcache文件。详细的方法可以参考这里:getios10beta1kernelcache.sh

* open kernelcache in a hex editor and look for 0xFFCFFAEDFE, note the offset (435)
* wget -q http://nah6.com/%7Eitsme/cvs-xdadevtools/iphone/tools/lzssdec.cpp
* g++ -o lzssdec lzssdec.cpp
* ./lzssdec -o 435 < kernelcache >kernelcache.dec # 435 is offset byte count to 0xFFCFFAEDFE header

首先,IDA加载解密好的kernelcache文件,kernelcache带有一些已知内核符号,我们可以通过反汇编的结果来大致了解一下iOS内核。

最先找到的是KSYMBOL_RET,跳转到已知符号的地址,这是从_kalloc_external函数返回的RET指令。利用joker转储的符号地址信息很容易在IDA中跳转到对应的地址并且在同一个函数中找到这个RET指令。

接下来是KSYMBOL_CPU_DATA_ENTRIES,其中提示称数据段为0x6000。在IDA中,选择Jump to Segment并转到_data段的开头,将该地址加上0x6000最终得到了我们所需的地址。

接下来的两个地址是KSYMBOL_EL1_HW_BP_INFINITE_LOOPKSYMBOL_SLEH_SYNC_EPILOG,这是ksymbol列表最后两个地址,具体可以看到Ian Beer利用代码里的symbols.h。在IDA中打开了String窗口(Shift + F12)并搜索字符串,双击查看引用。

对于前者,向下阅读代码找到了这段switch case 49语句,并且得到该地址。

对于后者,是字符串引用地址下面几个LDP指令中的第一个。

最后一个就是KSYMBOL_X21_JOP_GADGET,在看到所需的指令是MOV X21,X0后,我在IDA中进行了搜索,以找到我的iPad设备的Gadget。

还剩下的5条内核符号地址是最棘手的,在IDA中搜索并没有找到什么有用的信息,所以我开始查看我找到的地址以及它们与已知地址的比较。再然后,通过对比symbols.h里的符号地址之间的偏移差,我发现几个已经找到的地址之间偏移差基本上都能对应得上。最后,我比较了已知地址与未知地址之间的偏移差,例如,VALID_LINK_REGISTER和X21_JOP_GADGET仅相隔0x28个字节。

接下来,用IDA加载我设备的kernelcache并跳转到KNOWN_ADDRESS + my offset guess,并开始在附近寻找相同的指令。

当找到所有所需内核符号地址,需在poc代码中再添加一个if路径来支持我的设备的。

添加一个prinf()打印出信息,编译运行poc

最后漏洞在我的设备上成功触发。这是复现iOS设备内核漏洞的一般步骤,因为网上贴出来的poc、exp用到的内核符号地址一般与我们手头上的设备不一致,这样往往造成我们无法在本机上触发漏洞。

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖