ARM64 - 汇编分支到函数地址

时间:2017-07-24 11:45:14

标签: assembly hook cpu-registers arm64

我在使用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位地址加载到寄存器中? 或者是否有更好的方法来实现我的函数钩子以跳转到我的地址?

致以问候并感谢您的帮助

2 个答案:

答案 0 :(得分:1)

目前还不完全清楚你在做什么。如果你想挂钩一个功能,你不能只将blr x3放在那里,并期望x3保持你在其他地方使用内联asm设置的值(除非你知道它)没有碰过任何地方,但我觉得不太可能)。您需要将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;
}

另请注意,无论您覆盖的是什么,都应该通过钩子功能进行补偿。像往常一样,您还需要确保要修补的部分是可写的。

答案 1 :(得分:0)

我能够通过使用@ 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;