--- hydra-4.6-src/hydra-smbnt.c	2004-05-10 14:27:07.000000000 -0500
+++ hydra-jmk/hydra-smbnt.c	2005-03-29 15:57:53.000000000 -0600
@@ -8,13 +8,26 @@
 #else
 #include <openssl/md4.h>
 #include <openssl/des.h>
-#include <openssl/des.h>
 
 /*
    SMB NTLM Password/HASH Checking Hydra Module
-   Copyright (C) m0j0.j0j0
-   m0j0.j0j0 / m0j0@foofus.net 
-   09/30/2003
+   Version: $Id: hydra-smbnt.c 67 2005-03-08 20:14:40Z jmk $
+   
+   ------------------------------------------------------------------------
+    Copyright (C) 2005 Joseph N. Mondloch
+    JoMo-Kun / jmk@foofus.net 
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2,
+    as published by the Free Software Foundation
+   
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+   
+    http://www.gnu.org/licenses/gpl.txt
+   ------------------------------------------------------------------------
 
    Based on code from: SMB Auditing Tool
    [Copyright (C) Patrik Karlsson 2001]
@@ -27,7 +40,7 @@
    LanMan passwords.
 
    The "-m 'METHOD'" option is required for this module. The
-   following are valid methods: L, LH, D, DH, B and BH 
+   following are valid methods: L, LH, D, DH, B, BH and M
    (in quotes).
 
      L == Check local account.
@@ -39,6 +52,7 @@
           locally on the host being tested, that host then 
           queries its domain controller.
      H == Use a NTLM hash rather than a password. 
+     M == Use the Machine's NetBIOS name as the password. 
 
    Be careful of mass domain account lockout with this. For
    example, assume you are checking several accounts against 
@@ -49,20 +63,28 @@
    lockouts. Of course, it'd look like the workstations, not 
    you, were doing it. ;)
 
-   **FYI, this code does not appear to currently work against 
-   Windows XP hosts which are NOT a member of a domain. Will 
-   look into this...
+   **FYI, this code is unable to test accounts on default XP
+   hosts which are not part of a domain and do not have normal
+   file sharing enabled. Default XP does not allow shares and
+   returns STATUS_LOGON_FAILED for both valid and invalid 
+   credentials. XP with simple sharing enabled returns SUCCESS
+   for both valid and invalid credentials. If anyone knows a
+   way to test in these configurations...
 
-   See http://www.foofus.net/m0j0/passhash.html for further
+   See http://www.foofus.net/jmk/passhash.html for further
    examples.
 
    Greets: Foofus, Phenfen & Fizzgig  
 */
 
+#define WIN2000_NATIVEMODE 1
+#define WIN_NETBIOSMODE 2
+
 extern char *HYDRA_EXIT;
 char challenge[8];
 unsigned char workgroup[16];
-int hashFlag, accntFlag;
+unsigned char machine_name[16];
+int hashFlag, accntFlag, protoFlag;
 
 static unsigned char
 Get7Bits(unsigned char *input, int startBit)
@@ -122,13 +144,13 @@
   unsigned char p21[21];
   unsigned char ntlm_response[24];
   int i = 0, j = 0;
-  int mdlen = strlen((char *) pass) * 2 * 8;
+  int mdlen;
   unsigned char *p;
   char HexChar;
   int HexValue;
 
   /* Use NTLM Hash instead of password */
