ios 代码设置启动页_在VIM3开发板上运行无修改的iOS内核镜像

2fc7ff819095877a57ebd0aa16570a2a.png

之前在网上有看到过人使用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都记录下来的话,理论上只需要把相关的实现代码移植过来,就可以跑起来。但往往情况会比较复杂,所以一定要有个可以调试的工具做支持,故采取以下思路
  1. 使用ARM DS5作为调试工具,DS5是ARM官方出品的一款非常强大的ARM架构的集成开发调试工具,用户可以免费申请一个30天的试用
  2. 前期在ARM FVP上进行调试,在FVP跑通后基本上可以直接移植到VIM3上

IOS OTA文件选择

苹果从A7芯片开始使用64位的ARMv8架构,以下是苹果每一代芯片的一些基本信息

c493f78b73c92b6b44d957e101768a52.png

苹果的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提到的有差异

  1. secure monitor - 由于我们会使用虚拟机的形式启动ios内核,所以这里我们将在hypervisor中模拟相关SMC调用和一些寄存器的访问模拟
  2. trust cache - Afek教程里面这部分有点复杂,且需要切换到Mac系统(相关工具也提供linux版本,但测试下来不好使),所以选择直接加载recovery ramdisk来作为根文件系统.

按照Afek教程里面的步骤得到以下image

  1. kernel.out MACH-O格式的ios内核镜像
  2. dt.out 设备device tree,IOS内核也是用device tree,但ios 用的device-tree的格式和linux下的格式不太一样,所以无法直接用dtc工具来反编译。Afek教程中的device tree脚本大致作用是把几乎所有外设的compatible字段变为0,不让系统去加载对应驱动,只留下uart和最基本的platform信息,实际上对于前期的调试我们只需要把uart , timer中断驱动起来就可以
  3. ramdisk.out ramdisk镜像

Bootloader

我们要做的第一步工作就是把提取出来的三个image加载到内存当中,也就是我们要实现一个简易的IOS bootloader,IOS使用的是iboot作为bootloader,这部分的代码是不开放的。还好,Zhuowei已经实现了在qemu中加载MACH-O文件的的相关代码,我们只需把qemu中这些代码移植到Minos中就可以,这里有两个方案:

  1. 使用U-boot作为bootloader,在uboot中实现MACH-O文件的解析和加载,把IOS当做Native VM来启动
  2. 使用Minos自带的虚拟机管理程序mvm来启动,启动一个Guest VM

很显然,以上两种方式采用第二种方式会更简单和更以实现,读取文件的操作会更方便,代码主要实现了以下功能

  1. 解析内核文件获取内核的入口地址
  2. 根据内核MACH-O文件提供的内存布局信息计算出ranmdisk,device-tree,bootarg的地址
  3. 加载内核镜像到对应内存区域
  4. 设置内核启动参数,和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中相关代码了解到:

  1. xnu中system tick timer使用了FIQ并没有使用irq方式
  2. 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的模拟,只需要稍微做些改动就可以,具体改动有两个:

  1. 把中断类型从irq改成fiq
  2. 添加代码实现清中断动作

串口

最后为了查看内核输出的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

d44c0d6021b65ad3eb1a79290a428daa.png

通过以上信息我们可以看到所有镜像均已加载成功,内核的入口地址为0x470a5098,我们在这个地址上设置个断点

a83db19df30536e5739808a221c163ff.png

通过反汇编且结合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这个函数后

8302b002d2279321a0ac005ae81b557d.png

通过反复研究反汇编和和已有的内核代码发现,这个函数其实就是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架构提供这个支持

  1. 把HCR_EL2中的28位置1
  2. 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有了输出

6be92d64770f6a3590ec9bc1e120d7b6.png

但是panic了,报指令不支持,通过反汇编发现是执行sha256指令上,难道ARM FVP没有实现sha256相关指令

a8b0365a991bc358c2c80cd87f853e50.png

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。

38351c9bbf4622a8479f121839598c58.png

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

b2aeb02bc7a0ecc52d6cfb37a1b1f06c.png

但系统没有任何输出,也没有panic,说明系统卡在某处或者等待某个事件或者信号。

总结

由于在开发板上没有有效的调试工具和方法,当前进展停在这里,后面还想往下调试的话,暂时只能等ARM FVP上SHA256指令问题解决掉,可以用DS进行单步等。IOS内核起来了,如果能拿到一些device的spec,可以进行更多设备的模拟,理论上在普通armv8设备跑ios也不是没有可能。这个实验倒对arm架构有个更深的了解,并且掌握一些逆向调试的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值