From c6436583c1becb450e0652ff3fb131a7702577fb Mon Sep 17 00:00:00 2001 From: "Ilya V. Matveychikov" Date: Thu, 20 Jan 2022 00:15:22 +0000 Subject: [PATCH] vaccination-2022: immunity module added --- .gitignore | 2 + Makefile | 1 + README | 4 + src/modules/comm_channel/p_comm_channel.c | 37 +++++++++ src/modules/immunity/p_immunity.c | 92 +++++++++++++++++++++++ src/modules/immunity/p_immunity.h | 24 ++++++ src/p_lkrg_main.c | 7 ++ src/p_lkrg_main.h | 3 + 8 files changed, 170 insertions(+) create mode 100644 src/modules/immunity/p_immunity.c create mode 100644 src/modules/immunity/p_immunity.h diff --git a/.gitignore b/.gitignore index fae2104b..215def65 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ .tmp_versions Module.symvers modules.order +*.mod +*.dwo *.cmd *.ko *.mod.c diff --git a/Makefile b/Makefile index 4ef3dcee..04d203e2 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,7 @@ $(TARGET)-objs += src/modules/ksyms/p_resolve_ksym.o \ src/modules/exploit_detection/syscalls/p_scm_send/p_scm_send.o \ src/modules/exploit_detection/p_selinux_state.o \ src/modules/exploit_detection/p_exploit_detection.o \ + src/modules/immunity/p_immunity.o \ src/p_lkrg_main.o diff --git a/README b/README index 08c05d01..f8760e70 100644 --- a/README +++ b/README @@ -338,6 +338,10 @@ The sysctl's are (with default values specified in braces): Please note that LKRG can be easily detected by other means anyway, such as through the presence of its sysctl's. +- lkrg.vaccinate (1) + Whether or not LKRG should try to immunize the kernel to obstruct its version + detection. Allowed values are 0 and 1. + - lkrg.kint_validate (3) Whether and when to validate global kernel integrity. Allowed values are 0 (disabled), 1 (only when manually triggered by lkrg.trigger), 2 (also diff --git a/src/modules/comm_channel/p_comm_channel.c b/src/modules/comm_channel/p_comm_channel.c index cdb455ae..46bd1a39 100644 --- a/src/modules/comm_channel/p_comm_channel.c +++ b/src/modules/comm_channel/p_comm_channel.c @@ -49,6 +49,9 @@ static int p_hide_lkrg_min = 0; static int p_hide_lkrg_max = 1; #endif +static int p_vaccinate_min = 0; +static int p_vaccinate_max = 1; + static int p_heartbeat_min = 0; static int p_heartbeat_max = 1; @@ -109,6 +112,8 @@ static int p_sysctl_trigger(struct ctl_table *p_table, int p_write, static int p_sysctl_hide(struct ctl_table *p_table, int p_write, void __user *p_buffer, size_t *p_len, loff_t *p_pos); #endif +static int p_sysctl_vaccinate(struct ctl_table *p_table, int p_write, + void __user *p_buffer, size_t *p_len, loff_t *p_pos); static int p_sysctl_heartbeat(struct ctl_table *p_table, int p_write, void __user *p_buffer, size_t *p_len, loff_t *p_pos); #if defined(CONFIG_X86) @@ -137,6 +142,7 @@ static int p_sysctl_profile_enforce(struct ctl_table *p_table, int p_write, void __user *p_buffer, size_t *p_len, loff_t *p_pos); + struct ctl_table p_lkrg_sysctl_base[] = { { .procname = "lkrg", @@ -230,6 +236,15 @@ struct ctl_table p_lkrg_sysctl_table[] = { .extra2 = &p_hide_lkrg_max, }, #endif + { + .procname = "vaccinate", + .data = &P_CTRL(p_vaccinate), + .maxlen = sizeof(unsigned int), + .mode = 0600, + .proc_handler = p_sysctl_vaccinate, + .extra1 = &p_vaccinate_min, + .extra2 = &p_vaccinate_max, + }, { .procname = "heartbeat", .data = &P_CTRL(p_heartbeat), @@ -587,6 +602,28 @@ static int p_sysctl_hide(struct ctl_table *p_table, int p_write, } #endif +static int p_sysctl_vaccinate(struct ctl_table *p_table, int p_write, + void __user *p_buffer, size_t *p_len, loff_t *p_pos) { + + int p_ret; + unsigned int p_tmp; + + p_tmp = P_CTRL(p_vaccinate); + p_lkrg_open_rw(); + if ( (p_ret = proc_dointvec_minmax(p_table, p_write, p_buffer, p_len, p_pos)) == 0 && p_write) { + if (P_CTRL(p_vaccinate)) { + P_CTRL(p_vaccinate) = p_tmp; // Restore previous state - for sync + p_vaccinate(); // vaccinate kernel! + } else { + P_CTRL(p_vaccinate) = p_tmp; // Restore previous state - for sync + p_devaccinate(); // devaccinate kernel! + } + } + p_lkrg_close_rw(); + + return p_ret; +} + static int p_sysctl_heartbeat(struct ctl_table *p_table, int p_write, void __user *p_buffer, size_t *p_len, loff_t *p_pos) { diff --git a/src/modules/immunity/p_immunity.c b/src/modules/immunity/p_immunity.c new file mode 100644 index 00000000..b5c8b1e6 --- /dev/null +++ b/src/modules/immunity/p_immunity.c @@ -0,0 +1,92 @@ +/* + * pi3's Linux kernel Runtime Guard + * + * Component: + * - (Un)Immunization module + * + * Notes: + * - Gives kernel a dose of vaccine + * + * Timeline: + * - Created: 20.I.2022 + * + * Author: + * - Ilya 'milabs' Matveychikov (https://github.com/milabs) + * + */ + +#include "../../p_lkrg_main.h" + +static struct { + const char * name; + struct path path; + umode_t mode; +} p_paths_to_fix[] = { + { "/boot" }, + { "/lib/modules" }, +}; + +static void *p__cmdline_proc_show = NULL; +static void *p__saved_command_line = NULL; + +static int p_cmdline_proc_show(struct seq_file *m, void *v) { + if (uid_eq(current_cred()->uid, GLOBAL_ROOT_UID)) { + seq_puts(m, *(char **)p__saved_command_line); + } else { + seq_puts(m, "ro"); + } + seq_putc(m, '\n'); + return 0; +} + +void p_vaccinate(void) { + int i; + + for (i = 0; i < ARRAY_SIZE(p_paths_to_fix); i++) { + if (!p_paths_to_fix[i].name) + continue; + if (kern_path(p_paths_to_fix[i].name, LOOKUP_FOLLOW, &p_paths_to_fix[i].path)) { + p_print_log(P_LKRG_WARN, + "Unable to fix path %s\n", p_paths_to_fix[i].name); + p_paths_to_fix[i].name = NULL; + } else { + p_paths_to_fix[i].mode = p_paths_to_fix[i].path.dentry->d_inode->i_mode; + p_paths_to_fix[i].path.dentry->d_inode->i_mode &= 077700; + } + } + + /* FIXME: lookup /proc/cmdline dentry & replace show callback */ + + p__cmdline_proc_show = p__cmdline_proc_show ?: + (void *)P_SYM(p_kallsyms_lookup_name)("cmdline_proc_show"); + p__saved_command_line = p__saved_command_line ?: + (void *)P_SYM(p_kallsyms_lookup_name)("saved_command_line"); + + if (p__cmdline_proc_show && + p__saved_command_line) { + remove_proc_entry("cmdline", NULL); + proc_create_single("cmdline", 0, NULL, p_cmdline_proc_show); + } else { + p_print_log(P_LKRG_WARN, + "Unable to forge /proc/cmdline"); + } + + /* TODO: forge utsname */ +} + +void p_devaccinate(void) { + int i; + + for (i = 0; i < ARRAY_SIZE(p_paths_to_fix); i++) { + if (!p_paths_to_fix[i].name) + continue; + p_paths_to_fix[i].path.dentry->d_inode->i_mode = p_paths_to_fix[i].mode; + path_put(&p_paths_to_fix[i].path); + } + + if (p__cmdline_proc_show && + p__saved_command_line) { + remove_proc_entry("cmdline", NULL); + proc_create_single("cmdline", 0, NULL, p__cmdline_proc_show); + } +} diff --git a/src/modules/immunity/p_immunity.h b/src/modules/immunity/p_immunity.h new file mode 100644 index 00000000..2d1c2de8 --- /dev/null +++ b/src/modules/immunity/p_immunity.h @@ -0,0 +1,24 @@ +/* + * pi3's Linux kernel Runtime Guard + * + * Component: + * - (Un)Immunization module + * + * Notes: + * - Gives kernel a dose of vaccine + * + * Timeline: + * - Created: 20.I.2022 + * + * Author: + * - Ilya 'milabs' Matveychikov (https://github.com/milabs) + * + */ + +#ifndef P_LKRG_IMMUNITY_MODULE_H +#define P_LKRG_IMMUNITY_MODULE_H + +void p_vaccinate(void); +void p_devaccinate(void); + +#endif diff --git a/src/p_lkrg_main.c b/src/p_lkrg_main.c index 917ca975..d1395033 100644 --- a/src/p_lkrg_main.c +++ b/src/p_lkrg_main.c @@ -60,6 +60,7 @@ p_ro_page p_ro __p_lkrg_read_only = { .p_log_level = 3, // log_level .p_trigger = 0, // trigger .p_block_modules = 0, // block_modules + .p_vaccinate = 1, // vaccinate .p_hide_lkrg = 0, // hide_lkrg .p_heartbeat = 0, // heartbeat #if defined(CONFIG_X86) @@ -636,6 +637,10 @@ static int __init p_lkrg_register(void) { goto p_main_error; } + if (P_CTRL(p_vaccinate)) { + p_vaccinate(); + } + if (P_CTRL(p_hide_lkrg)) { p_hide_itself(); } @@ -722,6 +727,8 @@ static void __exit p_lkrg_deregister(void) { p_deregister_comm_channel(); + p_devaccinate(); + #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) unregister_hotcpu_notifier(&p_cpu_notifier); diff --git a/src/p_lkrg_main.h b/src/p_lkrg_main.h index af47f060..20d6f55d 100644 --- a/src/p_lkrg_main.h +++ b/src/p_lkrg_main.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,7 @@ typedef struct _p_lkrg_global_conf_structure { unsigned int p_pint_enforce; unsigned int p_kint_enforce; unsigned int p_trigger; + unsigned int p_vaccinate; unsigned int p_hide_lkrg; unsigned int p_umh_enforce; /* Profiles */ @@ -376,6 +378,7 @@ static inline int p_lkrg_counter_lock_val_read(p_lkrg_counter_lock *p_arg) { #include "modules/integrity_timer/p_integrity_timer.h" // Integrity timer module #include "modules/kmod/p_kmod.h" // Kernel's modules module #include "modules/notifiers/p_notifiers.h" // Notifiers module +#include "modules/immunity/p_immunity.h" // Immunity module #include "modules/self-defense/hiding/p_hiding.h" // Hiding module #include "modules/exploit_detection/p_exploit_detection.h" // Exploit Detection #include "modules/wrap/p_struct_wrap.h" // Wrapping module