使用PongoOS读取苹果ARM64 CPU功能支持寄存器

前言

苹果自A6开始采用定制CPU核心,A7是全球第一款使用64位ARM的处理器。苹果CPU性能一直领先高通,必有一定的原因。通过读取ARM64 ID registers,或许能侧面揭晓一些答案。

PongoOS

自2019年checkm8漏洞公开以来,很快有大神们利用该漏洞制作了checkra1n越狱工具,为了方便地支持A7-A11多个硬件平台,多个iOS版本,checkra1n实现了一个Preboot environment,名为PongoOS,一个简易的操作系统。

checkra1n运行时利用checkm8将PongoOS注入iBoot,PongoOS通过内存Hook劫持iBoot,利用iBoot初始化平台,并在iBoot执行末尾启动自身,Pongo启动后加载KPF(Kernel Patch Finder)内核模块,KPF会patch掉内存中的iOS内核。

PongoOS目前已经开源,可以当作苹果硬件的实验环境使用。

编译启动PongoOS

在修改PongoOS之前,需要能够编译PongoOS,能够使用checkra1n启动iPhone。

PongoOS源码:

https://github.com/checkra1n/pongoOS

支持macOS和Linux编译,根据官方readme,macOS下编译会简单一些:

  • Install Xcode + command-line utilities
  • Run make all

需要安装Xcode及其命令行工具。(命令行工具只需要在终端里运行git等命令就会自动弹出来)

先跑一遍make all,build下应该生成Pongo.bin,安装checkra1n后可通过以下命令启动:

/Applications/checkra1n.app/Contents/MacOS/checkra1n -c -p -k ./build/Pongo.bin

接下来

cd scripts/

make

会生成pongoterm工具,通过它就可以通过USB和iPhone上的PongoOS shell交互了。

一切准备就绪以后,可以修改Pongo源码,在pongo shell里添加读取ARM64寄存器的命令了。

 

读取ARM64功能支持寄存器

打开 src/shell/main.c, 在shell_main函数以前加入读寄存器的命令:

void read_aa64_ids_cmd(const char* cmd, char* args) {
//PongoOS有一个command handler,用户输入的命令和参数会以char*传递给相应命令处理函数
//也就是说,需要自己解析args(不过这里并不需要)

    uint64_t id; //要读的寄存器是64位的
    __asm__("mrs %0, ID_AA64ISAR0_EL1" : "=r" (id) : : );//通过内联asm读取寄存器
    iprintf("ID_AA64ISAR0_EL1 is %llx\n", id);

    __asm__("mrs %0, ID_AA64ISAR1_EL1" : "=r" (id) : : );
    iprintf("ID_AA64ISAR1_EL1 is %llx\n", id);

    __asm__("mrs %0, ID_AA64MMFR0_EL1" : "=r" (id) : : );
    iprintf("ID_AA64MMFR0_EL1 is %llx\n", id);

    __asm__("mrs %0, ID_AA64MMFR1_EL1" : "=r" (id) : : );
    iprintf("ID_AA64MMFR1_EL1 is %llx\n", id);

    __asm__("mrs %0, ID_AA64MMFR2_EL1" : "=r" (id) : : );
    iprintf("ID_AA64MMFR2_EL1 is %llx\n", id);

    __asm__("mrs %0, ID_AA64PFR0_EL1" : "=r" (id) : : );
    iprintf("ID_AA64PFR0_EL1 is %llx\n", id);
}

然后在shell_main函数里注册刚添加的命令:

