寻找iOS内核符号

上周,谷歌零号项目的伊恩·比尔(Ian Beer)在Twitter上宣布,他将发布一些东西,以帮助任何希望引导iOS 11内核安全性研究的人,通过task_for_pid_0tfp0提供对内核内存的读/写访问。

尽管围绕此公告感到非常兴奋的是有可能进行新的越狱,但我想以此为契机再次花时间在移动安全上。 我过去的大部分经验都是在应用程序级别测试中进行的,但我想深入了解操作系统本身的精髓。

乔纳森·莱文(Jonathan Levin)承诺提供了一个工具包,“对于那些在处理过程中最终获得对kernel_task端口(aka tfp0)的发送权,但又不知道下一步要做什么的人”,这似乎很棒潜水的机会。

贝尔先生的漏洞公告和PoC代码已于昨天发布,非常漂亮。 极好的文档(包括ASCII艺术堆栈示例!),干净,并且相对容易阅读和推理。 我已经准备好开始测试,但是很快遇到了麻烦。 贝尔先生很客气,可以为几种设备添加内核符号,但是我没有打算使用它。 幸运的是,作为该文档的一部分,他提供了有关如何查找符号的详细提示,因此我已准备好应对挑战。

这篇文章的其余部分将逐步介绍我寻找符号的过程,希望它可能对您增加对设备的支持也很有用。 除了未删除的符号外,我没有找到任何其他有关执行此操作的文档,因此我想为其他人员(和我自己)记录此过程。 视乔纳森·莱文(Jonathan Levin)的工具包中的内容而定,这可能不是必需的,但我认为这是一个有趣的学习练习。

查找符号的第一步是获取目标iOS版本的kernelcache 。 我跳到https://ipsw.me/并为我的iPad Mini 2以及已经在symbols.c定义了符号的设备之一下载了11.1.2固件。 拥有已经定义好的固件对确认我用来查找每个符号的过程是否正确非常有帮助,因为我们已经知道该设备应该使用的正确符号。

解压缩.ipsw文件后,我抓住了Levin先生的工具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

9点下来,10点走。 其余部分必须已被剥离(或首先没有像JOP小工具那样标记),因此是时候在IDA Pro中加载kernelcache文件了。 您当然可以为此使用其他反汇编程序,例如Binary Ninja,Hopper或radare2。

在此之前,我们需要解码kernelcache文件。 我从Joshua Wright找到了本指南来准备文件。

  *在十六进制编辑器中打开kernelcache并查找0xFFCFFAEDFE,注意偏移量(435) 
* wget -q
http://nah6.com/%7Eitsme/cvs-xdadevtools/iphone/tools/lzssdec.cpp* g ++ -o lzssdec lzssdec.cpp
* ./lzssdec -o 435 kernelcache.dec#435是将字节计数偏移到0xFFCFFAEDFE标头

首先,我为IDA加载了带有已知符号的固件的内核缓存,以便可以大致了解仍然需要找到的符号的程序集。

接下来最容易找到的是KSYMBOL_RET 。 跳转到已知符号的地址,我看到它是_kalloc_external函数的RET指令。 因此,很容易将我的目标设备内核缓存加载到IDA中,并在相同的功能中找到RET 。 对于其余的内容,我们将需要严重依赖评论中提供的提示。

接下来是KSYMBOL_CPU_DATA_ENTRIES ,提示说是0x6000进入数据段。 在IDA中,我转到“跳转到段”并转到0x6000段的开头,记下了地址,并进行了一些十六进制数学运算以添加0x6000并获取我需要的地址。

我发现的下两个实际上是列表中的最后两个, KSYMBOL_EL1_HW_BP_INFINITE_LOOPKSYMBOL_SLEH_SYNC_EPILOG 。 我在IDA(Shift + F12)中打开了字符串窗口,并搜索了字符串。 双击它们会将我引向参考。

对于第一个,我向下滚动以找到开关盒49,然后抓住地址。

对于第二个,已知符号文件的地址是XREF字符串下方的多个LDP指令中的第一个。

最后一个简单的是KSYMBOL_X21_JOP_GADGET 。 看到所需的指令是MOV X21, X0 ,我在IDA中进行了文本搜索以找到适合我的设备的小工具。

对于我来说,最后五个是最棘手的。 我的搜索没有直接找到注释中提到的参考文献,因此我开始研究发现的地址以及它们与已知地址的比较。 做一些基本的减法可以看出,它们之间的距离,给予或接受都差不多,这至少可以帮助我缩小搜索范围。 我还比较了已知已知地址之间的距离。 例如, VALID_LINK_REGISTERX21_JOP_GADGET仅相隔0x28字节。

因此,我查找并在已知地址记录了汇编指令,然后加载了设备的kernelcache并跳转到KNOWN_ADDRESS + my offset guess ,然后开始在附近寻找这些相同的指令。

一旦我完成了汇编方面的工作,只需在if块中添加以获得对我的设备的支持即可。

最后,将iPad插入笔记本电脑,打开Xcode项目,然后运行!

我为iPad Mini 2 WiFi制作的补丁可在此处获得。

整个过程对我来说是全新的(但是非常有趣!),所以我欢迎对我可能弄错或被误解的事情提供任何反馈,或者如果您知道一种查找其中任何或大部分地址的简便方法(请允许有一种更简单的方法)。 我喜欢学习新的工具和技术,并且很高兴听到它们并更新本文。

谢谢!

编辑 -我的KSYMBOL_WRITE_SYSCALL_ENTRYPOINT错误,因此我以前的“成功”想法还不完全!感谢我的出色同事Etienne的帮助解决问题!)