JnewChen 2025-07-11 18:05 采纳率: 100%
浏览 7
已结题

Linux arm syscall hook

模拟hook openat 系统调用,hook能够成功,但是调用原函数返回失败。主要错误码 -14/* Bad address /、-22/ Invalid argument */,有没有大神帮忙看看。

日志如下:

img

系统环境

root@jc-kvmvirtualmachine:~# cat /etc/kylin-build
Kylin-Desktop V10-SP1
Build 20220513
buildid: 31950
root@jc-kvmvirtualmachine:src# uname -a
Linux jc-kvmvirtualmachine 5.4.18-53-generic #42-KYLINOS SMP Fri Mar 4 06:09:02 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux

系统架构

root@jc-kvmvirtualmachine:~# lscpu
架构:                           aarch64
CPU 运行模式:                   64-bit
字节序:                         Little Endian
CPU:                             4
在线 CPU 列表:                  0-3
每个核的线程数:                 1
每个座的核数:                   4
座:                             1
NUMA 节点:                      1
厂商 ID:                        0x70
型号:                           3
型号名称:                       Phytium,FT-2000/4
步进:                           0x1
CPU 最大 MHz:                   2100.0000
CPU 最小 MHz:                   2100.0000
BogoMIPS:                       100.00
NUMA 节点0 CPU:                 0-3
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Vulnerable
Vulnerability Spec store bypass: Vulnerable
Vulnerability Spectre v1:        Mitigation; __user pointer sanitization
Vulnerability Spectre v2:        Vulnerable
Vulnerability Tsx async abort:   Not affected
标记:                           fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid

测试代码


#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ccc");
MODULE_VERSION("1.0");

void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);
static unsigned long start_rodata = 0, end_rodata = 0;
void* sys_call_table_ptr[__NR_syscalls] = {0};
// 保存原始的openat函数指针
asmlinkage long (*orig_openat_func)(const struct pt_regs *) = NULL;


asmlinkage long my_stub_openat(const struct pt_regs *regs)
{
    long fd = -1;

    printk(KERN_INFO "=== HOOK OPENAT DEBUG START ===\n");
  
    // 检查原始函数指针是否有效
    if(!orig_openat_func){
        printk(KERN_ERR "hook: orig_openat_func is NULL!\n");
        return -ENOSYS;
    }
    
    printk(KERN_INFO "hook openat: calling original func %lx\n", (unsigned long)orig_openat_func);
    fd = orig_openat_func(regs);
    printk(KERN_INFO "hook openat: original func returned fd=%ld\n", fd);
    printk(KERN_INFO "=== HOOK OPENAT DEBUG END ===\n");

    return fd;
}

void free_new_sys_call_table(void *table) {
    if(table){
        vfree(table);
    }
}

static void init_hook_func(int NR_call, unsigned long func) {
    void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
    if(!orig_table) {
        printk(KERN_ERR "Failed to find sys_call_table symbol.\n");
        return;
    }
    if(NR_call < 0 || NR_call >= __NR_syscalls) {
        printk(KERN_ERR "Invalid syscall number: %d\n", NR_call);
        return;
    }

    *((unsigned long *) (orig_table + (NR_call * sizeof(void *)))) = func;
    printk(KERN_INFO "Hooked syscall number %d with function %lx\n", NR_call, func);
}

static int init_global_value(void){
    void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
    update_mapping_prot = (void *)kallsyms_lookup_name("update_mapping_prot");
    start_rodata = (unsigned long)kallsyms_lookup_name("__start_rodata");
    end_rodata= (unsigned long)kallsyms_lookup_name("__end_rodata");

    if(!update_mapping_prot || !start_rodata || !end_rodata || !orig_table) {
        printk(KERN_ERR "Failed to find required symbols.\n");
        return -1;
    }
    
    memcpy(sys_call_table_ptr, orig_table, sizeof(void *) * __NR_syscalls);

    orig_openat_func = (asmlinkage long (*)(const struct pt_regs *))sys_call_table_ptr[__NR_openat];

    printk(KERN_INFO "myhook found symbols: update_mapping_prot: %lx, start_rodata: %lx, end_rodata: %lx, orig_table: %lx\n",
           (unsigned long)update_mapping_prot, start_rodata, end_rodata, (unsigned long)orig_table);
    printk(KERN_INFO "myhook saved orig_openat_func: %lx\n", (unsigned long)orig_openat_func);
    return 0;
}

static void disable_write_protection(void)
{
    update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL);
    return ;
}
 
static void enable_write_protection(void)
{
    update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL_RO);
    return ;
}


static int __init patch_init(void) {
    if(init_global_value() != 0){
        printk(KERN_ERR "Failed to initialize global values.\n");
        return -ENOSPC;
    }
    preempt_disable();
    disable_write_protection();

    init_hook_func(__NR_openat, (unsigned long)my_stub_openat);

    enable_write_protection();
    preempt_enable();
    printk(KERN_INFO "Module loaded successfully.\n");
    return 0;
}

