You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过内核模块替换write系统调用按键输入及终端崩溃问题问询

崩溃原因

你的代码核心错误是混淆了write系统调用的参数含义:
x86_64架构下系统调用的参数通过寄存器传递,write的原型为ssize_t write(int fd, const void *buf, size_t count),对应寄存器规则是:

  • rdi:第一个参数,文件描述符fd
  • rsi:第二个参数,用户态缓冲区的内存指针
  • rdx:第三个参数,写入长度

你直接将regs->si(也就是rsi寄存器的值)赋值为0x62(字符'b'的ASCII值),等于强制让write系统调用从地址为0x62的非法低地址读取数据,直接触发内存访问错误,导致关联的终端进程崩溃。同时你直接解引用用户态指针buf[0]也存在风险,如果用户态传入非法指针,会直接触发内核oops。

正确实现思路

要在hook的write系统调用中修改写入内容,需遵循内核态访问用户态内存的安全规则,不要直接修改指针本身,而是修改指针指向的缓冲区内容,或者使用内核临时缓冲区中转:

  1. 先安全校验并读取用户态缓冲区的内容,禁止直接解引用用户态指针
  2. 确认需要替换内容后,安全写入修改后的值到用户态缓冲区,或者使用内核临时缓冲区中转后调用原write逻辑

修正后示例代码

unsigned long hacked_write_test(struct pt_regs *regs) {
    int r;
    unsigned int fd = regs->di;
    char __user *buf = (char __user *)regs->si;
    char tmp;

    // 仅处理标准输出等目标fd,可优化为判断fd对应是否为tty设备,兼容性更好
    if (fd == 1 || fd == 2 || fd == 3) {
        // 安全读取用户态buf的第一个字符,访问失败直接跳过修改
        if (get_user(tmp, buf) == 0) {
            if (tmp == 0x61) {
                printk("in write: A received");
                // 安全将修改后的字符写回用户态缓冲区
                put_user(0x62, buf);
            }
        }
    }

    r = original_write(regs);
    return r;
}

注意事项

  • 上述实现会直接修改用户态传入的缓冲区内容,如果业务不允许修改原用户态内存,可以在内核栈申请临时缓冲区,拷贝全部写入内容修改后,调整rsi寄存器指向临时缓冲区,同时调用set_fs(KERNEL_DS)(仅旧内核可用,5.10+内核已废弃该接口)让write可以读取内核态地址,调用完成后恢复原fs值即可
  • 直接hook系统调用的兼容性较差,更推荐hook tty层的receive_buf或write回调实现按键替换,稳定性更高

内容的提问来源于stack exchange,提问作者tarun14110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 13:06:07