【问题标题】:ARM64 - assembly branch to function addressARM64 - 汇编分支到函数地址
【发布时间】:2017-07-25 17:01:32
【问题描述】:

我在使用 arm64 内联汇编从 LKM 中将 64 位地址加载到寄存器时遇到问题。

我正在尝试在内核内存中设置一个函数挂钩。因此,每次调用特定函数时,它都应该分支到我的函数。

我的想法是将地址加载到寄存器中,这是在使用此运行时获得的:

unsigned long address = &hooked_do_undefinstr;

然后编写相应的OPCode

BLR X3

进入记忆。

我尝试将地址加载到寄存器 X3(因为它是 64 位操作系统)

__asm__ __volatile__ ( "MOV x3, %[var]" : [var] "=r" (address));

因为我必须在运行时获取地址,所以我不能使用 LDR 命令。插入模块时出现以下错误:

root@___ :~# insmod mod_init.ko 
[   70.386938] mod_init: Unknown symbol x19 (err 0)
[   70.391508] mod_init: Unknown symbol x3 (err 0)

使用此命令,我打印 X3 内容时的输出为零:

[  558.948492]          MOV x3 Register value 0x0

我现在的问题是,有没有办法将 64 位地址加载到寄存器中? 或者有没有更好的方法来实现我的函数挂钩以便跳转到我的地址?

问候并感谢您的帮助

【问题讨论】:

    标签: assembly hook cpu-registers arm64


    【解决方案1】:

    您在做什么并不完全清楚。如果你想挂钩一个函数,你不能只是把你的blr x3 放在那里并期望x3 保持你在别处使用内联汇编设置的值(除非你知道它没有在任何地方被触及,但我发现这不太可能) .您需要将x3 加载代码也放入挂钩函数中,这样可以工作:

    ldr x3, .+8
    blr x3
    

    使用汇编程序创建机器码给出:43 00 00 58 60 00 3F D6

    修补时,您的代码应在末尾附加目标地址:

    void patch(unsigned char* target)
    {
        unsigned char code[] = { 0x43, 0x00, 0x00, 0x58, 0x60, 0x00, 0x3F, 0xD6 };
        memcpy(target, code, 8);
        *(void (**)())(target + 8) = hooked_do_undefinstr;
    }
    

    还请注意,您覆盖的任何内容都应由您的钩子函数补偿。像往常一样,您还需要确保您正在修补的部分是可写的。

    【讨论】:

    • 感谢您的回答。我没想到,寄存器可以被覆盖。我已经禁用了内存写保护并为我正在覆盖的代码创建了一个备份。此外,我必须将您的十六进制代码转换为小端。使用您的代码,我必须(从原始条目中)保存两个命令的 8 个字节加上地址的 8 个字节,对吗?但我正在尝试这个。再次感谢
    • 编辑:我刚刚检查并看到您的 OPCode 已经是 little endian
    • 有时您需要使用BR 而不是BLR,因为后者会将PC(跳转后)的值设置回PC + 4
    【解决方案2】:

    我能够通过使用@Jester 的想法解决这个问题。

    请注意,如果您使用他的代码,请检查您的系统是运行小端还是大端。这可以通过以下方式完成:

    //Get the SCTLR_EL1 content
    __asm__ __volatile__ ( "MRS %[result], SCTLR_EL1" : [result] "=r" (sctlr_el1));
    
    //Check the 25th bit. if 1 -> big, else little
    if(sctlr_el1 & (1<<25))
    {
        printk(KERN_INFO "          Big Endian Found\n");
        create_hook_big(addresse);
    }else
    {
        printk(KERN_INFO "          Little Endian found\n");
        create_hook_little(addresse);
    }
    

    否则:这是我的工作代码:

    //Backup original entries
    memcpy(original_blr, (void*)el1_sync,sizeof(original_blr));
    
    
    //Set function hook, el1_sync is my used target
    memcpy((void*)el1_sync,replace_jump_offset,sizeof(replace_jump_offset));
    *(void (**)(void))(el1_sync + 8) = &hooked_do_undefinstr;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多