我在使用arm64内联汇编从LKM中将64位地址加载到寄存器时遇到了问题。
我正在尝试在内核内存中设置一个函数钩子。因此,每次调用特定函数时,它都应该转换为我的函数。
我的想法是将一个地址加载到一个寄存器中,这是在使用它运行时获得的:
unsigned long address = &hooked_do_undefinstr;
然后编写
的相应OPCodeBLR 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位地址加载到寄存器中? 或者是否有更好的方法来实现我的函数钩子以跳转到我的地址?
致以问候并感谢您的帮助
答案 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;