-  if (hashFlag) {
+  if (hashFlag == 1) {
     /* 1000:D42E35E1A1E4C22BD32E2170E4857C20:5E20780DD45857A68402938C7629D3B2::: */
     p = pass;
     while ((*p != '\0') && (i < 2)) {
@@ -170,12 +192,22 @@
       hash[i] = (unsigned char) HexValue;
     }
   } else {
+    /* Password == Machine Name */
+    if (hashFlag == 2) {
+      for (i = 0; i < 16; i++) {
+        if (machine_name[i] > 0x39)
+          machine_name[i] = machine_name[i] | 0x20;     /* convert upper case to lower */
+        pass = machine_name;
+      }
+    }
+   
     /* Initialize the Unicode version of the secret (== password). */
     /* This implicitly supports 8-bit ISO8859/1 characters. */
     bzero(unicodePassword, sizeof(unicodePassword));
     for (i = 0; i < strlen((char *) pass); i++)
       unicodePassword[i * 2] = (unsigned char) pass[i];
 
+    mdlen = strlen((char *) pass) * 2;    /* length in bytes */
     MD4_Init(&md4Context);
     MD4_Update(&md4Context, unicodePassword, mdlen);
     MD4_Final(hash, &md4Context);        /* Tell MD4 we're done */
@@ -205,6 +237,10 @@
   char *buf;
   unsigned char rbuf[400];
 
+  /* if we are running in native mode (aka port 445) don't do netbios */
+  if (protoFlag == WIN2000_NATIVEMODE)
+    return 0;
+  
   /* convert computer name to netbios name */
   memset(nb_name, 0, 32);
   memset(nb_local, 0, 32);
@@ -219,7 +255,7 @@
   memcpy(buf + 39, nb_local, 32);
   memcpy(buf + 71, (char *) rqbuf + 5, 1);
 
-  hydra_send(s, buf, 72, 0);
+  hydra_send(s, buf, 76, 0);
   free(buf);
 
   memset(rbuf, 0, 400);
@@ -269,10 +305,18 @@
   };
 
   unsigned char rbuf[400];
-  int i = 0;
+  unsigned char sess_key[2];
+  unsigned char userid[2] = {0xCD, 0xEF};
+  int i = 0, j = 0;
 
   memset((char *) rbuf, 0, 400);
 
+  /* set session key */
+  sess_key[1] = getpid() / 100;
+  sess_key[0] = getpid() - (100 * sess_key[1]);
+  memcpy(buf + 30, sess_key, 2);
+  memcpy(buf + 32, userid, 2);
+  
   hydra_send(s, (char *) buf, 168, 0);
   hydra_recv(s, (char *) rbuf, sizeof(rbuf));
 
@@ -281,12 +325,18 @@
 
   /* find the primary domain/workgroup name */
   memset(workgroup, 0, 16);
+  memset(machine_name, 0, 16);
 
   while ((rbuf[81 + i * 2] != 0) && (i < 16)) {
     workgroup[i] = rbuf[81 + i * 2];
     i++;
   }
 
+  while ((rbuf[81 + (i + j + 1) * 2] != 0) && (j < 16)) {
+    machine_name[j] = rbuf[81 + (i + j + 1) * 2];
+    j++;
+  }
+
   return 2;
 }
 
@@ -300,7 +350,7 @@
        valid NTLM hash.
   Returns: TRUE on success else FALSE.
 */
