在QEMU中引导MacOS Apple硅核

2020-11-12 08:48:04

我在QEMU中引导MacOS 11.0.1测试版1内核的arm64e内核,直到启动。它完全没有用,但如果你想知道Apple Silicon Mac如何引导,它可能会很有趣。

运行qemu:./aarch64-softmu/qemu-system-aarch64-M virt-cpu max\-内核/路径/to/bootcache-arm64e\-dtb/path/to/DeviceTree_iPad_Pro_iOS_14.0_b3_Modified.dtb\-monitor stdio-m 6G-s-S-d unimp,mmu\-串口文件:/dev/stdout-串口文件:/dev/stdout-串口文件:/dev/stdout\-append";-noProgress cs_forcement_Disable=1 AMFI_GET_OUT_OF_MY_WAY=1 NVRAM-LOG=1 DEBUG=0x8 kextlog=0xffff io=0xfff Serial=0x7 CPU=1 rd=md0 apcie=0xffffffff";\-initrd/path/to/ios14.0b3/ramdisk.dmg$@。

绝对不支持任何东西:从字面上讲,只有内核和串口可以工作,甚至用户空间都不能工作,因为没有磁盘驱动程序。

最重要的是,即使我曾经设法完全引导MacOS内核,模仿MacOS无论如何也是没用的。

我能想到的效仿MacOS的理由只有三个:安全研究、没有真正的苹果硅机的软件开发,以及哈金托什(Hackintoshing)。这种方法对所有这些都无济于事:

当越狱不可用时,模拟iOS对于安全研究非常有用。Apple Silicon Mac已经支持内核调试。

对软件开发人员没有用处:QEMU的CPU仿真不支持Apple Silicon特定的特性,比如Rosetta的内存排序或APRR JIT。

至于hackintosh:MacOS使用的CPU指令还不能在非Apple ARM CPU上使用,所以你不能进行硬件加速虚拟化,只能进行非常慢的仿真。此外,Hackintoshes通常是在苹果自己的硬件速度不够快的情况下构建的;在这种情况下,苹果的ARM处理器已经是业内速度最快的处理器之一。

我研究这个并不是因为它实用,而只是为了了解苹果的Silicon Mac是如何工作的。这永远不会是一辆时间列车:只会是一次科学实验。

在iOS上,内核及其kext被打包到一个称为内核缓存的可引导文件中。

与iOS kernelcache一样,它包含引导所需的所有kext,因此引导加载程序只需将其加载到内存中并跳转到内存中即可。

它手动排除一些kext,因为它们会导致kmutil出错。大多数是因为它们依赖于ACPI,而ACPI在苹果硅片上是不可用的。我写了一个脚本来检测他们。

在MacOS11Beta3上调试kmutil故障很容易,因为它删除了整个NSError消息。然而,在MacOS 11.0.1测试版上,苹果决定隐藏完整的错误信息,只打印错误代码。我不得不禁用SIP,并在swft_errorRetain上设置断点来查找底层错误。

一旦build_arm64e_kcache.sh运行,就会在~/kcache_out/bootcache-arm64e处创建一个Boot Kext Collection,它可以在QEMU中引导。

为了进行调试,我还必须在Ghidra中反汇编新创建的Boot Kext Collection。

遗憾的是,Ghidra没有针对MacOS 11进行更新,因此将拒绝加载该文件,首先会给出一个关于XML DOCTYPE的错误,然后-一旦解决了这个问题-LC_BUILD_VERSION LOAD命令中的无效nTools值会引发IOException。

我创建了一个脚本来修复kext集合,以便Ghidra可以加载它。

请注意,这仍然不是完美的-Ghidra仍然不能修复指针或读取符号。

为了获得方法名,我还反汇编了原始内核文件(/system/Library/kernels/kernel.relase.t8020)以供交叉引用。请注意,原始内核位于不同的地址--您可以在Ghidra中重新设置它的基地址,或者只需小心转换地址即可。

我已经有了一个经过修改的QEMU来引导iOS内核(这激励了其他公司,比如Aleph Security,来构建更好的开源iOS仿真平台)。

2019年初,我更新了我修改后的QEMU,以便与iPhone Xs/XR的PAC一起工作。

那时QEMU已经支持PAC指令;但是,Apple在实现PAC时修改了加密算法,因此内核无法引导。

我决定把PAC指令变成无操作指令,因为我不知道苹果的算法是如何工作的。这也使得调试内核变得更容易。

与iOS类似,Apple Silicon上的MacOS使用设备树向内核描述硬件,并传递引导参数。

MacOS11.0.1测试版的安装程序没有包含DTK的设备树:我怀疑它可能在.ipsw文件中,而这些文件并未公开提供。取而代之的是,我借用了iOS 14 Beta 3中iPad Pro的设备树。

与QEMU实验中的IOS一样,我首先禁用了设备树中除串口以外的所有硬件。

NVRAM,否则在读取随机数种子时会出现空指针死机。(我从BAZAD的iPhone设备树转储中复制了NVRAM。)。

我不能实际引导MacOS根文件系统,因为我没有模拟硬盘。

我也没有恢复磁盘:它可能只包含在DTK IPSW中,它不是公开的。

相反,我决定使用iOS内存磁盘引导以测试内核,并使用gdb断点禁用签名检查。

我也无法获得Trustcache(内核信任的可执行文件列表)来加载。我试着遵循Aleph Security的指导,但MacOS11比iOS 12更严格,需要在内核下使用它;我找不到正确的内存地址。

实际上,我从8月9日就准备好了这篇博文,但我花了额外的3个月的时间来解决问题,因为我真的想至少找到一个外壳!

我想等到苹果发布A14内核,而不是DTK的A12内核,这样我们就可以看看虚拟化是如何工作的,但他们从来没有这么做。

现在是11月9日,苹果公司明天将举行新闻发布会:所以,要么现在,要么永远不会。

我可能不会在这方面做更多的工作,但以下是人们可以做的,让它成为一个真正有用的研究平台:

编写基本驱动程序/仿真:可能会在QEMU中仿真AIC(基于Project SandCastle的Linux驱动程序),因为自定义中断控制器Kext很难编写。

移植苹果旧的PowerPC PCIe驱动程序,因为要模仿Apple Silicon PCIe控制器太难了。这将允许我们连接虚拟硬盘。

在苹果发布Apple Silicon Mac时切换到A14内核,这样我们就可以测试虚拟化了