微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 XNU 内核上补丁查找某个函数的指针的最佳方法是什么?

如何解决在 XNU 内核上补丁查找某个函数的指针的最佳方法是什么?

我目前正在开发适用于 iOS 13.7 的 iOS 越狱。 作为越狱的一部分,我需要对内存中的 xnu 内核进行一系列补丁。 当然,内核受到 kASLRKPP / KTRR 和其他内存看门狗的保护,如果某些内容修改,则会触发内核恐慌。 幸运的是,KTRR(仅内核文本就绪区域)只能保护不应该更改的静态数据(即 TEXT 部分和常量)。变量仍然可以改变。

我正在构建一个 PatchFinder,它应该根据指示符号在 xnu 内存中定位一个函数或变量,我想知道什么是最有效的方法

我目前正在通过 in7egal 在 iOS 8 时代的 PatchFinder made publicly available 上进行调整,如下所示:

uint32_t find_cs_enforcement_disable_amfi(uint32_t region,uint8_t* kdata,size_t ksize)
{
    // Find a function referencing cs_enforcement_disable_amfi
    const uint8_t search_function[] = {0x20,0x68,0x40,0xF4,0x70,0x20,0x60,0x00,0x90,0xBD};
    uint8_t* ptr = memmem(kdata,ksize,search_function,sizeof(search_function));
    if(!ptr)
        return 0;

    // Only LDRB in there should try to dereference cs_enforcement_disable_amfi
    uint16_t* ldrb = find_last_insn_matching(region,kdata,(uint16_t*) ptr,insn_is_ldrb_imm);
    if(!ldrb)
        return 0;

    // Weird,not the right one.
    if(insn_ldrb_imm_imm(ldrb) != 0 || insn_ldrb_imm_rt(ldrb) > 12)
        return 0;

    // See what address that LDRB is dereferencing
    return find_pc_rel_value(region,ldrb,insn_ldrb_imm_rn(ldrb));
}

我想知道是否有任何更快或更可靠的方法来定位 cs_enforcement_disable_amfi

一旦被 xnu Kernel 内存中的 PatchFinder 发现,它的使用方式如下:

uint32_t cs_enforcement_disable_amfi = find_cs_enforcement_disable_amfi(kernel_base,ksize);
    printf("cs_enforcement_disable_amfi is at=0x%08x\n",cs_enforcement_disable_amfi);
    if (cs_enforcement_disable_amfi){
        char patch[] ="\x00\xbf\x00\xbf\x00\xbf\x00\xbf\x00\xbf";
        kern_return_t kernret = vm_write(proccesstask,cs_enforcement_disable_amfi+kernel_base,patch,sizeof(patch)-1);
        if (kernret == KERN_SUCCESS){
            printf("Successfully patched cs_enforcement_disable_amfi\n");
        }
    }

因此 PatchFinder 必须能够可靠地将指针返回到 cs_enforcement_disable_amfi 否则我会盲目地写入无效(或有效但不同)的地址,这几乎肯定会触发内存损坏。

当前代码在大多数情况下确实返回了一个指向 cs_enforcement_disable_amfi 的有效指针,但在大约 10-15% 的时间内随机使内核恐慌,这意味着它在 10-15% 的时间内返回的地址无效.不知道如何让它更可靠。

解决方法

您要查找的变量已不存在。

第一个片段中的字节组成了 Thumb 指令,这些指令在 32 位内核缓存的 AMFI 中找到此函数:

0x8074ad04      90b5           push {r4,r7,lr}
0x8074ad06      01af           add r7,sp,4
0x8074ad08      0d48           ldr r0,[0x8074ad40]
0x8074ad0a      7844           add r0,pc
0x8074ad0c      0078           ldrb r0,[r0]
0x8074ad0e      0128           cmp r0,1
0x8074ad10      03d1           bne 0x8074ad1a
0x8074ad12      0020           movs r0,0
0x8074ad14      00f04efa       bl 0x8074b1b4
0x8074ad18      30b9           cbnz r0,0x8074ad28
0x8074ad1a      7c69           ldr r4,[r7,0x14]
0x8074ad1c      002c           cmp r4,0
0x8074ad1e      05d0           beq 0x8074ad2c
0x8074ad20      2068           ldr r0,[r4]
0x8074ad22      40f44070       orr r0,r0,0x300
0x8074ad26      2060           str r0,[r4]
0x8074ad28      0020           movs r0,0
0x8074ad2a      90bd           pop {r4,pc}

鉴于魔法常数 0x300 以及 AMFI 的 __TEXT_EXEC 段非常小这一事实,我们可以在其他内核(包括 64 位内核)中轻松找到这一点。
这是在 8.4 版本的 iPhone 5s 上的样子:

0xffffff800268d2e4      f44fbea9       stp x20,x19,[sp,-0x20]!
0xffffff800268d2e8      fd7b01a9       stp x29,x30,0x10]
0xffffff800268d2ec      fd430091       add x29,0x10
0xffffff800268d2f0      f30307aa       mov x19,x7
0xffffff800268d2f4      e8fc1110       adr x8,section.com.apple.driver.AppleMobileFileIntegrity.10.__DATA.__bss
0xffffff800268d2f8      1f2003d5       nop
0xffffff800268d2fc      08054039       ldrb w8,[x8,1]
0xffffff800268d300      a8000037       tbnz w8,0xffffff800268d314
0xffffff800268d304      130100b4       cbz x19,0xffffff800268d324
0xffffff800268d308      680240b9       ldr w8,[x19]
0xffffff800268d30c      08051832       orr w8,w8,0x300
0xffffff800268d310      680200b9       str w8,[x19]
0xffffff800268d314      00008052       mov w0,0
0xffffff800268d318      fd7b41a9       ldp x29,0x10]
0xffffff800268d31c      f44fc2a8       ldp x20,[sp],0x20
0xffffff800268d320      c0035fd6       ret

但是到了 iOS 11 的时候,这个变量已经消失了:

0xfffffff006245d84      f44fbea9       stp x20,-0x20]!
0xfffffff006245d88      fd7b01a9       stp x29,0x10]
0xfffffff006245d8c      fd430091       add x29,0x10
0xfffffff006245d90      f30307aa       mov x19,x7
0xfffffff006245d94      130100b4       cbz x19,0xfffffff006245db4
0xfffffff006245d98      680240b9       ldr w8,[x19]
0xfffffff006245d9c      08051832       orr w8,0x300
0xfffffff006245da0      680200b9       str w8,[x19]
0xfffffff006245da4      00008052       mov w0,0
0xfffffff006245da8      fd7b41a9       ldp x29,0x10]
0xfffffff006245dac      f44fc2a8       ldp x20,0x20
0xfffffff006245db0      c0035fd6       ret

以 iOS 12.0b1 为例,我们可以了解到该函数的签名:

_vnode_check_exec(ucred*,vnode*,label*,componentname*,unsigned int*,void*,unsigned long)

是的,找到这个函数真的很容易:

  1. 查找 AMFI 的 __TEXT_EXEC 细分。
  2. 在其中找到一个 orr wN,wN,0x300

但是除非您破坏内核完整性,否则这对您没有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。