程序使用系统调用来从操作系统的内核请求服务。
我正在尝试通过 libc/syscall 拦截编写(有限的)内存中文件系统重定向,并为虚拟化的文件返回 memfd_create 生成的文件描述符。作为准备...
内核模块代码 #包括 #包括 #包括 #包括 #包括 #包括 内核模块代码 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/kprobes.h> #include <linux/syscalls.h> #include <linux/uaccess.h> #include <linux/fs.h> MODULE_LICENSE("GPL"); static void my_write_cr0(long value) { __asm__ volatile("mov %0, %%cr0" :: "r"(value) : "memory"); } #define disable_write_protection() my_write_cr0(read_cr0() & (~0x10000)) #define enable_write_protection() my_write_cr0(read_cr0() | 0x10000) unsigned long* sys_call_table_address; asmlinkage int (*original_chmod)(const char __user*, umode_t); static struct kprobe kp = { .symbol_name = "kallsyms_lookup_name" }; typedef unsigned long (*kallsyms_lookup_name_t)(const char* name); unsigned long* get_sys_call_table_address(void) { kallsyms_lookup_name_t kallsyms_lookup_name; int ret = register_kprobe(&kp); if (ret < 0) { printk(KERN_ERR "InterceptChmod: register_kprobe failed, returned %d\n", ret); return NULL; } kallsyms_lookup_name = (kallsyms_lookup_name_t)kp.addr; unregister_kprobe(&kp); if (!kallsyms_lookup_name) { printk(KERN_ERR "InterceptChmod: kallsyms_lookup_name not found\n"); return NULL; } unsigned long* address = (unsigned long*)kallsyms_lookup_name("sys_call_table"); if (!address) { printk(KERN_ERR "InterceptChmod: sys_call_table not found\n"); } else { printk(KERN_INFO "InterceptChmod: sys_call_table address: %p\n", address); } return address; } asmlinkage int custom_chmod(const char __user* filename, umode_t mode) { char fname[256]; // Copy the filename from user space to kernel space if (strncpy_from_user(fname, filename, sizeof(fname)) > 0) { fname[sizeof(fname) - 1] = '\0'; // Ensure null termination printk(KERN_INFO "InterceptChmod: chmod intercepted for file: %s, mode: %o\n", fname, mode); } else { printk(KERN_INFO "InterceptChmod: chmod intercepted, failed to get filename, mode: %o\n", mode); } // Call the original chmod system call return original_chmod(filename, mode); } static int __init intercept_chmod_init(void) { printk(KERN_INFO "InterceptChmod: Loading module\n"); sys_call_table_address = get_sys_call_table_address(); if (!sys_call_table_address) { printk(KERN_ERR "InterceptChmod: Failed to get sys_call_table_address\n"); return -EFAULT; } printk(KERN_INFO "InterceptChmod: sys_call_table address: %p\n", sys_call_table_address); original_chmod = (void*)sys_call_table_address[__NR_chmod]; printk(KERN_INFO "InterceptChmod: Original chmod address: %p\n", original_chmod); disable_write_protection(); sys_call_table_address[__NR_chmod] = (unsigned long)custom_chmod; enable_write_protection(); printk(KERN_INFO "InterceptChmod: Hooked chmod system call, new address: %p\n", (void*)sys_call_table_address[__NR_chmod]); return 0; } static void __exit intercept_chmod_exit(void) { if (sys_call_table_address) { disable_write_protection(); sys_call_table_address[__NR_chmod] = (unsigned long)original_chmod; enable_write_protection(); printk(KERN_INFO "InterceptChmod: Restored original chmod system call, address: %p\n", (void*)sys_call_table_address[__NR_chmod]); } printk(KERN_INFO "InterceptChmod: Module unloaded\n"); } module_init(intercept_chmod_init); module_exit(intercept_chmod_exit); 我使用 Linux 6.8.11-amd64、OracleVM VirtualBox 和 X86_64 处理器。 我使用以下方式加载模块: sudo insmod lkm_chmod.ko 然后我测试他的使用命令 sudo chmod 755 testfile他没有记录这个。 我的日志看起来像这样。 [ 9245.540511] InterceptChmod: Loading module [ 9245.561100] InterceptChmod: sys_call_table address: 00000000d760dd16 [ 9245.561105] InterceptChmod: sys_call_table address: 00000000d760dd16 [ 9245.561106] InterceptChmod: Original chmod address: 0000000014a7fad1 [ 9245.561110] InterceptChmod: Hooked chmod system call, new address: 00000000ce1988d5 [ 9330.452750] InterceptChmod: Restored original chmod system call, address: 0000000014a7fad1 [ 9330.452766] InterceptChmod: Module unloaded 我不明白为什么他不工作,我的日志中没有错误。我尝试将 __NR_chmod 更改为 __NR_open 或 __NR_close,但他不起作用。 我尝试使用 ChatGPT,他只说废话,只是重复我的代码。 好吧,我在这个答案中找到了解决方案answer。感谢 Ian Abbott 指出在 6.9 及更早版本中 sys_call_table 不再有效。 现在我修复了代码,他开始使用kprobes工作。 #include <linux/kprobes.h> #include <linux/ptrace.h> static int sys_read_kprobe_pre_handler(struct kprobe* p, struct pt_regs* regs) { printk(KERN_NOTICE "ROOTKIT: read(%ld, 0x%lx, 0x%lx)\n", regs->di, regs->si, regs->dx); return 0; } struct kprobe syscall_kprobe = { .symbol_name = "__x64_sys_read", .pre_handler = sys_read_kprobe_pre_handler, }; static int __init startup(void) { int err; err = register_kprobe(&syscall_kprobe); if (err) { pr_err("register_kprobe() failed: %d\n", err); return err; } printk(KERN_NOTICE "ROOTKIT: Starting of due"); return 0; } static void __exit shutdown(void) { unregister_kprobe(&syscall_kprobe); printk(KERN_NOTICE "ROOTKIT: Ending"); } module_init(startup); module_exit(shutdown); MODULE_LICENSE("GPL");
在我早期的内核编程工作中,我尝试替换/挂钩 ioctl 系统调用,目的是记录并最终检查完成的每个 ioctl 调用。 目标系统是...
有没有办法在不依赖于 Linux 的 libc 的情况下编译 Rust 程序?
我是否可以将 Rust 程序编译为二进制文件,该二进制文件在运行时和 Linux 上不依赖于 libc?
我正在尝试使用系统调用 56 在 /dev/input/js0 打开我的 Xbox 游戏手柄。我已验证给定路径中设备的存在。包括通过使用 open() 用 C 编写的测试程序。然而,...
错误:FALLOC_FL_KEEP_SIZE 未声明(在此函数中首次使用)
根据手册页,我在包含 之前定义了 _GNU_SOURCE: #包括 #define _GNU_SOURCE /* 对于Linux 的fallocate()。 */ #define HAVE_FALLOCATE 1 #我...
对于在 EINTR 上重试的系统调用的包装器,重试多少次才有意义?
通常像 write(2)、read(2)、close(2) 等系统调用会由于被带有 errno 值 EINTR 的信号中断而失败(比如终端窗口的大小发生了变化并且收到了 SIGWINCH),
我正在尝试连接到arm64的sys_call_table,同样我正在修改sys_call_table的读写权限。它在使表可读可写时崩溃,返回-22: u200e u200e ...
无法在 Oracle 8 ARM64 中使 sys_call_table 读写
内核版本:5.15.0-205.149.5.1.el8uek.aarch64(5.15系列全部) 操作系统:Oracle 8 ARM64 我正在尝试连接到 sys_call_table,同样我正在修改
Linux 编程接口在第 3 章中有一个练习,如下所示: 当使用Linux特定的reboot()时 系统调用来重新启动系统, 第二个参数 magic2 必须是 规格...
这就是我所做的。 在路径./linux-5.7中 mkdir 你好 你好 vim 你好.c #包括 asmlinkage 长 sys_hello(void) { 打印k(“ 你好内核 ”); 返回0; ...
我需要监控Linux执行的系统调用量。 我知道 vmstat 能够为 BSD 和 AIX 系统显示这一点,但对于 Linux 则不能(根据手册页)。 有没有可以...
有没有一种方法可以从 eBPF 映射中读取数据,而无需支付内核调用 read / ppoll 添加的开销(因为它们是内核调用)。也许 mmap 传递了一些奇怪的参数?
祝大家圣诞快乐。我在 Perl 脚本方面遇到了困境。在我的脚本中,我通过系统调用调用另一个程序,但出现以下错误: 无法执行“./Classificador/svm_classify”:不...
ARM系统调用的接口是什么?它在Linux内核中的哪里定义?
我读过有关Linux中的系统调用的内容,到处都有关于x86架构(0x80中断和SYSENTER)的描述。但我无法追踪系统的文件和进程...
我有以下代码来监视目录的更改,并在终端中打印一些内容。 该代码监视两个文件中的更改 - 一个名为 test,另一个名为 test2 - 之后
将 ASCII 代码点值存储在浮点数中可以防止将其解释为字符(在 C 中)
浮动c; c = 'a'; 而 (c <= 'z') { write(1, &c, 1); c++; } write() is data type-agnostic. It should deliver the correct code point values to the terminal. The terminal should then
_syscallN 宏到哪里去了<linux/unistd.h>?
过去的情况是,如果你需要直接在linux中进行系统调用而不使用现有的库,你可以只包含,它会定义一个宏...
高级程序如何调用用低级语言编写的函数 - 函数调用之间如何进行数据类型转换
众所周知,LINUX 系统调用是用 C 语言编写的,例如:open()、read() 等, - JAVA、PYTHON 等高级语言将如何使用这些函数 - 因为这些系统符合.. .
为什么设置 F_SEAL_WRITE 后无法创建只读、共享映射?
执行 fcntl(memfd, F_ADD_SEALS, F_SEAL_WRITE); 之后,调用 mmap(NULL, 4096, PROT_READ, MAP_SHARED, memfd, 0);失败并出现错误 EPERM。基于man 2 fcntl,我对F_SEAL_WRITE的理解是...