之前在网上有看到过人使用QEMU成功的把IOS内核运行起来且成功挂载根文件系统的相关文章。理论上能在QEMU上跑成功,在真实的ARMv8开发板上运行起来也不是问题。本着研究IOS内核启动流程以及IOS 内核相关安全措施的目的,经过一个多星期的研究和调试,终于成功的把IOS内核通过虚拟化的方式在Khadas VIM3开发板上跑起来了,以下记录了下调试过程中碰到的一些问题。
准备和开发阶段
调试环境搭建
IOS使用的是xnu内核,当前苹果已经开源了xnu源码(但和A系列芯片的相关驱动代码都没有开放),具体源码可以在以下Github仓库中找到:https://github.com/apple/darwin-xnu.git
以下是在QEMU上实验的一些文章,通过以下文章可以了解到很多关于XNU及IOS启动的基本知识,可以直接享用牛人的研究成果,避免重复造车轮子:
Zhuowei : https://worthdoingbadly.com/xnuqemu2/
Jonathan Afek:https://alephsecurity.com/2019/06/25/xnu-qemu-arm64-2/
以上文章写的非常的详细,每个系列都分为两篇,第一篇介绍怎么做,第二批记录了碰到的问题以及问题如何解决的,两位牛人都提供了很多工具用来从IOS升级包中提取所需要的固件。
接下来将介绍基于Zhuowei和Afek的研究成果基础之上,把IOS内核通过Hypervisor运行到Khadas VIM3开发板上的过程,首先第一步是搭建基本的调试环境:
- Hypervisor使用的是Minos -https://github.com/minosproject/minos 一款功能非常强大的嵌入式虚拟化解决方案,同时是个支持多核的实时操作系统
- 由于IOS解压出来的内核文件保留的内核symbol越来越少,且留下来的symbol对调试几乎没有帮助,基本上都是syscall的地址,如果所有的问题已经被Zhuowei和Afek都记录下来的话,理论上只需要把相关的实现代码移植过来,就可以跑起来。但往往情况会比较复杂,所以一定要有个可以调试的工具做支持,故采取以下思路
- 使用ARM DS5作为调试工具,DS5是ARM官方出品的一款非常强大的ARM架构的集成开发调试工具,用户可以免费申请一个30天的试用
- 前期在ARM FVP上进行调试,在FVP跑通后基本上可以直接移植到VIM3上
IOS OTA文件选择
苹果从A7芯片开始使用64位的ARMv8架构,以下是苹果每一代芯片的一些基本信息
苹果的SOC的每次升级换代还是挺快的,且紧跟最新的ARM指令集,最新的SOC采用了ARMv8.3指令集。由于当前下载的DS5自带的模拟器只支持ARMv8.0指令集(事实上当前市面上的开发板也都是ARMv8.0指令集,包括VIM3),所以只能选择前三个,这里我选择了Apple Typhoon,也就是Apple A8处理器,Iphone 6使用的就是A8处理器,因此从以下地址下载了Iphone 6 IOS 12.2的固件做为调试固件
http://updates-http.cdn-apple.com/2019SpringFCS/fullrestores/041-06917/ECD402F4-499F-11E9-85D3-E64576CE070F/iPhone_4.7_12.2_16E227_Restore.ipsw
按照Jonathan Afek第一篇文章里面的教程,下载相关脚本,得到所需要的image。这里没有完全使用教程里面提到的所有image,有两个image和Afek提到的有差异
- secure monitor - 由于我们会使用虚拟机的形式启动ios内核,所以这里我们将在hypervisor中模拟相关SMC调用和一些寄存器的访问模拟
- trust cache - Afek教程里面这部分有点复杂,且需要切换到Mac系统(相关工具也提供linux版本,但测试下来不好使),所以选择直接加载recovery ramdisk来作为根文件系统.
按照Afek教程里面的步骤得到以下image
- kernel.out MACH-O格式的ios内核镜像
- dt.out 设备device tree,IOS内核也是用device tree,但ios 用的device-tree的格式和linux下的格式不太一样,所以无法直接用dtc工具来反编译。Afek教程中的device tree脚本大致作用是把几乎所有外设的compatible字段变为0,不让系统去加载对应驱动,只留下uart和最基本的platform信息,实际上对于前期的调试我们只需要把uart , timer中断驱动起来就可以
- ramdisk.out ramdisk镜像
Bootloader
我们要做的第一步工作就是把提取出来的三个image加载到内存当中,也就是我们要实现一个简易的IOS bootloader,IOS使用的是iboot作为bootloader,这部分的代码是不开放的。还好,Zhuowei已经实现了在qemu中加载MACH-O文件的的相关代码,我们只需把qemu中这些代码移植到Minos中就可以,这里有两个方案:
- 使用U-boot作为bootloader,在uboot中实现MACH-O文件的解析和加载,把IOS当做Native VM来启动
- 使用Minos自带的虚拟机管理程序mvm来启动,启动一个Guest VM
很显然,以上两种方式采用第二种方式会更简单和更以实现,读取文件的操作会更方便,代码主要实现了以下功能
- 解析内核文件获取内核的入口地址
- 根据内核MACH-O文件提供的内存布局信息计算出ranmdisk,device-tree,bootarg的地址
- 加载内核镜像到对应内存区域
- 设置内核启动参数,和command line
为了减少在移植过程中尽可能少的出现问题,这里我给VM非配了和iphone6一样多的内存也就是1G
用1G内存这个配置在实际调试过程中碰到了一个问题,由于VIM3 官方Android镜像使用的还是32位,且没有打开LPAE模式,为了模拟这个情况,ARM FVP也是使用的32位非LPAE模式,由于32位下进程的地址空间只有4G,默认情况下mvm会把VM的内存空间全部映射到自己的进程空间内,这就意味着要在mvm这个进程中找到一段1G连续虚拟地址空间,这个情况几乎不太容易满足。为此,通过修改mvm和hypervisor实现了映射VM特定区域到内存空间的功能,用多少映射多少。bootloader的具体实现可以参考https://github.com/minosproject/minos/blob/master/tools/mvm/os/os_xnu.c
Hypervisor中XNU操作系统的支持
xnu系统启动要求bootloader需要把启动参数传递给内核,通过阅读xnu arm64的启动代码,发现这块的处理比较简单,只需要把内核启动参数的硬件地址存放到x0寄存器就可以,xnu arm64的启动代码可以参照https://github.com/apple/darwin-xnu/blob/master/osfmk/arm64/start.s,启动参数的定义如下,启动参数的设置可以参考mvm中的相关代码
struct xnu_arm64_boot_args {
uint16_t revision; /* Revision of boot_args structure */
uint16_t version; /* Version of boot_args structure */
uint64_t virt_base; /* Virtual base of memory */
uint64_t phys_base; /* Physical base of memory */
uint64_t mem_size; /* Size of memory */
uint64_t top_of_kdata; /* Highest physical address used in kernel data area */
struct xnu_arm64_boot_video video; /* Video Information */
uint32_t machine_type; /* Machine Type */
uint64_t dtb; /* Base of flattened device tree */
uint32_t dtb_length; /* Length of flattened tree */
char cmdline[XNU_ARM64_BOOT_LINE_LENGTH]; /* Passed in command line */
uint64_t boot_flags; /* Additional flags specified by the bootloader */
uint64_t mem_size_actual; /* Actual size of memory */
};
在Minos中添加了https://github.com/minosproject/minos/blob/master/virt/os/os_xnu.c文件用来支持xnu虚拟机的启动
中断控制器支持
苹果A系列处理器并没有使用ARM的GIC系列,而是自己的AIC,搜遍了整个XNU代码只发现了AIC的头文件定义,头文件中也只定义了相关的寄存器偏移,这下糟了,不了解AIC的终端控制器原理,中断信息怎么发送给虚拟机?还好通过查看前面两篇文章,以及xnu中相关代码了解到:
- xnu中system tick timer使用了FIQ并没有使用irq方式
- xnu中对于FIQ处理简单粗暴,压根不需要操作AIC
void
sleh_fiq(arm_saved_state_t *state)
{
unsigned int type = DBG_INTR_TYPE_UNKNOWN;
#if DEVELOPMENT || DEBUG
int preemption_level = get_preemption_level();
#endif
#if MONOTONIC
uint64_t pmsr = 0, upmsr = 0;
#endif /* MONOTONIC */
#if MONOTONIC
if (mt_pmi_pending(&pmsr, &upmsr)) {
type = DBG_INTR_TYPE_PMI;
} else
#endif /* MONOTONIC */
if (ml_get_timer_pending()) {
type = DBG_INTR_TYPE_TIMER;
}
sleh_interrupt_handler_prologue(state, type);
#if MONOTONIC
if (type == DBG_INTR_TYPE_PMI) {
mt_fiq(getCpuDatap(), pmsr, upmsr);
} else
#endif /* MONOTONIC */
{
/*
* We don't know that this is a timer, but we don't have insight into
* the other interrupts that go down this path.
*/
cpu_data_t *cdp = getCpuDatap();
cdp->cpu_decrementer = -1; /* Large */
/*
* ARM64_TODO: whether we're coming from userland is ignored right now.
* We can easily thread it through, but not bothering for the
* moment (AArch32 doesn't either).
*/
rtclock_intr(TRUE);
}
sleh_interrupt_handler_epilogue();
#if DEVELOPMENT || DEBUG
if (preemption_level != get_preemption_level())
panic("fiq type %u changed preemption level from %d to %d", type, preemption_level, get_preemption_level());
#endif
}
整个FIQ的处理只有一个大函数,代码中ml_get_timer_pending就是用来判断是否有timer pending,实现也很简单,通过读取CNTP_CTL寄存器然后判断ISTATUS位来判断是否有timer终端pending,这样实现的原因可能和整个IOS/MAC的软件架构及安全有关。AIC驱动被实现为一个kext。
因为在最开始阶段我们只需要一个timer中断,所以在Minos中对AIC的支持很简单,只需要实现给内核发送FIQ就可以,这个可以通过设置HCR_EL2的VFI标志来完成,具体实现可以参考https://github.com/minosproject/minos/blob/master/virt/virq_chips/vaic.c
Timer支持
和中断控制器一样,对于timer的支持也放在了hypervisor里面,IOS也使用了ARM架构的标准timer,但很不幸使用的是 Physical Timer而没有使用Virtual Timer,幸好Minos已经有对Physical timer的模拟,只需要稍微做些改动就可以,具体改动有两个:
- 把中断类型从irq改成fiq
- 添加代码实现清中断动作
串口
最后为了查看内核输出的log,我们还需要实现一个虚拟的串口设备,ios内核使用了三星的串口IP,相关代码可以在xnu源码中找到,串口的模拟放在了mvm中来实现,当前只实现了最基本的打log功能,具体代码在https://github.com/minosproject/minos/blob/master/tools/mvm/devices/s3c_uart.c文件中
ARM-FVP调试阶段
通过以上工作,我们有了需要的image以及支持IOS内核的基础环境代码,万事俱备只欠东风,接下来我们将进行第一阶段在ARM-FVP的调试,通过以下命令我们可以启动VM
./mvm vcpus=1 memory=1024M vm_name=ios12 tc_file=tc.out kernel_image=kernel.out dtb_image=dt.out ramdisk_image=ramdisk.out os-64bit vm_os=xnu run_as_daemon debug_enable cmdline="debug=0x8 kextlog=0xfff cpus=1 rd=md0 serial=2" device@s3c_uart
通过以上信息我们可以看到所有镜像均已加载成功,内核的入口地址为0x470a5098,我们在这个地址上设置个断点
通过反汇编且结合xnu的start.S对比发现,第一条指令是一样的,在单步几条指令之后也能对上,说明我们的bootloader功能是ok的。
16K页表支持
在ARM FVP上碰到的第一个问题就是,内核挂在了mmu配置,只要已开启MMU系统就挂,后来发现内核配置的TCR_EL1的内如如下
#define TCR_EL1_BASE (TCR_IPS_40BITS |
TCR_SH0_OUTER | TCR_ORGN0_WRITEBACK | TCR_IRGN0_WRITEBACK | (T0SZ_BOOT << TCR_T0SZ_SHIFT) | (TCR_TG0_GRANULE_SIZE) |
TCR_SH1_OUTER | TCR_ORGN1_WRITEBACK | TCR_IRGN1_WRITEBACK | (TCR_TG1_GRANULE_SIZE))
内核使用了16K的页表,这个难道FVP不支持,通过寄存器发现,默认情况下ARM FVP确实不支持16K页表,需要在启动参数中添加以下参数
-C cluster0.has_16k_granule=1
CPACR_EL1寄存器的处理
解决了页表的问题,继续运行,发现串口还是没有log输出,又挂了,通过单步以及各种调试手法(不得不说在没有任何symbol下去逆向一个软件确实非常难)发现系统只要访问了SMID以及浮点寄存器就挂了,后发现CPACR_EL1初始化为0,也就是EL1和EL0都无法访问浮点模块,这个简单,直接在hypervisor中把CPACR_EL1的寄存器值配置位0x300000就可以。但后面想想事情绝对没有这么简单,终于在网上搜到了这篇文章
Tick (FPU) Tock (IRQ) https:// xerub.github.io/ios/kpp /2017/04/13/tick-tock.html
原来IOS在通过secure monitor使用浮点模块实现了一套内核保护机制,内核相关代码可在xnu的源码找到。这意味着我们需要在Minos中去模拟整个流程,但想想既然直接把值配置位0x300000能绕过去就先用着吧,以后有时间再说
DC ZVA指令模拟
在解决以上两个问题之后,感觉胜利就在眼前,但是内核再次hang住,通过反复调试发现每次hang都是在执行完0xfffffff0070996c0这个函数后
通过反复研究反汇编和和已有的内核代码发现,这个函数其实就是xnu内核中的bzero函数,且这个函数的实现逻辑是:会判断要被bzero的大小是否是64字节的整数倍,如果是的话就调用dc zva指令对直接操作cache,那么每次dc zva操作的大小就是64个字节,dc zva操作的大小会在DCZID_EL0寄存器中指明,而xnu内核并没有去判断DCZID_EL0的值,使用固定的64字节,在ARM FVP中大小为8,也就是2的8次方256次方,这就导致实际上每次DC ZVA执行的大小是256字节,这就导致执行这条指令会把不该清零的内存区域也清零了。
所以这里我们需要对DC ZVA指令进行模拟,还好arm v8架构提供这个支持
- 把HCR_EL2中的28位置1
- Hypervisor中添加如下代码
static int apple_soc_dczva_trap(struct vcpu *vcpu, unsigned long va)
{
unsigned long pa = guest_va_to_pa(va, 0);
memset((void *)pa, 0, ASOC_DCZVA_SIZE);
return 0;
}
SHA256指令支持
看来调试的道路困难重重,但是解决了DC ZVA问题之后,感觉马上就要成功了,因为通过跟踪代码发现处理架构相关的代码基本上跑完了,实际情况也确实如此,终于kernel log有了输出
但是panic了,报指令不支持,通过反汇编发现是执行sha256指令上,难道ARM FVP没有实现sha256相关指令
FVP命令行参数显示
minle@minle-Z840:/usr/local/DS-5_v5.27.0/bin$ ./FVP_Base_AEMv8A --list-params | grep sha256
cluster0.cpu0.crypto_sha256=0x1 # (int , init-time) default = '0x1' : SHA-256 instructions supported (requires CryptoPlugin to be loaded).
CryptoPlugin是什么东西,在网上没有搜到任何信息
VIM3开发板硬件调试阶段
sha256指令问题在ARM FVP上实在绕不过去,没办法只能直接上硬件了,手上有好几块开发板,发现只有espressobin和VIM3是支持sha256指令的,树莓派4尽然不支持,因为vim3是pro版本,有4G内存所以选择VIM3 Pro做为实验平台。这里推荐下这块开发板,个人认为做工和软硬件开放层度比树莓派4好很多。另外一个就是Minos已经支持VIM3且支持Android。
Trust Cache
在VIM3上运行首次运行的log,比我预期的结果要好,可以直接打印log
console:/sdcard # sync
console:/sdcard # sh ios.sh
[WARN ] argment format wrong: device
console:/sdcard # [INFO ] os is 64bit
[DEBUG] MACH-O magic: 0xfeedfacf
[DEB[ 54.300207@00 070] INF add slab mem : 0xeb858fc8 : 0x38 to slab
[ 54.306680@00 070] WRN destroy host mapping 0x4d6c2c30---->0x4d6c2cb0
UG] MACH-O cpu_type: 0x100000c
[DEBUG] MACH-O cpu_sub_type: 0x0
[[ 54.320308@00 070] WRN PMD block remap 0xbe800000 ---> 0xbe800000 @0x200000
[ 52.944986@0] register event-9 irq-34
[ 54.331017@00 070] INF vm_mmap start:0x80000000 size:0x7800000
[ 52.956727@0] vm-1 map 0xb4200000 -> 0x80000000 size:0x7800000
[ 52.960375@0] vma flags is 0x40404fb
DEBUG] MACH-O file_type: 2
[DEBUG] MACH-O nr_cmds: 22
[DEBUG] MACH-O size_of_cmds: 4120
[DEBUG] MACH-O flags: 0x200001
[INFO ] xnu entry address is 0xfffffff0070a5098
[INFO ] xnu kernel_load_base 0xfffffff005c6c000
[INFO ] xnu ramdisk_load_base 0xfffffff0079ec000
[INFO ] xnu dtb_load_base 0xfffffff00d0b0000
[INFO ] xnu bootarg_load_base 0xfffffff00d0d0000
[INFO ] xnu tc cache load base 0x45a00000
[INFO ] xnu tc cache load size 0x0
[INFO ] xnu memory map start 0x45a00000
[INFO ] xnu memory map size 0x7800000
[NIC ] create new vm *
[NIC ] -name : ios12
[NIC ] -os_type : xnu
[NIC ] -nr_vcpu : 1
[NIC ] -bit64 : 1
[NIC ] -mem_size : 0x40000000
[NIC ] -mem_base : 0x40000000
[NIC ] -entry : 0x470a5098
[NIC ] -setup_data : 0x4d0d0000
[INFO ] create s3c uart
[NIC ] vm-1 0x45a00000@0x7800000 mmap to 0xb4200000
[INFO ] load image: 0xb5e88000 0x1c88000 0x610000 0x62ee0
[INFO ] load image: 0xb5fe0000 0x1de0000 0x1b00000 0x0
[INFO ] load image: 0xb5fe0000 0x1de0000 0x1b00000 0x0
[INFO ] load image: 0xb55f8000 0x13f8000 0x1800000 0x20c000
[INFO ] load image: 0xb5eec000 0x1cec000 0x1a0c000 0xf4000
[INFO ] load image: 0xb4910000 0x710000 0xb18000 0xce8000
[INFO ] load image: 0xb5fe0000 0x1de0000 0x1b00000 0x20c000
[INFO ] load image: 0xb446c000 0x26c000 0x674000 0x4a4000
[INFO ] load image: 0xb5e70000 0x1c70000 0x5f8000 0x18000
[INFO ] load image: 0xb5dc8000 0x1bc8000 0x5c4000 0x34000
[INFO ] memset for 0xfffffff0075fc000 ---> 0x74000
[INFO ] load image: 0xb5dc4000 0x1bc4000 0x5c0000 0x4000
[INFO ] load image: 0xb5dc0000 0x1bc0000 0x5bc000 0x4000
[INFO ] load image: 0xb5898000 0x1698000 0x94000 0x528000
[INFO ] load image: 0xb5878000 0x1678000 0x74000 0x20000
[INFO ] load image: 0xb5804000 0x1604000 0x0 0x74000
[INFO ] load image: 0xb61ec000 0x1fec000 0x0 0x56c1a1b
[INFO ] load image: 0xbb8b0000 0x76b0000 0x0 0x1d460
[INFO ] xnu bootarg revision - 2
[INFO [ 55.315938@01 071] NIC vm-1 vcpu-0 affnity to pcpu-4
[ 55.320908@01 071] NIC vmpidr is 0x0
] xnu bootarg version - 2
[INFO ] xnu bootarg virtbase - 0xfffffff000000000
[INFO ] xnu bootarg physbase - 0x40000000
[INFO ] xnu bootarg mem_size - 0x40000000
[INFO ] xnu bootarg tok - 0x4d0e0000
[INFO ] xnu bootarg dtb - 0xfffffff00d0b0000
[INFO ] xnu bootarg dtb_size - 0x1d460
[INFO ] xnu bootarg cmdline - debug=0x8 kextlog=0xfff cpus=1 rd=md0 serial=2
[INFO ] set timer freq to 0x16e3600
iBoot version:
corecrypto_kext_start called
[cckprng] Yarrow PRNG initialized with SHA-256.
FIPSPOST_KEXT [1681736303] fipspost_post:156: PASSED: (0 ms) - fipspost_post_integrity
FIPSPOST_KEXT [1681896878] fipspost_post:162: PASSED: (0 ms) - fipspost_post_hmac
FIPSPOST_KEXT [1682187479] fipspost_post:163: PASSED: (0 ms) - fipspost_post_aes_ecb
FIPSPOST_KEXT [1682332977] fipspost_post:164: PASSED: (0 ms) - fipspost_post_aes_cbc
FIPSPOST_KEXT [1683811646] fipspost_post:165: PASSED: (54 ms) - fipspost_post_rsa_sig
FIPSPOST_KEXT [1684205414] fipspost_post:166: PASSED: (11 ms) - fipspost_post_ecdsa
FIPSPOST_KEXT [1684403124] fipspost_post:167: PASSED: (3 ms) - fipspost_post_ecdh
FIPSPOST_KEXT [1684501485] fipspost_post:168: PASSED: (0 ms) - fipspost_post_drbg_ctr
FIPSPOST_KEXT [1684798990] fipspost_post:169: PASSED: (0 ms) - fipspost_post_aes_ccm
FIPSPOST_KEXT [1684926962] fipspost_post:171: PASSED: (0 ms) - fipspost_post_aes_gcm
FIPSPOST_KEXT [1685053206] fipspost_post:172: PASSED: (0 ms) - fipspost_post_aes_xts
FIPSPOST_KEXT [1685190366] fipspost_post:173: PASSED: (0 ms) - fipspost_post_tdes_cbc
FIPSPOST_KEXT [1685325675] fipspost_post:174: PASSED: (0 ms) - fipspost_post_drbg_hmac
FIPSPOST_KEXT [1685466407] fipspost_post:197: all tests PASSED (156 ms)
AUC[<ptr>]::init(<ptr>)
AUC[<ptr>]::probe(<ptr>, <ptr>)
AppleCredentialManager: init: called, instance = <ptr>.
ACMRM: init: called, EN=YES, KB_OBS=YES.
ACMRM: _loadRestrictedModeForceEnable: restricted mode force-enabled = 0 .
ACMRM-A: init: called, .
ACMRM-A: _loadAnalyticsCollectionPeriod: analytics collection period = 86400 .
Darwin Image4 Validation Extension Version 1.2.0: Tue Mar 5 19:43:52 PST 2019; root:AppleImage4-1.250.8~181/AppleImage4/RELEASE_ARM64
ACMRM: _loadStandardModeTimeout: standard mode timeout = 259200 .
ACMRM-A: notifyStandardModeTimeoutChanged: called, value = 259200 (modifpanic(cpu 0 caller 0xfffffff0070efb0c): "No external trust cache found (region len is 0)."
"thread_invoke: preemption_level 1, possible cause: blocking while holding a spinlock, or within interrupt context"panic(cpu 0 caller 0xfffffff0070efb0c): "No external trust cache found (region len is 0)."
"thread already waiting on 0xffffffe0151f20d0"panic(cpu 0 caller 0xfffffff0070efb0c): "No external trust cache found (region len is 0)."
"thread already waiting on 0xffffffe0151f20d0"panic(cpu 0 caller 0xfffffff0070efb0c): "No external trust cache found (region len is 0)."
"hw_lock_bit(): timed out (0xffffffe0007837a0)"panic(cpu 0 caller 0xfffffff0070efb0c): "No external trust cache found (region len is 0)."
[ 62.732559@0] fb: mem_free_work, free memory: addr:800000
但是内核panic了,通过panic提示找到原因"No external trust cache found (region len is 0)",看来之前省掉的trust cache image是不能省的,通过Afek的文章中了解到如果要执行非apple签名的程序需要把hash值存放在trust cache中,所以理论上trust cache可以是空,但需要有个header信息。所以随便制作了一个trust cache文件,然后在mvm中添加trust cache文件的支持
成功挂载Ramdisk根文件系统
在上面这个问题解决之后,根文件系统终于成功挂载
console:/sdcard #
console:/sdcard #
console:/sdcard #
console:/sdcard # [ 39.897686@2] aml_tdm_open
[ 39.897717@2] Not init audio effects
[ 39.904385@2] asoc-aml-card auge_sound: tdm playback enable
[ 40.168019@0] dhd_bus_rxctl: resumed on timeout, INT status=0x20800040
console:/sdcard # sn[ 51.678628@0] type=1400 audit(1581514285.360:53): avc: denied { search } for pid=3350 comm="memtrack@1.0-se" name="3351" dev="proc" ino=692 scontext=u:r:hal_memtrack_default:s0 tcontext=u:r:hal_neuraln1
[ 51.694791@2] type=1400 audit(1581514291.472:65): avc: denied { open } for pid=4918 comm="Binder:4918_1" path="/sys/block" dev="sysfs" ino=11626 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=dir p1
[ 51.719042@0] type=1400 audit(1581514291.472:65): avc: denied { open } for pid=4918 comm="Binder:4918_1" path="/sys/block" dev="sysfs" ino=11626 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=dir p1
[ 51.736136@0] type=1400 audit(1581514291.512:66): avc: denied { open } for pid=4918 comm="Binder:4918_1" path="/proc/bus/pci/devices" dev="proc" ino=4026532039 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:proc:s1
[ 51.758148@0] type=1400 audit(1581514291.512:66): avc: denied { open } for pid=4918 comm="Binder:4918_1" path="/proc/bus/pci/devices" dev="proc" ino=4026532039 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:proc:s1
[ 51.779750@0] type=1400 audit(1581514291.512:67): avc: denied { getattr } for pid=4918 comm="Binder:4918_1" path="/proc/bus/pci/devices" dev="proc" ino=4026532039 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:pro1
[ 51.815128@3] type=1400 audit(1581514291.512:67): avc: denied { getattr } for pid=4918 comm="Binder:4918_1" path="/proc/bus/pci/devices" dev="proc" ino=4026532039 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:pro1
[ 51.831734@3] type=1400 audit(1581514291.608:68): avc: denied { read } for pid=4918 comm="Binder:4918_1" name="stat" dev="proc" ino=16245 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:r:zygote:s0 tclass=file permissive=1
[ 51.851425@3] type=1400 audit(1581514291.608:68): avc: denied { read } for pid=4918 comm="Binder:4918_1" name="stat" dev="proc" ino=16245 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:r:zygote:s0 tclass=file permissive=1
[ 51.870675@3] type=1400 audit(1581514291.608:69): avc: denied { open } for pid=4918 comm="Binder:4918_1" path="/proc/3330/stat" dev="proc" ino=16245 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:r:zygote:s0 tclass=file pe1
console:/sdcard #
console:/sdcard #
console:/sdcard #
console:/sdcard #
console:/sdcard # ls
Alarms Music aarch64-boot.img iphone6s n71.dt.out
Android Notifications backup kernel.out ramdisk.out
DCIM Pictures boot32.img minicom.sh tc.out
Download Podcasts dt.out mvm32-old.sh
Movies Ringtones ios.sh mvm32.sh
console:/sdcard # sh ios.sh
[WARN ] argment format wrong: device
console:/sdcard # [INFO ] os is 64bit
[DEBUG] MACH-O magic: 0xfeedfacf
[DEBUG][ 63.712283@00 070] INF add slab mem : 0xeb858fc8 : 0x38 to slab
[ 63.718681@00 070] WRN destroy host mapping 0x49ec2c30---->0x49ec2cb0
MACH-O cpu_type: 0x100000c
[DEBUG] MACH-O cpu_sub_type: 0x0
[DEBUG] MACH-O file_type: 2
[DEBUG] MACH-O nr_cmds: 22
[DEBUG] MACH-O size_of_cmds: 4120
[DEBUG] MACH-O flags: [ 63.743532@03 073] WRN PMD block remap 0xbe800000 ---> 0xbe800000 @0x200000
[ 62.368080@3] register event-10 irq-34
[ 63.754047@03 073] INF vm_mmap start:0x80000000 size:0x8600000
[ 62.377950@3] vm-1 map 0xb3800000 -> 0x80000000 size:0x8600000
[ 62.383651@3] vma flags is 0x40404fb
0x200001
[INFO ] xnu entry address is 0xfffffff0070a5098
[INFO ] xnu kernel_load_base 0xfffffff005c6c000
[INFO ] xnu ramdisk_load_base 0xfffffff0079ec000
[INFO ] xnu dtb_load_base 0xfffffff00dfc0000
[INFO ] xnu bootarg_load_base 0xfffffff00dfe0000
[INFO ] xnu tc cache load base 0x45a00000
[INFO ] xnu tc cache load size 0xc54
[INFO ] xnu memory map start 0x45a00000
[INFO ] xnu memory map size 0x8600000
[NIC ] create new vm *
[NIC ] -name : ios12
[NIC ] -os_type : xnu
[NIC ] -nr_vcpu : 1
[NIC ] -bit64 : 1
[NIC ] -mem_size : 0x40000000
[NIC ] -mem_base : 0x40000000
[NIC ] -entry : 0x470a5098
[NIC ] -setup_data : 0x4dfe0000
[INFO ] create s3c uart
[NIC ] vm-1 0x45a00000@0x8600000 mmap to 0xb3800000
[INFO ] load image: 0xb5488000 0x1c88000 0x610000 0x62ee0
[INFO ] load image: 0xb55e0000 0x1de0000 0x1b00000 0x0
[INFO ] load image: 0xb55e0000 0x1de0000 0x1b00000 0x0
[INFO ] load image: 0xb4bf8000 0x13f8000 0x1800000 0x20c000
[INFO ] load image: 0xb54ec000 0x1cec000 0x1a0c000 0xf4000
[INFO ] load image: 0xb3f10000 0x710000 0xb18000 0xce8000
[INFO ] load image: 0xb55e0000 0x1de0000 0x1b00000 0x20c000
[INFO ] load image: 0xb3a6c000 0x26c000 0x674000 0x4a4000
[INFO ] load image: 0xb5470000 0x1c70000 0x5f8000 0x18000
[INFO ] load image: 0xb53c8000 0x1bc8000 0x5c4000 0x34000
[INFO ] memset for 0xfffffff0075fc000 ---> 0x74000
[INFO ] load image: 0xb53c4000 0x1bc4000 0x5c0000 0x4000
[INFO ] load image: 0xb53c0000 0x1bc0000 0x5bc000 0x4000
[INFO ] load image: 0xb4e98000 0x1698000 0x94000 0x528000
[INFO ] load image: 0xb4e78000 0x1678000 0x74000 0x20000
[INFO ] load image: 0xb4e04000 0x1604000 0x0 0x74000
[INFO ] load image: 0xb57ec000 0x1fec000 0x0 0x65d3400
[ 62.695443@0] fb: mem_free_work, free memory: addr:800000
[INFO ] load image: 0xbbdc0000 0x85c0000 0x0 0x1d460
[ 64.858749@00 070] NIC vm-1 vcpu-0 affnity to pcpu-4
[ 64.863760@00 070] NIC vmpidr is 0x0
[INFO ] xnu bootarg revision - 2
[INFO ] xnu bootarg version - 2
[INFO ] xnu bootarg virtbase - 0xfffffff000000000
[INFO ] xnu bootarg physbase - 0x40000000
[INFO ] xnu bootarg mem_size - 0x40000000
[INFO ] xnu bootarg tok - 0x4dff0000
[INFO ] xnu bootarg dtb - 0xfffffff00dfc0000
[INFO ] xnu bootarg dtb_size - 0x1d460
[INFO ] xnu bootarg cmdline - debug=0x8 kextlog=0xfff cpus=1 rd=md0 serial=2
[INFO ] set timer freq to 0x16e3600
iBoot version:
corecrypto_kext_start called
[cckprng] Yarrow PRNG initialized with SHA-256.
FIPSPOST_KEXT [1931917382] fipspost_post:156: PASSED: (0 ms) - fipspost_post_integrity
FIPSPOST_KEXT [1932094315] fipspost_post:162: PASSED: (0 ms) - fipspost_post_hmac
FIPSPOST_KEXT [1932239773] fipspost_post:163: PASSED: (0 ms) - fipspost_post_aes_ecb
FIPSPOST_KEXT [1932384284] fipspost_post:164: PASSED: (0 ms) - fipspost_post_aes_cbc
FIPSPOST_KEXT [1933855582] fipspost_post:165: PASSED: (54 ms) - fipspost_post_rsa_sig
FIPSPOST_KEXT [1934278598] fipspost_post:166: PASSED: (11 ms) - fipspost_post_ecdsa
FIPSPOST_KEXT [1934498218] fipspost_post:167: PASSED: (3 ms) - fipspost_post_ecdh
FIPSPOST_KEXT [1934620988] fipspost_post:168: PASSED: (0 ms) - fipspost_post_drbg_ctr
FIPSPOST_KEXT [1934753970] fipspost_post:169: PASSED: (0 ms) - fipspost_post_aes_ccm
FIPSPOST_KEXT [1934879471] fipspost_post:171: PASSED: (0 ms) - fipspost_post_aes_gcm
FIPSPOST_KEXT [1935001951] fipspost_post:172: PASSED: (0 ms) - fipspost_post_aes_xts
FIPSPOST_KEXT [1935182014] fipspost_post:173: PASSED: (0 ms) - fipspost_post_tdes_cbc
FIPSPOST_KEXT [1935272353] fipspost_post:174: PASSED: (0 ms) - fipspost_post_drbg_hmac
FIPSPOST_KEXT [1935362535] fipspost_post:197: all tests PASSED (144 ms)
AUC[<ptr>]::init(<ptr>)
AUC[<ptr>]::probe(<ptr>, <ptr>)
AppleCredentialManager: init: called, instance = <ptr>.
ACMRM: init: called, EN=YES, KB_OBS=YES.
ACMRM: _loadRestrictedModeForceEnable: restricted mode force-enabled = 0 .
ACMRM-A: init: called, .
Darwin Image4 Validation Extension Version 1.2.0: Tue Mar 5 19:43:52 PST 2019; root:AppleImage4-1.250.8~181/AppleImage4/RELEASE_ARM64
ACMRM-A: _loadAnalyticsCollectionPeriod: analytics collection period = 86400 .
ACMRM: _loadStandardModeTimeout: standard mode timeout = 259200 .
ACMRM-A: notifyStandardModeTimeoutChanged: called, value = 259200 (modified = YES).
ACMRM: _loadGracePeriodTimeout: device lock timeout = 3600 .
ACMRM-A: notifyGracePeriodTimeoutChanged: called, value = 3600 (modified = YES).
ACMRM: _mapAndPublishTRM: set TRM_PolicyTimeout = 259200.
ACMRM: _mapAndPublishTRM: set TRM_GracePeriodTimeout = 3600.
ACMRM: _mapAndPublishTRM: sending kIOMessageServicePropertyChange(2): TRM: 259200 -/ff 3600 -/ff CUR: 259200 -/ff 3600 -/ff.
AppleCredentialManager: init: returning, result = true, instance = <ptr>.
AUC[<ptr>]::start(<ptr>)
AppleKeyStore starting (BUILT: Mar 7 2019 22:27:50)
AppleSEPKeyStore::start: _sep_enabled = 1
AppleCredentialManager: start: called, instance = <ptr>.
ACMRM: _publishIOResource: AppleUSBRestrictedModeTimeout = 259200.
AppleCredentialManager: start: initializing power management, instance = <ptr>.
AppleCredentialManager: start: started, instance = <ptr>.
AppleCredentialManager: start: returning, result = true, instance = <ptr>.
[ 112.327571@0] nf_conntrack: default automatic helper assignment has been turned off for security reasons and CT-based firewall rule not found. Use the iptables CT target to attach helpers instead.
AppleARMPE::getGMTTimeOfDay can not provide time of day: RTC did not show up
: apfs_module_start:1393: load: com.apple.filesystems.apfs, v945.250.134, apfs-945.250.134, 2019/03/05
com.apple.AppleFSCompressionTypeZlib kmod start
IOSurfaceRoot::installMemoryRegions()
IOSurface disallowing global lookups
apfs_sysctl_register:929: done registering sysctls.
com.apple.AppleFSCompressionTypeZlib load succeeded
L2TP domain init
L2TP domain init complete
PPTP domain init
BSD root: md0, major 2, minor 0
apfs_vfsop_mountroot:1549: apfs: mountroot called!
apfs_vfsop_mount:1279: unable to root from devvp <ptr> (root_device): 2
apfs_vfsop_mountroot:1553: apfs: mountroot failed, error: 2
hfs: mounted PeaceB16B92.arm64CustomerRamDisk on device b(2, 0)
但是系统永远地停在了这里,理论上接下来会启动lanchd进程,并打印以下log
: : Darwin Bootstrapper Version 6.0.0: Tue Oct 16 22:26:06 PDT 2018; root:libxpc_executables-1336.220.5~209/launchd/RELEASE_ARM64
boot-args = debug=0x8 kextlog=0xfff cpus=1 rd=md0 serial=2
但系统没有任何输出,也没有panic,说明系统卡在某处或者等待某个事件或者信号。
总结
由于在开发板上没有有效的调试工具和方法,当前进展停在这里,后面还想往下调试的话,暂时只能等ARM FVP上SHA256指令问题解决掉,可以用DS进行单步等。IOS内核起来了,如果能拿到一些device的spec,可以进行更多设备的模拟,理论上在普通armv8设备跑ios也不是没有可能。这个实验倒对arm架构有个更深的了解,并且掌握一些逆向调试的方法。