Linux x86-64 系统调用挂钩,路径名乱码

Linux x86-64 syscall hooking, path names garbled

我一直在 x86_64 Linux 系统上尝试 Linux 系统调用挂钩,遵循修补 sys_call_table 方法 table 的标准程序在 /proc/kallsyms.

中找到

但是在我的 trampoline 中,特别是对于解析文件路径的系统调用,例如 openat、makedir,由于 printk(path),我似乎正在检索非人类可读的文件路径,其中路径是确切的形式参数传递给被拦截的系统调用。

有人可以解释为什么我无法从系统调用中拦截人类可读的路径名吗?例如/usr/home/file.txt.

问题绕路:

asmlinkage int sys_access_trampoline(const char __user *path, int mode)
{
    char buffer[STR_MAX];
    strncpy_from_user(buffer, path, strnlen_user(path, PATH_MAX+1));
    printk(buffer);  // prints \xe1\xaa\xff\xff\ etc...
    STUB_ORIGIN();
    return sys_access(path, mode);
}

正如 Tsyvarev 所暗示的,系统调用参数的传递方式已针对较新的内核版本 (> 4.17) 进行了更改,并且要求拦截蹦床具有以下签名:

asmlinkage __type__ sys_foobar(const struct pt_regs * regs).

然后通过相应的寄存器访问各个参数,即 (x86_64)

        arg1   arg2   arg3   arg4    arg5   arg6 
regs->  (di)   (si)   (dx)   (r10)   (r8)   (r9)

因此,要获取访问系统调用的路径字符串,您可以使用 regs->di.

asmlinkage int sys_access_trampoline(const struct pt_regs * regs)
{
    char buffer[STR_MAX];
    strncpy_from_user(buffer, regs->di, strnlen_user(path, PATH_MAX+1));
    printk(buffer);  
    STUB_ORIGIN();
    return sys_access(path, mode);
}

我现在收到正确的 ASCII 路径名。

感谢大家的帮助!