文章源自略懂百科-http://wswcn.cn/13764.html
Tick (FPU) Tock (IRQ)文章源自略懂百科-http://wswcn.cn/13764.html
与iOS9一起推出的内核完整性保护又称为KPP,这对于arm64越狱带来了新的问题。文章源自略懂百科-http://wswcn.cn/13764.html
有效地观察到,在修补内核代码(通常在较旧的越狱中)之后,设备会一段时间后会静默地恐慌。 很明显,有些东西会检查内核代码。文章源自略懂百科-http://wswcn.cn/13764.html
这个东西在内核之外,很快就显现出一种在工作中的管理程序。文章源自略懂百科-http://wswcn.cn/13764.html
到目前为止,我仍然感到惊讶的是,没有人对KPP进行了一个写作 - 至少没有人知道。 所以,我将尝试解释hypervision如何工作。 具体的实施细节可能会在稍后的时间提供,只要我有时间。现在,不用多说,我们走文章源自略懂百科-http://wswcn.cn/13764.html
第1部分(设置)文章源自略懂百科-http://wswcn.cn/13764.html
KPP位于一个Mach-O可执行文件,紧随压缩内核块之后,在kernelcache img4内。 iBoot刻录出KPP图像,将其加载到0x4100000000,并在EL3中运行文章源自略懂百科-http://wswcn.cn/13764.html
EL3文章源自略懂百科-http://wswcn.cn/13764.html
_start(monitor_boot_args *mba)文章源自略懂百科-http://wswcn.cn/13764.html
这结构体有如下几项文章源自略懂百科-http://wswcn.cn/13764.html
struct monitor_boot_args {文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t version;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t virtBase;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t physBase;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t memSize;文章源自略懂百科-http://wswcn.cn/13764.html
struct kernel_boot_args *kernArgs;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t kernEntry;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t kernPhysBase;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t kernPhysSlide;文章源自略懂百科-http://wswcn.cn/13764.html
uint64_t kernVirtSlide;文章源自略懂百科-http://wswcn.cn/13764.html
};文章源自略懂百科-http://wswcn.cn/13764.html
KPP使用调用_start(NULL)的蹦床来覆盖自己的Mach-O头,0x4100000000,并安装了两个异常处理程序sync_handler和irq_handler。 回想一下AArch64异常表:文章源自略懂百科-http://wswcn.cn/13764.html
ExceptionVector具有两个处理程序的位置文章源自略懂百科-http://wswcn.cn/13764.html
接下来,它解析内核及其kexts(来自__PRELINK_INFO)文章源自略懂百科-http://wswcn.cn/13764.html
saveTEXT,DATA segments to map list文章源自略懂百科-http://wswcn.cn/13764.html
saveTEXT,DATA::__const zones to hash list文章源自略懂百科-http://wswcn.cn/13764.html
最后,如果启用 – which – it(以及其他)以下寄存器文章源自略懂百科-http://wswcn.cn/13764.html
CPACR_EL1 = 0x100000; // CPACR_EL1.FPEN=1, causes instructions in EL0 that use the Floating Point execution to be trapped文章源自略懂百科-http://wswcn.cn/13764.html
CPTR_EL3 = 0x80000000; // CPTR_EL3.TCPAC=1, accesses to CPACR_EL1 will trap from EL2 and EL1 to EL3文章源自略懂百科-http://wswcn.cn/13764.html
SCR_EL3 = 0x631; // SCR_EL3.IRQ=0, When executing at any Exception level, physical IRQ interrupts are NOT taken to EL3文章源自略懂百科-http://wswcn.cn/13764.html
// SCR_EL3.SMD=0, SMC instructions are ENABLED at EL1 and above文章源自略懂百科-http://wswcn.cn/13764.html
// SCR_EL3.SIF=1, Secure state instruction fetches from Non-secure memory are NOT permitted文章源自略懂百科-http://wswcn.cn/13764.html
EL1文章源自略懂百科-http://wswcn.cn/13764.html
内核在EL1中开始执行文章源自略懂百科-http://wswcn.cn/13764.html
_start() => start_first_cpu() => arm_init():文章源自略懂百科-http://wswcn.cn/13764.html
=> cpu_machine_idle_init() => monitor_call(0x800)文章源自略懂百科-http://wswcn.cn/13764.html
=> machine_startup() => kernel_bootstrap() => kernel_bootstrap_thread() => monitor_call(0x801)文章源自略懂百科-http://wswcn.cn/13764.html
_start_cpu() => arm_init_cpu() => cpu_machine_idle_init() => monitor_call(0x800)文章源自略懂百科-http://wswcn.cn/13764.html
monitor_call()将升级到EL3到管理程序的sync_handler文章源自略懂百科-http://wswcn.cn/13764.html
EL3文章源自略懂百科-http://wswcn.cn/13764.html
sync_handler:文章源自略懂百科-http://wswcn.cn/13764.html
if (ESR_EL3 == 0x5E000011) { // ESR_EL3.EC==0x17 && ESR_EL3.IL==1 && ESR_EL3.ISS==0x11 aka "SMC 0x11" aka monitor_call() inside the kernel文章源自略懂百科-http://wswcn.cn/13764.html
switch (arg0) {文章源自略懂百科-http://wswcn.cn/13764.html
case 0x800: // called by cpu_machine_idle_init()文章源自略懂百科-http://wswcn.cn/13764.html
/* save kernel entrypoint */文章源自略懂百科-http://wswcn.cn/13764.html
return ok;文章源自略懂百科-http://wswcn.cn/13764.html
case 0x801: // called by kernel_bootstrap_thread()文章源自略懂百科-http://wswcn.cn/13764.html
if (enabled) {文章源自略懂百科-http://wswcn.cn/13764.html
if (locked) {文章源自略懂百科-http://wswcn.cn/13764.html
FAIL(4);文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
/* do lockdown:文章源自略懂百科-http://wswcn.cn/13764.html
* hash all regions from hash list文章源自略懂百科-http://wswcn.cn/13764.html
* initialize some vars文章源自略懂百科-http://wswcn.cn/13764.html
* save SCTLR_EL1, TCR_EL1, TTBR1_EL1, VBAR_EL1文章源自略懂百科-http://wswcn.cn/13764.html
*/文章源自略懂百科-http://wswcn.cn/13764.html
...文章源自略懂百科-http://wswcn.cn/13764.html
SCR_EL3.SMD=1;文章源自略懂百科-http://wswcn.cn/13764.html
locked = 1;文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
return OK;文章源自略懂百科-http://wswcn.cn/13764.html
case 0x802: // wtf is this shit?文章源自略懂百科-http://wswcn.cn/13764.html
FAIL(5);文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
(to be continued)文章源自略懂百科-http://wswcn.cn/13764.html
当出现问题时,FAIL(代码)设置一个全局变量,并通过以下方式向内核发出信号:文章源自略懂百科-http://wswcn.cn/13764.html
ESR_EL1 = 0xBF575400 | code // ESR_EL1.EC=0x2F, ESR_EL1.ISV=1, ESR_EL1.IS=0x575400|code文章源自略懂百科-http://wswcn.cn/13764.html
代码含义文章源自略懂百科-http://wswcn.cn/13764.html
帧违规文章源自略懂百科-http://wswcn.cn/13764.html
坏系统调用文章源自略懂百科-http://wswcn.cn/13764.html
未锁定文章源自略懂百科-http://wswcn.cn/13764.html
已锁定文章源自略懂百科-http://wswcn.cn/13764.html
软件请求文章源自略懂百科-http://wswcn.cn/13764.html
TTE / PTE无效文章源自略懂百科-http://wswcn.cn/13764.html
违反绘图文章源自略懂百科-http://wswcn.cn/13764.html
违反系统注册文章源自略懂百科-http://wswcn.cn/13764.html
然后,执行再转移到SError回到内核的ExceptionTable中:文章源自略懂百科-http://wswcn.cn/13764.html
SError => fleh_serror() => sleh_serror() => kernel_integrity_error_handler() => panic()文章源自略懂百科-http://wswcn.cn/13764.html
否则,如果一切都会好的,就在monitor_call()之后,执行在内核中恢复。文章源自略懂百科-http://wswcn.cn/13764.html
这是设置阶段,为了让内核设置一次写入内存位置所需的。 接下来,进入心跳阶段文章源自略懂百科-http://wswcn.cn/13764.html
第二部分 (the ticking)文章源自略懂百科-http://wswcn.cn/13764.html
同时在用户空间运行代码,当FPU指令被执行后,CPACR_EL1.FPEN==1会产生一个内核陷阱。文章源自略懂百科-http://wswcn.cn/13764.html
EL1文章源自略懂百科-http://wswcn.cn/13764.html
在内核中,fleh_synchronous()fleh_irq()fleh_fiq()和fleh_serror()所有都会这样结束exception_return_dispatch() => check_user_asts() => MSR CPACR_EL1, X0一旦来自于EL3内核陷阱,CPACR_EL1就会执行。当CPTR_EL3.TCPAC==1时,执行权就转交到EL3sync_handler文章源自略懂百科-http://wswcn.cn/13764.html
EL3文章源自略懂百科-http://wswcn.cn/13764.html
This time, it means business.文章源自略懂百科-http://wswcn.cn/13764.html
sync_handler:文章源自略懂百科-http://wswcn.cn/13764.html
(continued)文章源自略懂百科-http://wswcn.cn/13764.html
else if (ESR_EL3 == 0x62340400) { // ESR_EL3.EC==0x18 && ESR_EL3.IL==1 && ESR_EL3.ISS==0x340400 aka trapped by "MSR CPACR_EL1, X0"文章源自略懂百科-http://wswcn.cn/13764.html
if (violated) {文章源自略懂百科-http://wswcn.cn/13764.html
FAIL(1);文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
if (!locked) {文章源自略懂百科-http://wswcn.cn/13764.html
FAIL(3);文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
if (!(++number_of_hits & watchtower_throttle)) {文章源自略懂百科-http://wswcn.cn/13764.html
if (!(++flip_flop & 1)) {文章源自略懂百科-http://wswcn.cn/13764.html
if (hash_is_ready) {文章源自略懂百科-http://wswcn.cn/13764.html
blake2b_final(&hash, digest);文章源自略懂百科-http://wswcn.cn/13764.html
if (memcmp(cur->digest, digest, 32)) {文章源自略懂百科-http://wswcn.cn/13764.html
FAIL(1);文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
cur = get_next_region();文章源自略懂百科-http://wswcn.cn/13764.html
if (!cur) {文章源自略懂百科-http://wswcn.cn/13764.html
cur = get_first_region();文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
cur_data_ptr = cur->base;文章源自略懂百科-http://wswcn.cn/13764.html
cur_data_left = cur->size;文章源自略懂百科-http://wswcn.cn/13764.html
blake2b_init(&hash);文章源自略懂百科-http://wswcn.cn/13764.html
hash_is_ready = 0;文章源自略懂百科-http://wswcn.cn/13764.html
} else {文章源自略懂百科-http://wswcn.cn/13764.html
chunk = min(cur_data_left, 128);文章源自略懂百科-http://wswcn.cn/13764.html
blake2b_update(&hash, cur_data_ptr, chunk);文章源自略懂百科-http://wswcn.cn/13764.html
cur_data_ptr += chunk;文章源自略懂百科-http://wswcn.cn/13764.html
cur_data_left -= chunk;文章源自略懂百科-http://wswcn.cn/13764.html
if (!cur_data_left) {文章源自略懂百科-http://wswcn.cn/13764.html
hash_is_ready = 1;文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
} else {文章源自略懂百科-http://wswcn.cn/13764.html
/* walk and check TTE/PTE文章源自略懂百科-http://wswcn.cn/13764.html
* verify map list文章源自略懂百科-http://wswcn.cn/13764.html
* check system registers SCTLR_EL1, TCR_EL1, TTBR1_EL1, VBAR_EL1文章源自略懂百科-http://wswcn.cn/13764.html
*/文章源自略懂百科-http://wswcn.cn/13764.html
...文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
ELR_EL3 += 4; // skip insn文章源自略懂百科-http://wswcn.cn/13764.html
CPTR_EL3 = 0; // CPTR_EL3.TCPAC=0, accesses to CPACR_EL1 will not trap from EL2 and EL1 to EL3文章源自略懂百科-http://wswcn.cn/13764.html
CPACR_EL1 = 0x300000; // CPACR_EL1.FPEN=3, does not cause any FPU instruction to be trapped文章源自略懂百科-http://wswcn.cn/13764.html
SCR_EL3 = 0x6B3; // SCR_EL3.IRQ=1, When executing at any Exception level, physical IRQ interrupts are taken to EL3文章源自略懂百科-http://wswcn.cn/13764.html
// SCR_EL3.SMD=1, SMC instructions are UNDEFINED at EL1 and above文章源自略懂百科-http://wswcn.cn/13764.html
// SCR_EL3.SIF=1, Secure state instruction fetches from Non-secure memory are NOT permitted文章源自略懂百科-http://wswcn.cn/13764.html
return OK;文章源自略懂百科-http://wswcn.cn/13764.html
}文章源自略懂百科-http://wswcn.cn/13764.html
EL3.SIF=0, Secure state instruction fetches from Non-secure memory are permitted文章源自略懂百科-http://wswcn.cn/13764.html
也就是说:重置IRQs到EL1,使其重新能够FPU 陷阱,能够处理CPACR_EL1访问的陷阱,最后的4步然后一直重复。文章源自略懂百科-http://wswcn.cn/13764.html
*文章源自略懂百科-http://wswcn.cn/13764.html
总结文章源自略懂百科-http://wswcn.cn/13764.html
KPP确保FPU陷阱且不会被禁用。当FPU命中,内核就会尝试禁用陷阱但同时也会由KPP接管。KPP然后运行检查,释放FPU,运行IRQs本身。只要任何IRQ触发,就会使FPU进入内核陷阱并结束IRQs文章源自略懂百科-http://wswcn.cn/13764.html
这是保持管理程序跳动的引擎。 如果你修改触发器,即CPACR_EL1访问,则FPU无法执行。 但是,有一个catch。 我们可以窃取CPACR_EL1访问单独的蹦床:文章源自略懂百科-http://wswcn.cn/13764.html
取消patch文章源自略懂百科-http://wswcn.cn/13764.html
触发CPACR_EL1,管理程序然后运行恢复执行权文章源自略懂百科-http://wswcn.cn/13764.html
再次patch文章源自略懂百科-http://wswcn.cn/13764.html
profit文章源自略懂百科-http://wswcn.cn/13764.html
这种绕过方式在@qwertyoruiop的yalu102中使用过。文章源自略懂百科-http://wswcn.cn/13764.html
本文由看雪论坛iOS安全小组 OSG ksmokee 原创 转载请注明来自看雪社区文章源自略懂百科-http://wswcn.cn/13764.html
文章源自略懂百科-http://wswcn.cn/13764.html
评论