static void __exit patch_cleanup(void)
{
    preempt_disable();
    disable_write_protection();

    // 恢复原始的openat系统调用
    if(orig_openat_func) {
        init_hook_func(__NR_openat, (unsigned long)orig_openat_func);
        printk(KERN_INFO "Restored original openat syscall: %lx\n", (unsigned long)orig_openat_func);
    }

    enable_write_protection();
    preempt_enable();

    
    printk(KERN_INFO "Module unloaded successfully.\n");
    return ;
}

module_init(patch_init);
module_exit(patch_cleanup);

  • 写回答

6条回答 默认 最新

  • JnewChen 2025-07-14 14:25
    关注
    
    #include <linux/init.h>
    #include <linux/vmalloc.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/kallsyms.h>
    #include <linux/uaccess.h>
    #include <asm/unistd.h>
    #include <asm/ptrace.h>
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("ccc");
    MODULE_VERSION("1.0");
    
    void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);
    static unsigned long start_rodata = 0, end_rodata = 0;
    void* sys_call_table_ptr[__NR_syscalls] = {0};
    // 保存原始的openat函数指针
    asmlinkage long (*orig_openat_func)(int dirfd, const char *pathname, int flags, mode_t mode) = NULL;
    
    //-----更改点:显式定义HOOK函数的参数列表------
    asmlinkage long my_stub_openat(int dfd, const char *pathname, int flags, mode_t mode)
    {
        long fd = -EFAULT;
    
        // 如果后缀是".777",则拒绝打开
        if (pathname && strlen(pathname) > 4 && strcmp(pathname + strlen(pathname) - 4, ".777") == 0) {
            printk(KERN_INFO "myhook openat: blocked opening .777 file: %s\n", pathname);
            return -EACCES; // 返回权限错误
        }
    
        fd = orig_openat_func(dfd, pathname, flags, mode);
        //printk(KERN_INFO "myhook openat returned fd=%ld\n", fd);
    
        return fd;
    }
    
    void free_new_sys_call_table(void *table) {
        if(table){
            vfree(table);
        }
    }
    
    static void init_hook_func(int NR_call, unsigned long func) {
        void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
        if(!orig_table) {
            printk(KERN_ERR "Failed to find sys_call_table symbol.\n");
            return;
        }
        if(NR_call < 0 || NR_call >= __NR_syscalls) {
            printk(KERN_ERR "Invalid syscall number: %d\n", NR_call);
            return;
        }
    
        *((unsigned long *) (orig_table + (NR_call * sizeof(void *)))) = func;
        printk(KERN_INFO "Hooked syscall number %d with function %lx\n", NR_call, func);
    }
    
    static int init_global_value(void){
        void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
        update_mapping_prot = (void *)kallsyms_lookup_name("update_mapping_prot");
        start_rodata = (unsigned long)kallsyms_lookup_name("__start_rodata");
        end_rodata= (unsigned long)kallsyms_lookup_name("__end_rodata");
    
        if(!update_mapping_prot || !start_rodata || !end_rodata || !orig_table) {
            printk(KERN_ERR "Failed to find required symbols.\n");
            return -1;
        }
        
        memcpy(sys_call_table_ptr, orig_table, sizeof(void *) * __NR_syscalls);
    
        orig_openat_func = (asmlinkage long (*)(int dirfd, const char *pathname, int flags, mode_t mode))sys_call_table_ptr[__NR_openat];
    
        printk(KERN_INFO "myhook found symbols: update_mapping_prot: %lx, start_rodata: %lx, end_rodata: %lx, orig_table: %lx\n",
               (unsigned long)update_mapping_prot, start_rodata, end_rodata, (unsigned long)orig_table);
        printk(KERN_INFO "myhook saved orig_openat_func: %lx\n", (unsigned long)orig_openat_func);
        return 0;
    }
    
    static void disable_write_protection(void)
    {
        update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL);
        return ;
    }
     
    static void enable_write_protection(void)
    {
        update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL_RO);
        return ;
    }
    
    
    static int __init patch_init(void) {
        if(init_global_value() != 0){
            printk(KERN_ERR "Failed to initialize global values.\n");
            return -ENOSPC;
        }
        preempt_disable();
        disable_write_protection();
    
        init_hook_func(__NR_openat, (unsigned long)my_stub_openat);
    
        enable_write_protection();
        preempt_enable();
        printk(KERN_INFO "Module loaded successfully.\n");
        return 0;
    }
    
    static void __exit patch_cleanup(void)
    {
        preempt_disable();
        disable_write_protection();
    
        // 恢复原始的openat系统调用
        if(orig_openat_func) {
            init_hook_func(__NR_openat, (unsigned long)orig_openat_func);
            printk(KERN_INFO "Restored original openat syscall: %lx\n", (unsigned long)orig_openat_func);
        }
    
        enable_write_protection();
        preempt_enable();
    
        printk(KERN_INFO "Module unloaded successfully.\n");
        return ;
    }
    
    module_init(patch_init);
    module_exit(patch_cleanup);
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 7月22日
  • 已采纳回答 7月14日
  • 创建了问题 7月11日