void shell_main() {
    /*
        Load command handler
    */

    extern void task_list(const char *, char*);
    //注册read_aa64_ids_cmd函数,命令名aa64id
    command_register("aa64id", "Read AArch64 ID registers", read_aa64_ids_cmd);
    command_register("panic", "calls panic()", panic_cmd);

保存main.c,再次make all 生成Pongo.bin,再次通过checkra1n命令启动。

结果

在PongoOS shell中执行我们新添加的命令,即可读取苹果CPU的支持状态了。

我在A7(iPhone 5S)和A10(iPhone 7)上测试了读取:

A7:

pongoOS> aa64id
ID_AA64ISAR0_EL1 is 1110 //支持基本AES, SHA2, SHA1
ID_AA64ISAR1_EL1 is 0 //无支持
ID_AA64MMFR0_EL1 is 11021 //36 bits, 64GB物理地址 16 bits.ASID , EL3/1不支持BigEnd, EL0支持BigEnd, 支持SNSMem, 支持4KB和64KB内存页表
ID_AA64MMFR1_EL1 is 0 //无支持
ID_AA64MMFR2_EL1 is 0 //无支持
ID_AA64PFR0_EL1 is 1012 //EL3,EL1仅AArch64, EL0可AArch64或AArch32, 未实现EL2

A10:

pongoOS> aa64id
ID_AA64ISAR0_EL1 is 10011120 //支持AES(PMULL/PMULL2), SHA2, SHA1, CRC32, FEAT_RDM , 不支持原子操作指令(违反Armv8.1规范)
ID_AA64ISAR1_EL1 is 0 //无支持
ID_AA64MMFR0_EL1 is f0100001//36 bits, 64GB物理地址 8 bits.ASID, 不支持SNSMem, 不支持BigEnd,支持16KB和64KB内存页表
ID_AA64MMFR1_EL1 is 111000 //支持Hierarchical Permission Disables,LORegions,Privileged Access Never(均Armv8.1强制要求)
ID_AA64MMFR2_EL1 is 0 //无支持
ID_AA64PFR0_EL1 is 12 //EL1仅AArch64, EL0可AArch64或AArch32, 未实现EL3,EL2

其中A7兼容Armv8.0-A,A10 Armv8.1-A。(真的完全兼容吗?)

通过上面的读取结果,可以看到:

1.苹果的ARM64处理器A7开始就不支持EL2(虚拟化),最近的M1/A14X因为要在mac上用才开始支持(且仅支持VHE模式,因为macOS只用这个模式)

2.苹果不使用ARM TrustZone实现加密敏感的操作,而是通过一个独立的SEP实现。但是在A7-A9上,为了实现KPP(Kernel Patch Protection),苹果使用了EL3。

而自A10开始,苹果使用了更加可靠的KTRR及其演进版本APRR代替KPP,于是苹果在A10里立刻砍掉了EL3支持。

3.A7和A10都使用了36bits物理地址。(已经完全够用了)

4.在A7中部分支持的大端模式已经在A10彻底砍掉。

5.因为不用EL3(TrustZone),A10没有SNSMem安全内存标识。

6.A7中的16bits ASID在A10变成了8bits(也够用了)

7.A10中砍掉了4KB内存页表支持,添加了16KB页表支持

这是iPhone7上很难运行安卓,(目前)不能运行Win10的原因之一。很多人讨论4KB和16KB的优劣,苹果应该是测试发现16KB在iPhone场景效率更高一些。

8.A10的结果可以看到,其中有明显违反ARM规范的地方。事实上1中仅支持VHE也是违反ARM specs的。

9.A7开始就不支持32bit EL1(仅支持64位操作系统)

综合来看,苹果因为掌握App Store的控制权,很容易要求开发者按照相应的规范适配,更不用考虑运行macOS/iOS体系以外的软件,因此也就没有安卓/Windows那么重的历史包袱,想要放弃一些CPU功能很容易(例如32位支持)。

因此苹果的原则就是,仅保留需要用的CPU功能,多余的使劲砍,需要用的不断优化,自然开销更低,效率也会高一些。

还有一个疑问:从A10返回结果来看,EL0支持AArch32模式(32位),但是不知为何在Project Sandcastle的readme里写道iPhone 7上的安卓不支持32位apk。

参考

Arm Armv8-A Architecture Registers

https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值