-int
+short
 SMBSessionSetup(int s, char *user, char *pass, char *miscptr)
 {
   unsigned char b[137] = {
@@ -328,6 +378,7 @@
   unsigned char *NTLMhash;
   unsigned char LMhash[24];
   unsigned char rbuf[400];
+  unsigned char sess_key[2];
   int userlen;
 
   NTLMhash = (unsigned char *) malloc(24);
@@ -349,6 +400,11 @@
   memcpy(buf + 65, LMhash, 24);
   memcpy(buf + 89, NTLMhash, 24);
 
+  /* set session key */
+  sess_key[1] = getpid() / 100;
+  sess_key[0] = getpid() - (100 * sess_key[1]);
+  memcpy(buf + 30, sess_key, 2);
+  
   userlen = strlen(user);
 
   memcpy(buf + 113, user, userlen);
@@ -366,7 +422,9 @@
   hydra_send(s, (char *) buf, 126 + userlen + strlen((char *) workgroup), 0);
   hydra_recv(s, (char *) rbuf, sizeof(rbuf));
 
-  return rbuf[9];
+  /* 41 - Action (Guest/Non-Guest Account) */
+  /*  9 - NT Status (Error code) */
+  return ((rbuf[41] << 8) | rbuf[9]);
 }
 
 int
@@ -374,28 +432,44 @@
 {
   char *empty = "";
   char *login, *pass;
-  int SMBerr;
+  int SMBerr, SMBaction;
+  short SMBSessionRet;
+  char ipaddr_str[INET_ADDRSTRLEN];
 
   if (strlen(login = hydra_get_next_login()) == 0)
     login = empty;
   if (strlen(pass = hydra_get_next_password()) == 0)
     pass = empty;
 
-  SMBerr = SMBSessionSetup(s, login, pass, miscptr);
+  inet_ntop(AF_INET, &ip, ipaddr_str, sizeof(ipaddr_str));
+  SMBSessionRet = SMBSessionSetup(s, login, pass, miscptr);
+  SMBerr = (short) SMBSessionRet & 0x00FF;
+  SMBaction = ((short) SMBSessionRet & 0xFF00) >> 8;
 
   if (0x00 == SMBerr) {         /* success */
-    hydra_report_found_host(port, ip, "smb", fp);
+    if (0x01 == SMBaction) {  /* invalid account - anonymous connection */
+      fprintf(stderr, "[%d][smb] Host: %s Account: %s Error: Invalid Account (Anonymous Mapping Created)\n", port, ipaddr_str, login);
+      hydra_completed_pair();
+    } else {         /* valid account */
+      hydra_report_found_host(port, ip, "smbnt", fp);
     hydra_completed_pair_found();
+    }
   } else if (0x24 == SMBerr) {  /* change password on next login [success] */
-    hydra_report_found_host(port, ip, "smb (must change password)", fp);
+    fprintf(stderr, "[%d][smb] Host: %s Account: %s Error: ACCOUNT_CHANGE_PASSWORD\n", port, ipaddr_str, login);
     hydra_completed_pair_found();
+  } else if (0x6D == SMBerr) {  /* STATUS_LOGON_FAILURE */
+    hydra_completed_pair();
   } else if (0x72 == SMBerr) {  /* account disabled */
-    hydra_report_found_host(port, ip, "smb (account disabled)", fp);
+    fprintf(stderr, "[%d][smb] Host: %s Account: %s Error: ACCOUNT_DISABLED\n", port, ipaddr_str, login);
     hydra_completed_pair();
   } else if (0x34 == SMBerr) {  /* account locked out */
-    fprintf(stderr, "[%d][smb] Account: %s is locked out\n", port, login);
+    fprintf(stderr, "[%d][smb] Host: %s Account: %s Error: ACCOUNT_LOCKED\n", port, ipaddr_str, login);
+    hydra_completed_pair();
+  } else if (0x8D == SMBerr) {  /* ummm... broken client-domain membership  */
+    fprintf(stderr, "[%d][smb] Host: %s Account: %s Error: NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE\n", port, ipaddr_str, login);
     hydra_completed_pair();
   } else {                      /* failed */
+    fprintf(stderr, "[%d][smb] Host: %s Account: %s Unknown Error: %2.2X\n", port, ipaddr_str, login, SMBerr);
     hydra_completed_pair();
   }
 
@@ -409,7 +483,6 @@
 service_smbnt(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port)
 {
   int run = 1, next_run, sock = -1;
-  int myport = PORT_SMB, mysslport = PORT_SMB_SSL;
 
   if ((strcmp(miscptr, "L") == 0)) {
     accntFlag = 0;
@@ -429,6 +502,9 @@
   } else if ((strcmp(miscptr, "BH") == 0)) {
     accntFlag = 2;
     hashFlag = 1;
+  } else if ((strcmp(miscptr, "M") == 0)) {
+    accntFlag = 0;
+    hashFlag = 2;
   } else {
     printf("SMBNT Module requires -m METHOD\n");
     hydra_child_exit(0);
@@ -443,16 +519,26 @@
       if (sock >= 0)
         sock = hydra_disconnect(sock);
       usleep(300000);
-      if ((options & OPTION_SSL) == 0) {
-        if (port != 0)
-          myport = port;
-        sock = hydra_connect_tcp(ip, myport);
-        port = myport;
-      } else {
-        if (port != 0)
-          mysslport = port;
-        sock = hydra_connect_ssl(ip, mysslport);
-        port = mysslport;
+
+      if (port != 0) {
+        sock = hydra_connect_tcp(ip, port);
+        if (port == PORT_SMB) 
+          protoFlag = WIN_NETBIOSMODE;
+        else  
+          protoFlag = WIN2000_NATIVEMODE;
+      }
+      else {
+        sock = hydra_connect_tcp(ip, PORT_SMBNT);
+        if (sock > 0) {
+          port = PORT_SMBNT;
+          protoFlag = WIN2000_NATIVEMODE;
+        }
+        else {
+          fprintf(stderr, "Failed to establish WIN2000_NATIVE mode. Attempting WIN_NETBIOS mode.\n");
+          port = PORT_SMB;
+          protoFlag = WIN_NETBIOSMODE;
+          sock = hydra_connect_tcp(ip, PORT_SMB);
+        }
       }
       if (sock < 0) {
         fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int) getpid());
--- hydra-4.6-src/hydra.h 2005-01-06 09:39:55.000000000 -0600
+++ hydra-jmk/hydra.h 2005-03-29 15:22:57.000000000 -0600
@@ -48,6 +48,8 @@
 #define PORT_NNTP_SSL  563
 #define PORT_SMB 139
 #define PORT_SMB_SSL    139
+#define PORT_SMBNT     445
+#define PORT_SMBNT_SSL 445
 #define PORT_IMAP  143
 #define PORT_IMAP_SSL  993
 #define PORT_LDAP  389
--- hydra-4.6-src/hydra.c 2005-02-01 08:51:21.000000000 -0600
+++ hydra-jmk/hydra.c 2005-03-29 15:34:13.000000000 -0600
@@ -670,7 +670,7 @@
     {"rexec", PORT_REXEC, PORT_REXEC_SSL},
     {"sapr3", PORT_SAPR3, PORT_SAPR3_SSL},
     {"smb", PORT_SMB, PORT_SMB_SSL},
-    {"smbnt", PORT_SMB, PORT_SMB_SSL},
+    {"smbnt", PORT_SMBNT, PORT_SMBNT_SSL},
     {"socks5", PORT_SOCKS5, PORT_SOCKS5_SSL},
     {"ssh2", PORT_SSH, PORT_SSH_SSL},
     {"telnet", PORT_TELNET, PORT_TELNET_SSL},
