标题 | 简介 | 类型 | 公开时间 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
详情 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[SAFE-ID: JIWO-2024-584] 作者: ecawen 发表于: [2017-09-07]
本文共 [403] 位读者顶过
Tick (FPU) Tock (IRQ)与iOS9一起推出的内核完整性保护又称为“KPP”,这对于arm64越狱带来了新的问题。 在修补内核代码(通常在较旧的越狱中)之后,一般要不了多久,设备就会panic。 很明显,有些东西会检查内核代码。 这个东西在内核之外,不断地管理和监视着内核。 到目前为止,我仍然感到惊讶的是,没人对KPP写点什么。 至少到现在我都没看到。 所以,我将尝试解释虚拟管理程序如何工作。 具体的实施细节可能会在稍后的时间提供,只要我有时间。现在,不浪费时间了我们开始吧。 第1部分(设置)KPP位于一个Mach-O可执行文件,附加在压缩的内核块之后,在kernelcache img4内。 iBoot加载KPP的镜像,将其加载到0x4100000000,并在EL3中运行。 EL3_start(monitor_boot_args *mba) 这结构体有如下几项
KPP调用_start(NULL)在0x4100000000来覆盖自己的Mach-O头,并安装了两个异常处理程序sync_handler和irq_handler。 回想一下AArch64异常表:
ExceptionVector具有两个处理程序的位置 接下来,它解析内核及其kexts(来自__PRELINK_INFO)
最后,如果被启用 它始终设置下面的寄存器
EL1内核在EL1中开始执行
monitor_call()将升级到EL3到管理程序的sync_handler EL3sync_handler:
当出现问题时,FAIL(代码)设置一个全局变量,并通过以下方式向内核发出信号:
代码含义
然后往下调用SError返回到内核的ExceptionTable中:
否则,如果一切是正常的,就在monitor_call()之后,在内核中执行恢复操作。[出自:jiwo.org] 第二部分 (the ticking)同时在用户空间运行代码,当FPU指令被执行后,CPACR_EL1.FPEN==1会产生一个内核陷阱。 EL1
在内核中,fleh_synchronous() fleh_irq() fleh_fiq() 和 fleh_serror() 所有都会这样结束 EL3sync_handler:
如果所有的检查都通过的话,管理程序就会禁用FPU陷阱(允许FPU最终执行)使得IRQ执行到EL3(确保再次命中),在CPACR_EL1命中后恢复内核然后等待。 EL1内核和用户空间愉快的运行着。当下一次IRQ触发时,就由EL3 IRQ的管理程序接管。 EL3irq_handler:
也就是说:重置IRQs到EL1,重新启动FPU陷阱,重新启动CPACR_EL1访问的陷阱,这些是最后的4步,然后会一直重复。 *总结:KPP总是确保FPU陷阱且不会被禁用。当FPU命中,内核就会尝试禁用陷阱但同时也会由KPP接管。然后KPP运行检查,释放FPU,运行IRQs本身。只要任何IRQ触发,就会使FPU进入内核陷阱并结束IRQs 这是保持虚拟管理程序跳动的引擎。 如果你修改触发器,即CPACR_EL1访问,则FPU无法执行。 但是,有一个catch。 我们可以“窃取”CPACR_EL1单独访问:
|