diff -uN hydra-2.4/configure hydra-2.4-m0j0/configure
--- hydra-2.4/configure	2003-08-14 10:35:08.000000000 -0500
+++ hydra-2.4-m0j0/configure	2003-10-01 10:22:47.000000000 -0500
@@ -25,8 +25,20 @@
 MANDIR=""
 LIBDIRS=`cat /etc/ld.so.conf 2> /dev/null`
 PREFIX=`echo "$1"|sed 's/.*--prefix=//'`
+LIBDES=""
 echo
 
+echo "Checking for libdes ..."
+for i in $LIBDIRS /lib /usr/lib /usr/local/lib /opt/local/lib
+do
+    if [ "X" = "X$LIBDES" ]; then
+        if [ -f "$i/libdes.a" ]; then
+            LIBDES="$i/libdes.a"
+        fi
+    fi
+done
+
+
 echo "Checking for openssl ..."
 for i in  $LIBDIRS /lib  /usr/lib /usr/local/lib /opt/local/lib \
 /*ssl /usr/*ssl /opt/*ssl /usr/local/*ssl /opt/local/*ssl \
@@ -164,6 +176,7 @@
 echo "XLIBPATHS=$XLIBPATHS" >> Makefile.in
 echo "XIPATHS=$XIPATHS" >> Makefile.in
 echo "PREFIX=$PREFIX" >> Makefile.in
+echo "LIBDES=$LIBDES" >> Makefile.in
 echo >> Makefile.in
 
 echo "Generating Makefile ..."
diff -uN hydra-2.4/hydra.c hydra-2.4-m0j0/hydra.c
--- hydra-2.4/hydra.c	2003-08-20 04:43:42.000000000 -0500
+++ hydra-2.4-m0j0/hydra.c	2003-10-14 15:37:08.000000000 -0500
@@ -2,6 +2,8 @@
  * hydra v2.4 (c) 2001-2003 by van Hauser / THC <vh@thc.org>
  * http://www.hackerschoice.com
  *
+ * Parallel host scanning by m0j0.j0j0 [m0j0@foofus.net]
+ *
  * Parallized network login hacker. Do only use for legal purposes.
  */
 
@@ -11,7 +13,7 @@
 
 #include "hydra.h"
 
-extern void service_telnet(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
+extern void service_telnet(unsigned long int ip, int sp, unsigned char options, char *iscptr, FILE *fp, int port);
 extern void service_ftp(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 extern void service_pop3(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 extern void service_imap(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
@@ -26,23 +28,26 @@
 extern void service_icq(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 extern void service_pcnfs(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 extern void service_smb(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
+extern void service_smbnt(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 extern void service_mysql(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port);
 // ADD NEW SERVICES HERE
-#define SERVICES  "telnet ftp pop3 imap smb http https cisco cisco-enable ldap mysql nntp vnc rexec socks5 icq pcnfs"
+#define SERVICES  "telnet ftp pop3 imap smb smbnt http https cisco cisco-enable ldap mysql nntp vnc rexec socks5 icq pcnfs"
 // ADD NEW SERVICES HERE
 
-#define MAXBUF    264
+#define MAXBUF  264
 #define MAXTASKS  255
+#define MAXSERVERS  255
 
 #define PROGRAM   "Hydra"
 #define VERSION   "v2.4"
-#define AUTHOR    "van Hauser / THC"
-#define EMAIL     "<vh@thc.org>"
+#define AUTHOR  "van Hauser / THC"
+#define EMAIL   "<vh@thc.org>"
 #define RESSOURCE "http://www.thc.org"
 
-#define DEBUG	  0
+#define DEBUG	  0 
 #define WAITTIME  30
-#define TASKS     4
+#define TASKS   4
+#define SERVERS   1
 
 char *prg, *tmp;
 extern char HYDRA_EXIT[5];
@@ -54,102 +59,108 @@
 int killed = 0;
 
 static pid_t pids[MAXTASKS];
+static pid_t addr_pids[MAXSERVERS];
 
 void help() {
-    printf("%s %s (c) 2003 by %s %s " \
-           "Syntax:  %s [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | " \
-           "[-C FILE]] [-o FILE] [-t TASKS] [-g TASKS] [-w TIME] " \
-           "[-f] [-e ns] [-s PORT] [-S] server service [OPT]\n", \
-           PROGRAM,VERSION,AUTHOR,EMAIL,prg);
-    printf("\nOptions:\n");
+  printf("%s %s (c) 2003 by %s %s " \
+       "Syntax:  %s [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | " \
+       "[-C FILE]] [-o FILE] [-t TASKS] [-g TASKS] [-T SERVERS] " \
+       "[-w TIME] [-f] [-e ns] [-s PORT] [-S] server service [OPT]\n", \
+       PROGRAM,VERSION,AUTHOR,EMAIL,prg);
+  printf("\nOptions:\n");
 #ifdef OPENSSL
-    printf("  -S        connect via SSL\n");
+  printf("  -S    connect via SSL\n");
 #endif
-    printf("  -s PORT   if the service is on a different default port, " \
-             "define it here\n" \
-           "  -l LOGIN  or -L FILE login with LOGIN name, or load " \
-             "several logins from FILE\n" \
-           "  -p PASS   or -P FILE try password PASS, or load several " \
-             "passwords from FILE\n" \
-           "  -e ns     additional checks, \"n\" for null password, \"s\" " \
-             "try login as pass\n" \
-           "  -C FILE   colon seperated \"login:pass\" format, instead of " \
-             "-L/-P option\n" \
-           "  -o FILE   write found login/password pairs to FILE instead " \
-             "of stdout\n" \
-           "  -f        exit after the first found login/password pair\n" \
-           "  -t TASKS  run TASKS number of connects in parallel " \
-             "(default: %d)\n" \
-           "  -g TASKS  start TASKS number per second until -t TASKS are" \
-             "reached\n" \
-           "  -w TIME   in seconds, defines the max wait reply time " \
-             "(default: %d)\n" \
-           "  server    the target server\n" \
-           "  service   the service to crack. Supported protocols: [%s]\n" \
-           "  OPT       some service modules need additional input, put " \
-              "it here\n" \
-           "\n%s is a tool to guess valid login/password pairs on a "\
-           "target server.\nYou can always find the newest version at %s\n" \
-           "Use this tool only for legal purposes!\n", \
-           TASKS,WAITTIME,SERVICES,PROGRAM,RESSOURCE);
-    exit(-1);
+  printf("  -s PORT  if the service is on a different default port, " \
+       "define it here\n" \
+       "  -l LOGIN or -L FILE login with LOGIN name, or load " \
+       "several logins from FILE\n" \
+       "  -p PASS or -P FILE try password PASS, or load several " \
+       "passwords from FILE\n" \
+       "  -e ns      additional checks, \"n\" for null password, \"s\" " \
+       "try login as pass\n" \
+       "  -C FILE    colon seperated \"login:pass\" format, instead of " \
+       "-L/-P option\n" \
+       "  -M FILE    file containing server list\n" \
+       "  -o FILE    write found login/password pairs to FILE instead " \
+       "of stdout\n" \
+       "  -f         exit after the first found login/password pair\n" \
+       "  -X         show username/password for login attempts\n" \
+       "  -m         misc options for some modules\n" \
+       "  -t TASKS   run TASKS number of connects in parallel " \
+       "(default: %d)\n" \
+       "  -T SERVERS run SERVERS number of hosts in parallel " \
+       "(default: %d)\n" \
+       "  -g TASKS   start TASKS number per second until -t TASKS are" \
+       "reached\n" \
+       "  -w TIME    in seconds, defines the max wait reply time " \
+       "(default: %d)\n" \
+       "  server     the target server\n" \
+       "  service    the service to crack. Supported protocols: [%s]\n" \
+       "  OPT        some service modules need additional input, put " \
+        "it here\n" \
+       "\n%s is a tool to guess valid login/password pairs on a "\
+       "target server.\nYou can always find the newest version at %s\n" \
+       "Use this tool only for legal purposes!\n", \
+       TASKS,SERVERS,WAITTIME,SERVICES,PROGRAM,RESSOURCE);
+  exit(-1);
 }
 
 void bail(char *text) {
-    fprintf(stderr, "Error: %s\n", text);
-    exit(-1);
+  fprintf(stderr, "Error: %s\n", text);
+  exit(-1);
 }
 
 void killed_childs(int signo) {
-    killed++;
-    (void) wait3(NULL, WNOHANG, NULL);
+  killed++;
+  (void) wait3(NULL, WNOHANG, NULL);
 }
 
 void kill_children(int signo) {
-    int i;
-    for (i = 0; i < MAXTASKS; i++)
-    if (pids[i] > 0)
-        kill(pids[i], SIGTERM);
-    sleep(1);
-    if (pids[i] > 0)
-        kill(pids[i], SIGKILL);
-    exit(0);
+  int i;
+  for (i = 0; i < MAXSERVERS; i++)
+  if (addr_pids[i] > 0)
+    kill(addr_pids[i], SIGTERM);
+  sleep(1);
+  if (addr_pids[i] > 0)
+    kill(addr_pids[i], SIGKILL);
+  exit(0);
 }
 
 unsigned long int countlines(FILE *fp) {
-    size_t lines = 0, size = 0;
-    char *buf = malloc(MAXBUF);
-    while (!feof(fp)) {
-        if (fgets(buf, MAXBUF, fp) != NULL) {
-            if (buf[0] != 0) {
-                size += strlen(buf);
-                lines++;
-            }
-        }
-    }
-    rewind(fp);
-    size++;
-    extra = size;
-    return lines;
+  size_t lines = 0, size = 0;
+  char *buf = malloc(MAXBUF);
+  while (!feof(fp)) {
+    if (fgets(buf, MAXBUF, fp) != NULL) {
+      if (buf[0] != 0) {
+        size += strlen(buf);
+        lines++;
+      }
+    }
+  }
+  rewind(fp);
+  size++;
+  extra = size;
+  return lines;
 }
 
 void fill_mem(char *ptr, FILE *fp) {
-    char tmp[MAXBUF + 4] = "";
-    while (! feof(fp)) {
-        if (fgets(tmp, MAXBUF, fp) != NULL) {
-            if (tmp[0] != 0) {
-                if (tmp[strlen(tmp)-1] == '\n')
-                    tmp[strlen(tmp)-1] = '\0';
-                if (tmp[strlen(tmp)-1] == '\r')
-                    tmp[strlen(tmp)-1] = '\0';
-                memcpy(ptr, tmp, strlen(tmp));
-                ptr += strlen(tmp);
-                *ptr = '\0';
-                ptr++;
-            }
-        }
+  char tmp[MAXBUF + 4] = "";
+  while (! feof(fp)) {
+    if (fgets(tmp, MAXBUF, fp) != NULL) {
+      if (tmp[0] != 0) {
+        if (tmp[strlen(tmp)-1] == '\n')
+          tmp[strlen(tmp)-1] = '\0';
+        if (tmp[strlen(tmp)-1] == '\r')
+          tmp[strlen(tmp)-1] = '\0';
+        memcpy(ptr, tmp, strlen(tmp));
+        ptr += strlen(tmp);
+        *ptr = '\0';
+        ptr++;
+      }
     }
-    fclose(fp);
+  }
+  fclose(fp);
 }
 
 
@@ -158,519 +169,674 @@
 #else
  int hydra_main(int soc, void *nessus, int argc, char *argv[]) {
 #endif
-    unsigned int tasks = 1, exit_found = 0;
-    unsigned int ssl = 0, group = MAXTASKS + 1;
-    unsigned char options = 0;
-    int try_password_same_as_login = 0, try_null_password = 0;
-    char *login = NULL, *loginfile = NULL, *pass = NULL, *passfile = NULL;
-    char *colonfile = NULL, *outfile_ptr = NULL;
-    char *miscptr = NULL, *server, *service;
-
-    char *login_ptr, *pass_ptr = "", *pass_ptr_save, *csv_ptr;
-    FILE *lfp, *pfp, *cfp, *ofp = stdout;
-    unsigned int socketpairs[MAXTASKS][2];
-    size_t countlogin = 1, sizelogin = 0, countpass = 0, sizepass = 0;
-    unsigned long int math2, todo, sent = 0;
-    struct hostent *target;
-    unsigned long int ip;
-    struct in_addr in;
-    int i, j;
-#ifdef NESSUS_PLUGIN    
-    char * svc_kb_name;
-    char * asc_port;
+  unsigned int tasks = 1, servers = 1, exit_found = 0;
+  unsigned int ssl = 0, group = MAXTASKS + 1;
+  unsigned char options = 0;
+  int try_password_same_as_login = 0, try_null_password = 0;
+  char *login = NULL, *loginfile = NULL, *pass = NULL, *passfile = NULL;
+  char *colonfile = NULL, *outfile_ptr = NULL, *infile_ptr = NULL;
+  char *miscptr = NULL, *server, *service;
+
+  char *login_ptr, *pass_ptr = "", *csv_ptr, *ipaddr_ptr;
+  FILE *lfp, *pfp, *cfp, *ifp, *ofp = stdout;
+  unsigned int addr_socketpairs[MAXSERVERS][2];
+  size_t countlogin = 1, sizelogin = 0, countpass = 0, sizepass = 0;
+  size_t countinfile = 1, sizeinfile = 0;
+  unsigned long int math2, todo;
+  struct hostent *target;
+  unsigned long int ip;
+  struct in_addr in;
+  int i, j, sID;
+#ifdef NESSUS_PLUGIN  
+  char * svc_kb_name;
+  char * asc_port;
 #endif  
-    
-    char empty_login[2] = "";
-    prg = argv[0];
-    debug = 0;
-    verbose = 0;
-    waittime = WAITTIME;
-    port = 0;
-    tasks = TASKS;
-    if (argc < 4) help();
-    tmp = malloc(MAXBUF);
-
-    while ((i = getopt(argc, argv, "de:vl:fg:L:p:P:o:C:t:m:w:s:S")) >= 0) {
-        switch (i) {
-            case 'd': debug = 1; verbose++; break;
-            case 'e': i = 0;
-                      while (i < strlen(optarg)) {
-                          switch(optarg[i]) {
-                              case 'n': try_null_password = 1; break;
-                              case 's': try_password_same_as_login = 1; break;
-                              default: fprintf(stderr,"Error: unknown mode %c for option -e, only supporting \"n\" and \"s\"\n", optarg[i]);
-                              exit(-1);
-                          }
-                          i++;
-                      }
-                      break;
-            case 'v': verbose = 1; break;
-            case 'l': login = optarg; break;
-            case 'L': loginfile = optarg; break;
-            case 'p': pass = optarg; break;
-            case 'P': passfile = optarg; break;
-            case 'f': exit_found = 1; break;
-            case 'g': group = atoi(optarg); break;
-            case 'o': outfile_ptr = optarg; break;
-            case 'C': colonfile = optarg; break;
-            case 't': tasks = atoi(optarg); break;
-            case 'm': miscptr = optarg; break;
-            case 'w': waittime = atoi(optarg); break;
-            case 's': port = atoi(optarg); break;
-            case 'S':
+
+  char empty_login[2] = "";
+  int showAttempt = 0;
+  prg = argv[0];
+  debug = 0;
+  verbose = 0;
+  waittime = WAITTIME;
+  port = 0;
+  tasks = TASKS;
+  if (argc < 4) help();
+  tmp = malloc(MAXBUF);
+
+  while ((i = getopt(argc, argv, "de:vXl:fg:L:p:P:o:M:C:t:T:m:w:s:S")) >= 0) {
+    switch (i) {
+      case 'd': debug = 1; verbose++; break;
+      case 'e': i = 0;
+            while (i < strlen(optarg)) {
+              switch(optarg[i]) {
+                case 'n': try_null_password = 1; break;
+                case 's': try_password_same_as_login = 1; break;
+                default: fprintf(stderr,"Error: unknown mode %c for option -e, only supporting \"n\" and \"s\"\n", optarg[i]);
+                exit(-1);
+              }
+              i++;
+            }
+            break;
+      case 'v': verbose = 1; break;
+      case 'X': showAttempt = 1; break;
+      case 'l': login = optarg; break;
+      case 'L': loginfile = optarg; break;
+      case 'p': pass = optarg; break;
+      case 'P': passfile = optarg; break;
+      case 'f': exit_found = 1; break;
+      case 'g': group = atoi(optarg); break;
+      case 'o': outfile_ptr = optarg; break;
+      case 'M': infile_ptr = optarg; break;
+      case 'C': colonfile = optarg; break;
+      case 't': tasks = atoi(optarg); break;
+      case 'T': servers = atoi(optarg); break;
+      case 'm': miscptr = optarg; break;
+      case 'w': waittime = atoi(optarg); break;
+      case 's': port = atoi(optarg); break;
+      case 'S':
 #ifndef OPENSSL
-		      fprintf(stderr, "Sorry, hydra was compiled without SSL support. Install openssl and recompile!\n");
-                      ssl = 0; break;
+		    fprintf(stderr, "Sorry, hydra was compiled without SSL support. Install openssl and recompile!\n");
+            ssl = 0; break;
 #else 
-            	      ssl = 1; break;
+      	    ssl = 1; break;
 #endif
-            default: fprintf(stderr,"Error: unknown option -%c\n", i); help();
-        }
+      default: fprintf(stderr,"Error: unknown option -%c\n", i); help();
     }
-    if (optind + 2 != argc && optind + 3 != argc) help();
+  }
+
+  if (argv[optind +1] == NULL && infile_ptr != NULL) {
+    server = NULL;
+    service = argv[optind];
+    if (optind + 2 == argc) miscptr = argv[optind + 1];
+  } else if (optind + 2 != argc && optind + 3 != argc) {
+    server = NULL;
+    service = NULL;
+    help();
+  } else {
     server = argv[optind];
     service = argv[optind + 1];
     if (optind + 3 == argc) miscptr = argv[optind + 2];
-    
-    i = 0;
-    if (strcmp(service, "telnet") == 0) i = 1;
-    if (strcmp(service, "ftp") == 0) i = 1;
-    if (strcmp(service, "pop3") == 0) i = 1;
-    if (strcmp(service, "imap") == 0) i = 1;
-    if (strcmp(service, "rexec") == 0) i = 1;
-    if (strcmp(service, "nntp") == 0) i = 1;
-    if (strcmp(service, "socks5") == 0) i = 1;
-    if (strcmp(service, "icq") == 0) i = 1;
-    if (strcmp(service, "mysql") == 0) i = 1;
+  }
+
+  i = 0;
+  if (strcmp(service, "telnet") == 0) i = 1;
+  if (strcmp(service, "ftp") == 0) i = 1;
+  if (strcmp(service, "pop3") == 0) i = 1;
+  if (strcmp(service, "imap") == 0) i = 1;
+  if (strcmp(service, "rexec") == 0) i = 1;
+  if (strcmp(service, "nntp") == 0) i = 1;
+  if (strcmp(service, "socks5") == 0) i = 1;
+  if (strcmp(service, "icq") == 0) i = 1;
+  if (strcmp(service, "mysql") == 0) i = 1;
 // ADD NEW SERVICES HERE
-    if (strcmp(service, "smb") == 0) {
-        if (tasks > 1) {
-            fprintf(stderr, "Reduced number of tasks to 1 (smb does not like parallel connections)\n");
-            tasks = 1;
-        }
-        i = 1;
-    }
-    if (strcmp(service, "pcnfs") == 0) {
-        i = 1;
-        if (port == 0) {
-            fprintf(stderr, "Error: You must set the port for pcnfs with -s (run \"rpcinfo -p %s\" and look for the pcnfs v2 UDP port)\n", server);
-            exit(-1);
-        }
-    }
-    if (strcmp(service, "cisco") == 0) {
-        i = 2;
-        login = empty_login;
-        if (tasks > 4)
-            printf("Warning: you should set the number of parallel task to 4 for cisco services.\n");
-    }
-    if (strcmp(service, "ldap") == 0) {
-        i = 1;
-        if ((miscptr != NULL && login != NULL) || (miscptr != NULL && loginfile != NULL) || (login != NULL && loginfile != NULL))
-            bail("Error: you may only use one of -l, -L or -m (or none)\n");
-        if (login == NULL && loginfile == NULL && miscptr == NULL)
-            fprintf(stderr, "Warning: no DN to authenticate to defined, using DN of null (use -m, -l or -L to define DNs)\n");
-        if (login == NULL && loginfile == NULL) {
-            i = 2;
-            login = empty_login;
-        }
-    }
-    if (strcmp(service, "cisco-enable") == 0) {
-        i = 2;
-        login = empty_login;
-        if (miscptr == NULL) {
-            bail("Error: You must supply the inial password to logon via the -m option\n");
-        }
-        if (tasks > 4)
-            printf("Warning: you should set the number of parallel task to 4 for cisco enable services.\n");
-    }
-    if (strcmp(service, "vnc") == 0) {
-        i = 2;
-        login = empty_login;
-        if (tasks > 4)
-            printf("Warning: you should set the number of parallel task to 4 for vnc services.\n");
-    }
-    if (strcmp(service, "www") == 0 || strcmp(service, "http") == 0) {
-        i = 1; 
-        if (miscptr == NULL) bail("You must supply the web page as an additional option or via -m");
-        if (*miscptr != '/') bail("The web page you supplied must start with a \"/\", e.g. \"/protected/login\"");
-        strcpy(service, "www");
-    }
+  if (strcmp(service, "smb") == 0) {
+    if (tasks > 1) {
+      fprintf(stderr, "Reduced number of tasks to 1 (smb does not like parallel connections)\n");
+      tasks = 1;
+    }
+    i = 1;
+  }
+  if (strcmp(service, "smbnt") == 0) {
+    if (tasks > 1) {
+      fprintf(stderr, "Reduced number of tasks to 1 (smb does not like parallel connections)\n");
+      tasks = 1;
+    }
+    i = 1;
+  }
+  if (strcmp(service, "pcnfs") == 0) {
+    i = 1;
+    if (port == 0) {
+      fprintf(stderr, "Error: You must set the port for pcnfs with -s (run \"rpcinfo -p %s\" and look for the pcnfs v2 UDP port)\n", server);
+      exit(-1);
+    }
+  }
+  if (strcmp(service, "cisco") == 0) {
+    i = 2;
+    login = empty_login;
+    if (tasks > 4)
+      printf("Warning: you should set the number of parallel task to 4 for cisco services.\n");
+  }
+  if (strcmp(service, "ldap") == 0) {
+    i = 1;
+    if ((miscptr != NULL && login != NULL) || (miscptr != NULL && loginfile != NULL) || (login != NULL && loginfile != NULL))
+      bail("Error: you may only use one of -l, -L or -m (or none)\n");
+    if (login == NULL && loginfile == NULL && miscptr == NULL)
+      fprintf(stderr, "Warning: no DN to authenticate to defined, using DN of null (use -m, -l or -L to define DNs)\n");
+    if (login == NULL && loginfile == NULL) {
+      i = 2;
+      login = empty_login;
+    }
+  }
+  if (strcmp(service, "cisco-enable") == 0) {
+    i = 2;
+    login = empty_login;
+    if (miscptr == NULL) {
+      bail("Error: You must supply the inial password to logon via the -m option\n");
+    }
+    if (tasks > 4)
+      printf("Warning: you should set the number of parallel task to 4 for cisco enable services.\n");
+  }
+  if (strcmp(service, "vnc") == 0) {
+    i = 2;
+    login = empty_login;
+    if (tasks > 4)
+      printf("Warning: you should set the number of parallel task to 4 for vnc services.\n");
+  }
+  if (strcmp(service, "www") == 0 || strcmp(service, "http") == 0) {
+    i = 1; 
+    if (miscptr == NULL) bail("You must supply the web page as an additional option or via -m");
+    if (*miscptr != '/') bail("The web page you supplied must start with a \"/\", e.g. \"/protected/login\"");
+    strcpy(service, "www");
+  }
 #ifdef OPENSSL
-    if (strcmp(service, "ssl") == 0 || strcmp(service, "https") == 0) {
-        i = 1; 
-        if (miscptr == NULL) bail("You must supply the web page as an additional option or via -m");
-        if (*miscptr != '/') bail("The web page you supplied must start with a \"/\", e.g. \"/protected/login\"");
-        ssl = 1;
-        strcpy(service, "www");
-    }
+  if (strcmp(service, "ssl") == 0 || strcmp(service, "https") == 0) {
+    i = 1; 
+    if (miscptr == NULL) bail("You must supply the web page as an additional option or via -m");
+    if (*miscptr != '/') bail("The web page you supplied must start with a \"/\", e.g. \"/protected/login\"");
+    ssl = 1;
+    strcpy(service, "www");
+  }
 #endif
 // ADD NEW SERVICES HERE
-    if (i == 0) bail("Unknown service");
+  if (i == 0) bail("Unknown service");
 
-    if (i == 2 && ((login != NULL && strlen(login) > 0) || loginfile != NULL || colonfile != NULL))
-        bail("The cisco, cisco-enable and vnc crack modes are only using the -p or -P option, not login (-l, -L) or colon file (-C).\nUse the normal telnet crack mode for cisco using \"Username:\" authentication.\n");
-    if (i == 1 && login == NULL && loginfile == NULL && colonfile == NULL)
-        bail("I need at least either the -l, -L or -C option to know the login");
-    if (colonfile != NULL && ((login != NULL || loginfile != NULL) || (pass != NULL && passfile != NULL)))
-        bail("The -C option is standalone, dont use it with -l/L and -p/P !");
-    if (try_password_same_as_login == 0 && try_null_password == 0 && pass == NULL && passfile == NULL && colonfile == NULL)
-        bail("I need at least the -e, -p or -P option to have some passwords!");
-    if (tasks < 1 || tasks > MAXTASKS) {
-        fprintf(stderr, "Option -t needs to be a number between 1 and %d", MAXTASKS);
-        exit(-1);
-    }
-
-    if (loginfile != NULL) {
-        if ((lfp = fopen(loginfile, "r")) == NULL)
-            bail("File for logins not found!");
-        countlogin = countlines(lfp);
-        sizelogin = extra;
-        if (countlogin == 0)
-            bail("File for logins is empty!");
-        login_ptr = malloc(sizelogin);
-        fill_mem(login_ptr, lfp);
-    } else
-        login_ptr = login;
-    if (passfile != NULL) {
-        if ((pfp = fopen(passfile, "r")) == NULL)
-            bail("File for passwords not found!");
-        countpass = countlines(pfp);
-        sizepass = extra;
-        if (countpass == 0)
-            bail("File for passwords is empty!");
-        pass_ptr = malloc(sizepass);
-        fill_mem(pass_ptr, pfp);
-    } else {
-        if (pass != NULL) {
-            pass_ptr = pass;
-            countpass = 1;
-        }
-    }
-    if (colonfile != NULL) {
-        if (try_password_same_as_login + try_null_password > 0)
-            bail("Error: the -C option may not be used together with the -e option\n");
-        if ((cfp = fopen(colonfile, "r")) == NULL)
-            bail("File with login:password information not found!");
-        countlogin = countlines(cfp);
-        sizelogin = extra;
-        if (countlogin == 0)
-            bail("File for login:password information is empty!");
-        csv_ptr = malloc(sizelogin);
-        fill_mem(csv_ptr, cfp);
-        countpass = 1;
-        pass_ptr = login_ptr = csv_ptr;
-        while(*pass_ptr != '\0' && *pass_ptr != ':') pass_ptr++;
-        if (*pass_ptr == ':') {
-            *pass_ptr = '\0';
-            pass_ptr++;
-        } else {
-            fprintf(stderr, "Invalid line in colonfile: %s\n", login_ptr);
-            pass_ptr = HYDRA_EXIT;
-        }
-    }
+  if (i == 2 && ((login != NULL && strlen(login) > 0) || loginfile != NULL || colonfile != NULL))
+    bail("The cisco, cisco-enable and vnc crack modes are only using the -p or -P option, not login (-l, -L) or colon file (-C).\nUse the normal telnet crack mode for cisco using \"Username:\" authentication.\n");
+  if (i == 1 && login == NULL && loginfile == NULL && colonfile == NULL)
+    bail("I need at least either the -l, -L or -C option to know the login");
+  if (colonfile != NULL && ((login != NULL || loginfile != NULL) || (pass != NULL && passfile != NULL)))
+    bail("The -C option is standalone, dont use it with -l/L and -p/P !");
+  if (try_password_same_as_login == 0 && try_null_password == 0 && pass == NULL && passfile == NULL && colonfile == NULL)
+    bail("I need at least the -e, -p or -P option to have some passwords!");
+  if (tasks < 1 || tasks > MAXTASKS) {
+    fprintf(stderr, "Option -t needs to be a number between 1 and %d", MAXTASKS);
+    exit(-1);
+  }
 
-    countpass += try_password_same_as_login + try_null_password;
-    math2 = countlogin * countpass;
-    if (math2 < tasks) {
-        tasks = math2;
-        fprintf(stderr, "Warning: More tasks defined than login/pass pairs exist. Tasks reduced to %d.\n",tasks);
-    }
-    todo = math2;
-
-    // set options (bits!)
-    options = 0;
-    if (ssl)
-        options = options | OPTION_SSL;
-
-    printf("%s %s (c) 2003 by %s - use allowed only for legal purposes.\n", PROGRAM, VERSION, AUTHOR);
-    printf("%s is starting! [parallel tasks: %d, login tries: %lu (l:%d/p:%d)]\n",PROGRAM,tasks,todo,countlogin,countpass);
-
-    math2 = math2 / tasks;
-    if (verbose)
-        printf("Approx. login tries per task: %lu (%d tasks)\n",math2,tasks);
-
-    /* resolve target */
-    // if ((ip = inet_addr(server)) == -1) { //deprecated
-    if (inet_pton(AF_INET, server, &in) <= 0) {
-        if ((target = gethostbyname(server)) == NULL) {
-	    perror(server);
-	    exit(-1);
-        }
-        memcpy(&ip, target->h_addr, 4);
+  if (loginfile != NULL) {
+    if ((lfp = fopen(loginfile, "r")) == NULL)
+      bail("File for logins not found!");
+    countlogin = countlines(lfp);
+    sizelogin = extra;
+    if (countlogin == 0)
+      bail("File for logins is empty!");
+    login_ptr = malloc(sizelogin);
+    fill_mem(login_ptr, lfp);
+  } else
+    login_ptr = login;
+  if (passfile != NULL) {
+    if ((pfp = fopen(passfile, "r")) == NULL)
+      bail("File for passwords not found!");
+    countpass = countlines(pfp);
+    sizepass = extra;
+    if (countpass == 0)
+      bail("File for passwords is empty!");
+    pass_ptr = malloc(sizepass);
+    fill_mem(pass_ptr, pfp);
+  } else {
+    if (pass != NULL) {
+      pass_ptr = pass;
+      countpass = 1;
+    }
+  }
+  if (colonfile != NULL) {
+    if (try_password_same_as_login + try_null_password > 0)
+      bail("Error: the -C option may not be used together with the -e option\n");
+    if ((cfp = fopen(colonfile, "r")) == NULL)
+      bail("File with login:password information not found!");
+    countlogin = countlines(cfp);
+    sizelogin = extra;
+    if (countlogin == 0)
+      bail("File for login:password information is empty!");
+    csv_ptr = malloc(sizelogin);
+    fill_mem(csv_ptr, cfp);
+    countpass = 1;
+    pass_ptr = login_ptr = csv_ptr;
+    while(*pass_ptr != '\0' && *pass_ptr != ':') pass_ptr++;
+    if (*pass_ptr == ':') {
+      *pass_ptr = '\0';
+      pass_ptr++;
     } else {
-        memcpy(&ip, &in.s_addr, 4);
+      fprintf(stderr, "Invalid line in colonfile: %s\n", login_ptr);
+      pass_ptr = HYDRA_EXIT;
     }
+  }
 
-    if (outfile_ptr != NULL) {
-        char datetime[24];
-        struct tm *the_time;
-        time_t epoch;
-        if ((ofp = fopen(outfile_ptr, "a+")) == NULL) {
-            bail("Error creating outputfile");
-        }
-        time(&epoch);
-        the_time = localtime(&epoch);
-        strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", the_time);
-        fprintf(ofp, "# %s %s run at %s on %s %s ( ", PROGRAM, VERSION, datetime, server, service);
-        if (login     != NULL) fprintf(ofp, "-l %s ", login);
-        if (pass      != NULL) fprintf(ofp, "-p %s ", pass);
-        if (colonfile != NULL) fprintf(ofp, "-C %s ", colonfile);
-        if (loginfile != NULL) fprintf(ofp, "-L %s ", loginfile);
-        if (passfile  != NULL) fprintf(ofp, "-P %s ", passfile);
-        if (try_password_same_as_login) fprintf(ofp, "-e s ");
-        if (try_null_password) fprintf(ofp, "-e n ");
-        fprintf(ofp, ")\n");
-    }
-
-    /* we have to flush all writeable buffered file pointers before forking */
-    fflush(stdout);
-    fflush(stderr);
-    fflush(ofp);
-    
-#ifdef NESSUS_PLUGIN    
-    svc_kb_name = malloc(40 + strlen(service));
-    if(strcmp(service, "http") == 0)
-      strcpy(svc_kb_name, "Services/www");
-    else
-    sprintf(svc_kb_name, "Services/%s", service);
-    asc_port = plug_get_key(nessus, svc_kb_name);
-    if (asc_port)port = atoi(asc_port);
-    free(svc_kb_name);
-    if(port && host_get_port_state(nessus, port) == 0)
-    	return 0;
-    if (port && IS_ENCAPS_SSL(plug_get_port_transport(nessus, port)))
+  countpass += try_password_same_as_login + try_null_password;
+  math2 = countlogin * countpass;
+  if (math2 < tasks) {
+    tasks = math2;
+    fprintf(stderr, "Warning: More tasks defined than login/pass pairs exist. Tasks reduced to %d.\n",tasks);
+  }
+  todo = math2;
+
+  // set options (bits!)
+  options = 0;
+  if (ssl)
+    options = options | OPTION_SSL;
+
+  printf("%s %s (c) 2003 by %s - use allowed only for legal purposes.\n", PROGRAM, VERSION, AUTHOR);
+  printf("%s is starting! [parallel tasks: %d, login tries: %lu (l:%d/p:%d)]\n",PROGRAM,tasks,todo,countlogin,countpass);
+
+  math2 = math2 / tasks;
+  if (verbose)
+    printf("Approx. login tries per task: %lu (%d tasks)\n",math2,tasks);
+
+  if (outfile_ptr != NULL) {
+    char datetime[24];
+    struct tm *the_time;
+    time_t epoch;
+    if ((ofp = fopen(outfile_ptr, "a+")) == NULL) {
+      bail("Error creating outputfile");
+    }
+    time(&epoch);
+    the_time = localtime(&epoch);
+    strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", the_time);
+    fprintf(ofp, "# %s %s run at %s on %s %s ( ", PROGRAM, VERSION, datetime, server, service);
+    if (login   != NULL) fprintf(ofp, "-l %s ", login);
+    if (pass    != NULL) fprintf(ofp, "-p %s ", pass);
+    if (colonfile != NULL) fprintf(ofp, "-C %s ", colonfile);
+    if (loginfile != NULL) fprintf(ofp, "-L %s ", loginfile);
+    if (passfile  != NULL) fprintf(ofp, "-P %s ", passfile);
+    if (try_password_same_as_login) fprintf(ofp, "-e s ");
+    if (try_null_password) fprintf(ofp, "-e n ");
+    fprintf(ofp, ")\n");
+  }
+
+  if (infile_ptr != NULL) {
+    if ((ifp = fopen(infile_ptr, "r")) == NULL)
+      bail("File for IP Addresses not found!");
+    countinfile = countlines(ifp);
+    sizeinfile = extra;
+    if (countinfile == 0)
+      bail("File for IP Addresses is empty!");
+    ipaddr_ptr = malloc(sizeinfile);
+    fill_mem(ipaddr_ptr, ifp);
+  } else
+    ipaddr_ptr = server;
+
+  /* we have to flush all writeable buffered file pointers before forking */
+  fflush(stdout);
+  fflush(stderr);
+  fflush(ofp);
+
+#ifdef NESSUS_PLUGIN  
+  svc_kb_name = malloc(40 + strlen(service));
+  if(strcmp(service, "http") == 0)
+    strcpy(svc_kb_name, "Services/www");
+  else
+  sprintf(svc_kb_name, "Services/%s", service);
+  asc_port = plug_get_key(nessus, svc_kb_name);
+  if (asc_port)port = atoi(asc_port);
+  free(svc_kb_name);
+  if(port && host_get_port_state(nessus, port) == 0)
+  	return 0;
+  if (port && IS_ENCAPS_SSL(plug_get_port_transport(nessus, port)))
 		options |= OPTION_SSL;
-    if (soc >= 0)
-    	ofp = fdopen(soc, "r+");		
+  if (soc >= 0)
+  	ofp = fdopen(soc, "r+");		
 #endif
 
-    /* fork attack processes */
-    signal(SIGCHLD, killed_childs);
-    signal(SIGTERM, kill_children);
-    signal(SIGSEGV, kill_children);
-    signal(SIGHUP, kill_children);
-    for(i = 0; i < tasks; i++) {
-        if (socketpair(PF_UNIX, SOCK_STREAM, 0, socketpairs[i]) != 0) {
-            perror("socketpair failed");
-            socketpairs[i][0] = -1;
-        } else {
-            if ((pids[i] = fork()) == 0) {
-	    	signal(SIGTERM, exit);
-                signal(SIGHUP, exit);
-    if (strcmp(service, "telnet") == 0) service_telnet(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "ftp") == 0) service_ftp(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "pop3") == 0) service_pop3(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "imap") == 0) service_imap(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "ldap") == 0) service_ldap(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "www") == 0) service_http(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "cisco") == 0) service_cisco(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "cisco-enable") == 0) service_cisco_enable(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "socks5") == 0) service_socks5(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "vnc") == 0) service_vnc(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "rexec") == 0) service_rexec(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "nntp") == 0) service_nntp(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "icq") == 0) service_icq(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "pcnfs") == 0) service_pcnfs(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "smb") == 0) service_smb(ip, socketpairs[i][1], options, miscptr, ofp, port);
-    if (strcmp(service, "mysql") == 0) service_mysql(ip, socketpairs[i][1], options, miscptr, ofp, port);
-// ADD NEW SERVICES HERE
-                return 0;
-            }
-            if (pids[i] > 0) {
-                write(socketpairs[i][1], "N", 1);
-                fcntl(socketpairs[i][0], F_SETFL, O_NONBLOCK);
-            } else {
-                perror("Fork for children failed");
+  /* fork attack processes */
+  signal(SIGCHLD, killed_childs);
+  signal(SIGTERM, kill_children);
+  signal(SIGSEGV, kill_children);
+  signal(SIGHUP, kill_children);
+  if (servers > countinfile)
+    servers = countinfile;
+  for (sID = 0; sID < servers; sID++) {                                    // PARALLEL HOSTS THREADS
+    if (socketpair(PF_UNIX, SOCK_STREAM, 0, addr_socketpairs[sID]) != 0) {
+      perror("socketpair failed");
+      addr_socketpairs[sID][1] = -1;
+    }
+    if ((addr_pids[sID] = fork()) == 0) {
+      close(addr_socketpairs[sID][1]);
+      char rc;
+      unsigned int socketpairs[MAXTASKS][2];
+      unsigned long int sent;
+      unsigned long int t_ip;
+      char t_ipaddr_str[INET_ADDRSTRLEN];
+      char *t_login_ptr; 
+      char *t_pass_ptr; 
+      char *t_pass_ptr_save;
+      int gkilled = 0;
+
+      void killed_gchilds(int signo) {
+        gkilled++;
+        (void) wait3(NULL, WNOHANG, NULL);
+      }
+
+      void kill_gchildren(int signo) {
+        int i;
+        for (i = 0; i < MAXTASKS; i++)
+          if (pids[i] > 0)
+            kill(pids[i], SIGTERM);
+        sleep(1);
+        if (pids[i] > 0)
+          kill(pids[i], SIGKILL);
+        exit(0);
+      }
+
+      signal(SIGCHLD, killed_gchilds);
+      signal(SIGTERM, kill_gchildren);
+      signal(SIGSEGV, kill_gchildren);
+      signal(SIGHUP, kill_gchildren);
+
+      while (1) { // Wait for Address
+        wait_addr:
+        if (read(addr_socketpairs[sID][0], &rc, 1) > 0) {
+          if (rc == 'N') {
+            write(addr_socketpairs[sID][0], "N", 1);
+            sleep(1);
+          } else if (rc == 'Q') {
+            exit(0);
+          } else if (rc == 'Y') {
+            read(addr_socketpairs[sID][0], &t_ip, sizeof(t_ip));
+            inet_ntop(AF_INET, &t_ip, t_ipaddr_str, sizeof(t_ipaddr_str));
+
+            t_login_ptr = login_ptr;
+            t_pass_ptr = pass_ptr;
+            sent = 0;
+            gkilled = 0;
+
+            for(i = 0; i < tasks; i++) {                            // PARALLEL LOGIN THREADS
+              if (socketpair(PF_UNIX, SOCK_STREAM, 0, socketpairs[i]) != 0) {
+                perror("socketpair failed");
                 socketpairs[i][0] = -1;
+              } else {
+                if ((pids[i] = fork()) == 0) {
+                  signal(SIGTERM, exit);
+                  signal(SIGHUP, exit);
+                  if (strcmp(service, "telnet") == 0) service_telnet(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "ftp") == 0) service_ftp(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "pop3") == 0) service_pop3(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "imap") == 0) service_imap(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "ldap") == 0) service_ldap(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "www") == 0) service_http(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "cisco") == 0) service_cisco(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "cisco-enable") == 0) service_cisco_enable(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "socks5") == 0) service_socks5(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "vnc") == 0) service_vnc(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "rexec") == 0) service_rexec(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "nntp") == 0) service_nntp(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "icq") == 0) service_icq(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "pcnfs") == 0) service_pcnfs(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "smb") == 0) service_smb(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "smbnt") == 0) service_smbnt(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  if (strcmp(service, "mysql") == 0) service_mysql(t_ip, socketpairs[i][1], options, miscptr, ofp, port);
+                  // ADD NEW SERVICES HERE
+                  return 0;
+                }
+                if (pids[i] > 0) {
+                  write(socketpairs[i][1], "N", 1);
+                  fcntl(socketpairs[i][0], F_SETFL, O_NONBLOCK);
+                } else {
+                  perror("Fork for children failed");
+                  socketpairs[i][0] = -1;
+                }
+              }
+              if ((((i+1) % group) == 0) && ((i+1) != tasks)) sleep(1);
             }
-        }
-        if ((((i+1) % group) == 0) && ((i+1) != tasks)) sleep(1);
-    }
 
-    /* feed the children with login/pass data - be a good mom */
-    {
-        int a, b, c, done, length;
-        char sb[MAXBUF], rc;
-        pass_ptr_save = pass_ptr;
-        
-        for (a = 0; a < countlogin; a++) {
-            for (b = 0; b < countpass; b++) {
-                done = 0;
-                if ((char *) pass_ptr != (char *) &HYDRA_EXIT) {
+            /* feed the (grand)children with login/pass data - be a good mom */
+            {
+              int a, b, c, done, length;
+              char sb[MAXBUF], rc;
+              t_pass_ptr_save = t_pass_ptr;
+
+              for (a = 0; a < countlogin; a++) {
+                for (b = 0; b < countpass; b++) {
+                  done = 0;
+                  if ((char *) t_pass_ptr != (char *) &HYDRA_EXIT) {
                     while(! done) {
-                        i = 0;
-                        for(c = 0; c < tasks; c++) {
-                            if (! done && socketpairs[c][0] >= 0) {
-                                if (read(socketpairs[c][0], &rc, 1) > 0) {
-                                    if (rc == 'F') {
-                                        char *cracked_login = malloc(MAXBUF);
-                                        if (exit_found) {
-                                            sleep(1);
-                                            for (i = 0; i < tasks; i++)
-                                                if (pids[i] > 0)
-                                                    (void) kill(pids[i], SIGTERM);
-                                            sleep(1);
-                                            fclose(ofp);
-                                            printf("%s Finished.\n", PROGRAM);
-                                            exit(0);
-                                        }
-                                        memset(cracked_login, 0, MAXBUF);
-                                        read(socketpairs[c][0], cracked_login, MAXBUF);
-                                        if (colonfile == NULL) {
-                                            if (strcmp(cracked_login, login_ptr) == 0) {
-                                                a++;
-                                                if (a < countlogin) {
-                                                    while (*login_ptr != '\0') login_ptr++;
-                                                    login_ptr++;
-                                                    pass_ptr = pass_ptr_save;
-                                                    sent += countpass - b;
-                                                    b = 0;
-                                                } else {
-                                                    rc = 'X';
-                                                    b = countpass;
-                                                    sent = todo;
-                                                    done = 1;
-                                                }
-                                                if (verbose)
-                                                    printf("The password for \"%s\" was found, skipping to next login (pairs already sent to childrens will still be tried)\n", cracked_login);
-                                            }
-                                        }
-                                    }
-                                    if (rc == 'N' || rc == 'F') {
-                                        done = 1;
-                                        sent++;
-                                        memset(&sb, 0, sizeof(sb));
-                                        length = strlen(login_ptr) + 1;
-                                        strcpy(sb, login_ptr);
-                                        if (b < try_password_same_as_login + try_null_password) {
-                                            if (try_null_password && b == 0) {
-                                                length += 1;
-                                            }
-                                            if (try_password_same_as_login && ((b == 0 && try_null_password == 0) || (b == 1 && try_null_password))) {
-                                                strcpy(sb + length, login_ptr);
-                                                length += strlen(login_ptr) + 1;
-                                            }
-                                        } else {
-                                            while (((try_password_same_as_login && strcmp(pass_ptr, login_ptr) == 0)
-                                                   ||
-                                                  (try_null_password && strlen(pass_ptr) == 0)) && b < countpass) {
-                                                if (verbose)
-                                                    printf("Detected double with -e n|s option, skipping double password try. %s <-> %s\n", login_ptr, pass_ptr);
-                                                pass_ptr += strlen(pass_ptr) + 1;
-                                                b++;
-                                                sent++;
-                                            }
-                                            if (b == countpass) {
-                                                strcpy(sb + length, "THChydra");
-                                                length += 9;
-                                                b = countpass - 1;
-                                                if (sent > todo)
-                                                    sent = todo;
-                                            } else {
-                                                strcpy(sb + length, pass_ptr);
-                                                length += strlen(pass_ptr) + 1;
-                                            }
-                                        }
-                                        if (verbose)
-                                            printf("New pair: login \"%s\" - pass \"%s\" \t(%lu of %lu completed)\n", sb, sb + strlen(sb) + 1, sent, todo);
-                                        write(socketpairs[c][0], sb, length);
-                                        if (debug) printf("Pair sent to process %d\n", pids[c]);
-                                    } else {
-                                        if (debug) printf("Process %d reported it quit\n",pids[c]);
-                                        socketpairs[c][0] = -1;
-                                        pids[c] = 0;
-                                        i++;
-                                        (void) wait3(NULL, WNOHANG, NULL);
-                                    }
+                      i = 0;
+                      for(c = 0; c < tasks; c++) {
+                        if (! done && socketpairs[c][0] >= 0) {
+                          if (read(socketpairs[c][0], &rc, 1) > 0) {
+                            if (rc == 'F') {
+                              char *cracked_login = malloc(MAXBUF);
+                              if (exit_found) {
+                                sleep(1);
+                                for (i = 0; i < tasks; i++)
+                                  if (pids[i] > 0)
+                                    (void) kill(pids[i], SIGTERM);
+                                printf("%s Finished scan for %s\n", PROGRAM, t_ipaddr_str);
+                                write(addr_socketpairs[sID][0], "Q", 1);
+                                goto wait_addr;
+                              }
+                              memset(cracked_login, 0, MAXBUF);
+                              read(socketpairs[c][0], cracked_login, MAXBUF);
+                              if (colonfile == NULL) {
+                                if (strcmp(cracked_login, t_login_ptr) == 0) {
+                                  a++;
+                                  if (a < countlogin) {
+                                    while (*t_login_ptr != '\0') t_login_ptr++;
+                                    t_login_ptr++;
+                                    t_pass_ptr = t_pass_ptr_save;
+                                    sent += countpass - b;
+                                    b = 0;
+                                  } else {
+                                    rc = 'X';
+                                    b = countpass;
+                                    sent = todo;
+                                    done = 1;
+                                  }
+                                  if (verbose)
+                                    printf("The password for \"%s\" was found, skipping to next login (pairs already sent to childrens will still be tried)\n", cracked_login);
+                                }
+                              }
+                            }
+                            if (rc == 'N' || rc == 'F') {
+                              done = 1;
+                              sent++;
+
+                              if ((verbose) || (showAttempt)) {
+                                if (b < try_null_password + try_password_same_as_login) {
+                                  if (try_null_password && b == 0)
+                                    printf("New pair: host: \"%s\"\t login \"%s\" - pass \"\" \t(%lu of %lu completed)\n", t_ipaddr_str, t_login_ptr, sent, todo);
+                                  if (try_password_same_as_login && ((b == 0 && try_null_password == 0) || (b == 1 && try_null_password)))
+                                    printf("New pair: host: \"%s\"\t login \"%s\" - pass \"%s\" \t(%lu of %lu completed)\n", t_ipaddr_str, t_login_ptr, t_login_ptr, sent, todo);
+                                } else
+                                  printf("New pair: host: \"%s\"\t login \"%s\" - pass \"%s\" \t(%lu of %lu completed)\n", t_ipaddr_str, t_login_ptr, t_pass_ptr, sent, todo);
+                              }
+
+                              memset(&sb, 0, sizeof(sb));
+                              length = strlen(t_login_ptr) + 1;
+                              strcpy(sb, t_login_ptr);
+                              if (b < try_password_same_as_login + try_null_password) {
+                                if (try_null_password && b == 0) {
+                                  length += 1;
+                                }
+                                if (try_password_same_as_login && ((b == 0 && try_null_password == 0) || (b == 1 && try_null_password))) {
+                                  strcpy(sb + length, t_login_ptr);
+                                  length += strlen(t_login_ptr) + 1;
                                 }
-                            } else i++;
-                        }
-                        if (i >= tasks || killed >= tasks) {
-                            printf("All childrens are dead.\n");
-                            exit(-1);
-                        }
+                              } else {
+                                while (((try_password_same_as_login && strcmp(t_pass_ptr, t_login_ptr) == 0)
+                                      || (try_null_password && strlen(t_pass_ptr) == 0)) && b < countpass) {
+                                  if (verbose)
+                                    printf("Detected double with -e n|s option, skipping double password try. %s <-> %s\n", t_login_ptr, t_pass_ptr);
+                                  t_pass_ptr += strlen(t_pass_ptr) + 1;
+                                  b++;
+                                  sent++;
+                                }
+                                if (b == countpass) {
+                                  strcpy(sb + length, "THChydra");
+                                  length += 9;
+                                  b = countpass - 1;
+                                  if (sent > todo)
+                                    sent = todo;
+                                } else {
+                                  strcpy(sb + length, t_pass_ptr);
+                                  length += strlen(t_pass_ptr) + 1;
+                                }
+                              }
+                              if (verbose)
+                                printf("New pair: login \"%s\" - pass \"%s\" \t(%lu of %lu completed)\n", sb, sb + strlen(sb) + 1, sent, todo);
+                              write(socketpairs[c][0], sb, length);
+                              if (debug) printf("Pair sent to process %d\n", pids[c]);
+                            } else {
+                              if (debug) printf("Process %d reported it quit\n",pids[c]);
+                              socketpairs[c][0] = -1;
+                              pids[c] = 0;
+                              i++;
+                              (void) wait3(NULL, WNOHANG, NULL);
+                            }
+                          }
+                        } else i++;
+                      }
+                      if (i >= tasks || killed >= tasks) {
+                        printf("All childrens are dead.\n");
+                        fprintf(stderr, "Server (%s) scan complete\n", t_ipaddr_str);
+                        write(addr_socketpairs[sID][0], "Q", 1);
+                        goto wait_addr;
+                      }
                     }
+                  }
+                  if (b < countpass && b >= try_password_same_as_login + try_null_password) {
+                    while(*t_pass_ptr != '\0') t_pass_ptr++;
+                    t_pass_ptr++;
+                  }
                 }
-                if (b < countpass && b >= try_password_same_as_login + try_null_password) {
-                    while(*pass_ptr != '\0') pass_ptr++;
-                    pass_ptr++;
-                }
-            }
-            if (a < countlogin) {
-                while(*login_ptr != '\0') login_ptr++;
-                login_ptr++;
-            }
-            if (colonfile == NULL) {
-                pass_ptr = pass_ptr_save;
-            } else {
-                if ((char *) pass_ptr != (char *) &HYDRA_EXIT) {
-                    while(*login_ptr != '\0') login_ptr++;
-                    login_ptr++;
+                if (a < countlogin) {
+                  while(*t_login_ptr != '\0') t_login_ptr++;
+                  t_login_ptr++;
                 }
-                pass_ptr = login_ptr;
-                while(*pass_ptr != '\0' && *pass_ptr != ':') pass_ptr++;
-                if (*pass_ptr == ':') {
-                    *pass_ptr = '\0';
-                    pass_ptr++;
+                if (colonfile == NULL) {
+                  t_pass_ptr = t_pass_ptr_save;
                 } else {
-                    if (strlen(login_ptr) > 0) fprintf(stderr, "Invalid line in colonfile: %s\n", login_ptr);
-                    pass_ptr = HYDRA_EXIT;
+                  if ((char *) t_pass_ptr != (char *) &HYDRA_EXIT) {
+                    while(*t_login_ptr != '\0') t_login_ptr++;
+                    t_login_ptr++;
+                  }
+                  t_pass_ptr = t_login_ptr;
+                  while(*t_pass_ptr != '\0' && *t_pass_ptr != ':') t_pass_ptr++;
+                  if (*t_pass_ptr == ':') {
+                    *t_pass_ptr = '\0';
+                    t_pass_ptr++;
+                  } else {
+                    if (strlen(t_login_ptr) > 0) fprintf(stderr, "Invalid line in colonfile: %s\n", t_login_ptr);
+                    t_pass_ptr = HYDRA_EXIT;
+                  }
                 }
-            }
-        }
+              }
 
-        i = 0;
-        j = 0;
-        (void) wait3(NULL, WNOHANG, NULL);
-        if (verbose) printf("Waiting for children to finnish their jobs ...\n");
-        while(i < tasks && j < 5) {
-            i = 0;
-            for(c = 0; c < tasks; c++) {
-                if (socketpairs[c][0] >= 0) {
+              i = 0;
+              j = 0;
+              (void) wait3(NULL, WNOHANG, NULL);
+              if (verbose) printf("Waiting for children to finnish their jobs ...\n");
+              while(i < tasks && j < 5) {
+                i = 0;
+                for(c = 0; c < tasks; c++) {
+                  if (socketpairs[c][0] >= 0) {
                     if (read(socketpairs[c][0], &rc, 1) > 0 || j == 4) {
-                        i++;
-                        (void) write(socketpairs[c][0], HYDRA_EXIT, sizeof(HYDRA_EXIT));
-                        socketpairs[c][0] = -1;
+                      i++;
+                      (void) write(socketpairs[c][0], HYDRA_EXIT, sizeof(HYDRA_EXIT));
+                      socketpairs[c][0] = -1;
                     }
-                } else i++;
-            }
-            if (i < tasks) {
-                j++;
-                sleep(1);
+                  } else i++;
+                }
+                if (i < tasks) {
+                  j++;
+                  sleep(1);
+                }
+              }
+
+          	  i = 0;
+          	  j = 1;
+              while (j > 0 && killed < tasks && i <= (WAITTIME + tasks + 6)) {
+          	    j = 0;
+          	    (void) wait3(NULL, WNOHANG, NULL);
+          	    for(c = 0; c < tasks; c++) {
+          	      if (pids[c] > 0)
+          	         if (kill(pids[c], 0) >= 0)
+          	           j++; 
+          	  }
+          	  sleep(1);
+          	  i++;
+          	  if (debug) printf("tasks: %d   still alive: %d   killed: %d   time: %d of %d\n", tasks, j, killed, i, WAITTIME + tasks + 6);
+              }
             }
-        }
 
-	i = 0;
-	j = 1;
-        while (j > 0 && killed < tasks && i <= (WAITTIME + tasks + 6)) {
-	    j = 0;
-	    (void) wait3(NULL, WNOHANG, NULL);
-	    for(c = 0; c < tasks; c++) {
-	        if (pids[c] > 0)
-	           if (kill(pids[c], 0) >= 0)
-	               j++; 
-	    }
-	    sleep(1);
-	    i++;
-	    if (debug) printf("tasks: %d   still alive: %d   killed: %d   time: %d of %d\n", tasks, j, killed, i, WAITTIME + tasks + 6);
-        }
+            for(i = 0; i < tasks; i++)
+              if (pids[i] > 0)
+                 kill(pids[i], SIGTERM);
+
+            fprintf(stderr, "Server (%s) scan complete\n", t_ipaddr_str);
+            write(addr_socketpairs[sID][0], "Q", 1);
+            goto wait_addr;
+          }
+        }
+      } // loop while waiting for an address
+    } // IP scanners fork
+
+    close(addr_socketpairs[sID][0]);
+    if (addr_pids[sID] > 0) {
+      write(addr_socketpairs[sID][1], "N", 1);
+      fcntl(addr_socketpairs[sID][0], F_SETFL, O_NONBLOCK);
+      fcntl(addr_socketpairs[sID][1], F_SETFL, O_NONBLOCK);
+    } else {
+      perror("Fork for children failed");
+      addr_socketpairs[sID][0] = -1;
     }
+  }
 
-    for(i = 0; i < tasks; i++)
-        if (pids[i] > 0)
-           kill(pids[i], SIGTERM);
+  /* feed the children with ip address data - be a good mom */
+  int a = 0, scans = 0, done = 0;
+  char rc;
+  while (done < countinfile) {
+    for (a=0; a < servers; a++) {
+      if (read(addr_socketpairs[a][1], &rc, 1) > 0) {
+        read(addr_socketpairs[a][1], &rc, 1);
+        if (rc == 'N') {
+          scans++;
+
+          /* resolve target */
+          if (inet_pton(AF_INET, ipaddr_ptr, &in) <= 0) {
+            if ((target = gethostbyname(ipaddr_ptr)) != NULL)
+              memcpy(&ip, target->h_addr, 4);
+          } else {
+            memcpy(&ip, &in.s_addr, 4);
+          }
+
+          if ((target = gethostbyname(ipaddr_ptr)) == NULL) {
+            done++;
+            fprintf(stderr, "Error: invalid server address: %s\n", ipaddr_ptr);
+            write(addr_socketpairs[a][1], "N", 1);
+          } else {
+            write(addr_socketpairs[a][1], "Y", 1);
+            write(addr_socketpairs[a][1], &ip, sizeof(ip));
+          }
+
+          if (scans < countinfile) {
+            while (*ipaddr_ptr != '\0') ipaddr_ptr++;
+            ipaddr_ptr++;
+          }
+        } else if (rc == 'Q') {
+          done++;
+          /* scan finished. should proc start another? */
+          if (scans < countinfile)
+            write(addr_socketpairs[a][1], "N", 1);
+          else {
+            write(addr_socketpairs[a][1], "Q", 1);
+            addr_pids[a] = 0;
+          }
+        }
+      }
+    }
+  }
 
-    /* yeah we did it */
-    printf("%s finished.\n", PROGRAM);
+  /* yeah we did it */
+  printf("%s finished.\n", PROGRAM);
 
-    fclose(ofp);
+  fclose(ofp);
 
-    return 0;
+  return 0;
 }
 
 
 #ifndef NESSUS_PLUGIN
 int main(int argc, char * argv[]) {
-    return hydra_main(-1, NULL, argc, argv);
+  return hydra_main(-1, NULL, argc, argv);
 }
 #endif
diff -uN hydra-2.4/hydra-cisco.c hydra-2.4-m0j0/hydra-cisco.c
--- hydra-2.4/hydra-cisco.c	2002-03-24 06:10:06.000000000 -0600
+++ hydra-2.4-m0j0/hydra-cisco.c	2003-10-14 14:28:56.000000000 -0500
@@ -3,121 +3,120 @@
 extern char *HYDRA_EXIT;
 char *buf;
 
-int start_cisco(int s, int port, unsigned char options,char *miscptr,FILE *fp) {
-    char *empty = "";
-    char *pass, buffer[300];
-
+int start_cisco(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
+  char *empty = "";
+  char *pass, buffer[300];
+
+  if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
+
+  // maybe \r\n or \r\000 needed instead of a single \n ?
+  sprintf(buffer, "%.250s\r\n", pass);
+  if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
+    return 1;
+  }
+  buf = hydra_receive_line(s);
+  if (strstr(buf, "assw") != NULL) {
+    hydra_completed_pair();
+    free(buf);
+    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+      return 3;
     if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
-
-// maybe \r\n or \r\000 needed instead of a single \n ?
     sprintf(buffer, "%.250s\r\n", pass);
     if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
-        return 1;
+      return 1;
     }
     buf = hydra_receive_line(s);
     if (strstr(buf, "assw") != NULL) {
-        hydra_completed_pair();
-        free(buf);
-        if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
-            return 3;
-        if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
-        sprintf(buffer, "%.250s\r\n", pass);
-        if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
-            return 1;
-        }
-        buf = hydra_receive_line(s);
-        if (strstr(buf, "assw") != NULL) {
-            hydra_completed_pair();
-            free(buf);
-            if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
-                return 3;
-            if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
-            sprintf(buffer, "%.250s\r\n", pass);
-            if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
-                return 1;
-            }
-            buf = hydra_receive_line(s);
-	}
-
-    }
-
-    if (strstr(buf, "assw") != NULL || strstr(buf, "ad ") != NULL || strstr(buf, "attempt") != NULL || strstr(buf, "fail") != NULL) {
-        free(buf);
-        hydra_completed_pair();
-        if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
-            return 3;
+      hydra_completed_pair();
+      free(buf);
+      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+        return 3;
+      if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
+      sprintf(buffer, "%.250s\r\n", pass);
+      if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
         return 1;
+      }
+      buf = hydra_receive_line(s);
     }
+  }
 
-    hydra_report_found(port, "cisco", fp);
-    hydra_completed_pair_found();
-    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
-        return 3;
+  if (strstr(buf, "assw") != NULL || strstr(buf, "ad ") != NULL || strstr(buf, "attempt") != NULL || strstr(buf, "fail") != NULL) {
     free(buf);
+    hydra_completed_pair();
+    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+      return 3;
     return 1;
+  }
+
+  hydra_report_found_host(port, ip, "cisco", fp);
+  hydra_completed_pair_found();
+  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+    return 3;
+  free(buf);
+  return 1;
 }
 
 void service_cisco(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port) {
-    int run = 1, failc = 0, retry = 1, next_run, sock = -1;
-    int myport = PORT_TELNET, mysslport = PORT_TELNET_SSL;
+  int run = 1, failc = 0, retry = 1, next_run, sock = -1;
+  int myport = PORT_TELNET, mysslport = PORT_TELNET_SSL;
 
-    hydra_register_socket(sp);
-    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
-        return;
-    while(1) {
-        next_run = 0;
-        switch(run) {
-            case 1: /* connect and service init function */
-                   {
-                    unsigned char *buf2 = malloc(256);
-                    int f = 0;
-                    if (sock >= 0) sock = hydra_disconnect(sock);
-                    usleep(275000);
-                    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 (sock < 0) {
-                        fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
-                        hydra_child_exit();
-                    }
-                    do {
-                        if (f != 0) free(buf2); else f = 1;
-                        if ((buf2 = hydra_receive_line(sock)) == NULL) {
-                            if (failc < retry) {
-                                next_run = 1;
-                                failc++;
-			        fprintf(stderr, "Error: Child with pid %d was disconnected - retrying (%d of %d retries)\n", (int)getpid(), failc, retry);
-			        sleep(3);
-                                break;
-                            } else {
-			        fprintf(stderr, "Error: Child with pid %d was disconnected - exiting\n", (int)getpid());
-			        hydra_child_exit();
-			    }
-                        }
-                    } while ( strstr(buf2, "assw") == NULL);
-                    free(buf2);
-                    if (next_run != 0) break;
-                    failc = 0;
-                    next_run = 2;
-                    break;
-                   }
-            case 2: /* run the cracking function */
-                    next_run = start_cisco(sock, port, options, miscptr, fp);
-                    break;
-            case 3: /* clean exit */
-                    if (sock >= 0) sock = hydra_disconnect(sock);
-                    hydra_child_exit();
-                    return;
-            default: fprintf(stderr,"Caught unknown return code, exiting!\n");
-                     hydra_child_exit();
-                     exit(-1);
+  hydra_register_socket(sp);
+  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+    return;
+  while(1) {
+    next_run = 0;
+    switch(run) {
+      case 1: /* connect and service init function */
+      {
+        unsigned char *buf2 = malloc(256);
+        int f = 0;
+        if (sock >= 0) sock = hydra_disconnect(sock);
+          usleep(275000);
+        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 (sock < 0) {
+          fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
+          hydra_child_exit();
         }
-        run = next_run;
+        do {
+          if (f != 0) free(buf2); else f = 1;
+          if ((buf2 = hydra_receive_line(sock)) == NULL) {
+            if (failc < retry) {
+              next_run = 1;
+              failc++;
+              fprintf(stderr, "Error: Child with pid %d was disconnected - retrying (%d of %d retries)\n", (int)getpid(), failc, retry);
+              sleep(3);
+              break;
+            } else {
+              fprintf(stderr, "Error: Child with pid %d was disconnected - exiting\n", (int)getpid());
+              hydra_child_exit();
+            }
+          }
+        } while ( strstr(buf2, "assw") == NULL);
+        free(buf2);
+        if (next_run != 0) break;
+        failc = 0;
+        next_run = 2;
+        break;
+      }
+      case 2: /* run the cracking function */
+        next_run = start_cisco(sock, ip, port, options, miscptr, fp);
+        break;
+      case 3: /* clean exit */
+        if (sock >= 0) sock = hydra_disconnect(sock);
+          hydra_child_exit();
+        return;
+      default: fprintf(stderr,"Caught unknown return code, exiting!\n");
+        hydra_child_exit();
+        exit(-1);
     }
+    run = next_run;
+  }
 }
diff -uN hydra-2.4/hydra-cisco-enable.c hydra-2.4-m0j0/hydra-cisco-enable.c
--- hydra-2.4/hydra-cisco-enable.c	2003-05-09 07:25:23.000000000 -0500
+++ hydra-2.4-m0j0/hydra-cisco-enable.c	2003-10-14 14:29:48.000000000 -0500
@@ -3,7 +3,7 @@
 extern char *HYDRA_EXIT;
 char *buf;
 
-int start_cisco_enable(int s,int port,unsigned char options,char *miscptr,FILE *fp) {
+int start_cisco_enable(int s,unsigned long int ip,int port,unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *pass, buffer[300];
 
@@ -49,7 +49,7 @@
         return 1;
     }
 
-    hydra_report_found(port, "cisco-enable", fp);
+    hydra_report_found_host(port, ip, "cisco-enable", fp);
     hydra_completed_pair_found();
     if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
         return 3;
@@ -133,7 +133,7 @@
                     break;
                    }
             case 2: /* run the cracking function */
-                    next_run = start_cisco_enable(sock, port, options, miscptr, fp);
+                    next_run = start_cisco_enable(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-ftp.c hydra-2.4-m0j0/hydra-ftp.c
--- hydra-2.4/hydra-ftp.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-ftp.c	2003-10-14 14:31:46.000000000 -0500
@@ -3,7 +3,7 @@
 extern char *HYDRA_EXIT;
 char *buf;
 
-int start_ftp(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_ftp(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "\"\"";
     char *login, *pass, buffer[300];
     int i = 1;
@@ -35,7 +35,7 @@
     if (buf == NULL)
         return 1;
     if (buf[0] == '2') {
-        hydra_report_found(port, "ftp", fp);
+        hydra_report_found_host(port, ip, "ftp", fp);
         hydra_completed_pair_found();
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
             return 3;
@@ -95,7 +95,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_ftp(sock,port, options, miscptr, fp);
+                    next_run = start_ftp(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-http.c hydra-2.4-m0j0/hydra-http.c
--- hydra-2.4/hydra-http.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-http.c	2003-10-14 14:31:32.000000000 -0500
@@ -49,7 +49,7 @@
     strcpy(buf, bof);
 }
 
-int start_http(int s, int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_http(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[300], buffer2[110];
     char *header = "";  // XXX TODO:
@@ -82,7 +82,7 @@
 
     ptr = ((char*)index(buf, ' ')) + 1;
     if (*ptr == '2') {
-        hydra_report_found(port, "www", fp);
+        hydra_report_found_host(port, ip, "www", fp);
         hydra_completed_pair_found();
     } else {
         if (*ptr != '4')
@@ -129,7 +129,7 @@
                     break;
                    }
             case 2: /* run the cracking function */
-                    next_run = start_http(sock, port, options, miscptr, fp);
+                    next_run = start_http(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-icq.c hydra-2.4-m0j0/hydra-icq.c
--- hydra-2.4/hydra-icq.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-icq.c	2003-10-14 14:32:25.000000000 -0500
@@ -130,7 +130,7 @@
     return (hydra_send(s, buf, 10, 0));
 }
 
-int start_icq(int sock, int port, FILE *output, char *miscptr, FILE *fp) {
+int start_icq(int sock, unsigned long int ip, int port, FILE *output, char *miscptr, FILE *fp) {
     unsigned char buf[1024];
     char *login, *pass;
     char *empty="";
@@ -159,7 +159,7 @@
 	}
 
 	if(buf[2] == 0x5a && buf[3] == 0x00)  {
-	    hydra_report_found(port, "icq", output);
+	    hydra_report_found_host(port, ip, "icq", output);
             hydra_completed_pair_found();
 	    icq_ack(sock, login);
 	    icq_login_1(sock, login);
@@ -212,7 +212,7 @@
 				next_run = 2;
 				break;
 			case 2:
-				next_run = start_icq(sock, port, fp, miscptr, fp);
+				next_run = start_icq(sock, ip, port, fp, miscptr, fp);
 				break;
 			case 3:
 				if(sock >= 0) sock = hydra_disconnect(sock);			
diff -uN hydra-2.4/hydra-imap.c hydra-2.4-m0j0/hydra-imap.c
--- hydra-2.4/hydra-imap.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-imap.c	2003-10-14 14:33:49.000000000 -0500
@@ -5,7 +5,7 @@
 char *buf;
 int counter;
 
-int start_imap(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_imap(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[300];
 
@@ -32,7 +32,7 @@
     }
     free(buf);
 
-    hydra_report_found(port, "imap", fp);
+    hydra_report_found_host(port, ip, "imap", fp);
     hydra_completed_pair_found();
     if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
         return 3;
@@ -55,11 +55,11 @@
                     if ((options & OPTION_SSL) == 0) {
                         if (port != 0) myport = port;
                         sock = hydra_connect_tcp(ip, myport);
-			port = myport;
+                        port = myport;
                     } else {
                         if (port != 0) mysslport = port;
                         sock = hydra_connect_ssl(ip, mysslport);
-			port = mysslport;
+                        port = mysslport;
                     }
                     if (sock < 0) {
                         fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
@@ -76,7 +76,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_imap(sock, port, options, miscptr, fp);
+                    next_run = start_imap(sock, ip, port, options, miscptr, fp);
                     counter++;
                     break;
             case 3: /* clean exit */
diff -uN hydra-2.4/hydra-ldap.c hydra-2.4-m0j0/hydra-ldap.c
--- hydra-2.4/hydra-ldap.c	2003-05-09 07:25:23.000000000 -0500
+++ hydra-2.4-m0j0/hydra-ldap.c	2003-10-14 14:39:18.000000000 -0500
@@ -20,7 +20,7 @@
 char *buf;
 int counter;
 
-int start_ldap(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_ldap(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login = "", *pass, buffer[512];
     int length;
@@ -55,7 +55,7 @@
     
     // success is: 0a 01 00 - failure is: 0a 01 31
     if ((buf[0] != 0 && buf[9] == 0) || (buf[0] != 32 && buf[9] == 32)) {
-        hydra_report_found(port, "ldap", fp);
+        hydra_report_found_host(port, ip, "ldap", fp);
         hydra_completed_pair_found();
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
             return 3;
@@ -105,7 +105,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_ldap(sock, port, options, miscptr, fp);
+                    next_run = start_ldap(sock, ip, port, options, miscptr, fp);
                     counter++;
                     break;
             case 3: /* clean exit */
diff -uN hydra-2.4/hydra-mod.c hydra-2.4-m0j0/hydra-mod.c
--- hydra-2.4/hydra-mod.c	2003-08-14 10:39:53.000000000 -0500
+++ hydra-2.4-m0j0/hydra-mod.c	2003-10-14 15:08:33.000000000 -0500
@@ -15,6 +15,7 @@
 int fail = 0;
 int alarm_went_off = 0;
 int use_ssl = 0;
+char ipaddr_str[INET_ADDRSTRLEN];
 
 #ifdef OPENSSL
  SSL     *ssl = NULL;
@@ -211,6 +212,11 @@
     fprintf(fp, "[%d][%s] login: %s   password: %s\n",port, svc, hydra_get_next_login(),hydra_get_next_password());
 }
 
+void hydra_report_found_host(int port, unsigned int ip, char * svc, FILE *fp) {
+    inet_ntop(AF_INET, &ip, ipaddr_str, sizeof(ipaddr_str));
+    fprintf(fp, "[%d][%s] host: %s   login: %s   password: %s\n",port, svc, ipaddr_str, hydra_get_next_login(),hydra_get_next_password());
+}
+
 int hydra_connect_ssl(unsigned long int host, int port) {
 #ifdef OPENSSL
     return (internal__hydra_connect_ssl(host, port, SOCK_STREAM, 6));
diff -uN hydra-2.4/hydra-mod.h hydra-2.4-m0j0/hydra-mod.h
--- hydra-2.4/hydra-mod.h	2002-03-24 05:46:11.000000000 -0600
+++ hydra-2.4-m0j0/hydra-mod.h	2003-10-14 13:59:07.000000000 -0500
@@ -15,6 +15,7 @@
 extern void  hydra_completed_pair();
 extern void  hydra_completed_pair_found();
 extern void  hydra_report_found(int port, char * svc, FILE *fp);
+extern void  hydra_report_found_host(int port, unsigned int ip, char * svc, FILE *fp);
 extern int   hydra_connect_ssl(unsigned long int host, int port);
 extern int   hydra_connect_tcp(unsigned long int host, int port);
 extern int   hydra_connect_udp(unsigned long int host, int port);
diff -uN hydra-2.4/hydra-mysql.c hydra-2.4-m0j0/hydra-mysql.c
--- hydra-2.4/hydra-mysql.c	2003-08-20 04:34:21.000000000 -0500
+++ hydra-2.4-m0j0/hydra-mysql.c	2003-10-14 14:41:01.000000000 -0500
@@ -137,7 +137,7 @@
     return 0;
 }
 
-int start_mysql(int sock, int port, unsigned char options, char* miscptr, FILE *fp)
+int start_mysql(int sock, unsigned long int ip, int port, unsigned char options, char* miscptr, FILE *fp)
 {
     char *response = NULL, *login = NULL, *pass = NULL;
     unsigned long response_len;
@@ -178,7 +178,7 @@
     if(!res) {
 	hydra_mysql_send_com_quit(sock);
 	sock = hydra_disconnect(sock);
-	hydra_report_found(port, "mysql", fp);
+	hydra_report_found_host(port, ip, "mysql", fp);
 	hydra_completed_pair_found();
 	free(response);
 	if(memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -223,7 +223,7 @@
 	    next_run = 2;
 	    break;
 	case 2 : /* run the cracking function */
-	    next_run = start_mysql(sock, port, options, miscptr, fp);
+	    next_run = start_mysql(sock, ip, port, options, miscptr, fp);
 	    break;
 	case 3 : /* clean exit */
 	    if (sock >= 0) {
diff -uN hydra-2.4/hydra-nntp.c hydra-2.4-m0j0/hydra-nntp.c
--- hydra-2.4/hydra-nntp.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-nntp.c	2003-10-14 14:41:42.000000000 -0500
@@ -3,7 +3,7 @@
 extern char *HYDRA_EXIT;
 char *buf;
 
-int start_nntp(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_nntp(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "\"\"";
     char *login, *pass, buffer[300];
     int i = 1;
@@ -35,7 +35,7 @@
     if (buf == NULL)
         return 1;
     if (buf[0] == '2') {
-        hydra_report_found(port, "nntp", fp);
+        hydra_report_found_host(port, ip, "nntp", fp);
         hydra_completed_pair_found();
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
             return 3;
@@ -95,7 +95,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_nntp(sock, port, options, miscptr, fp);
+                    next_run = start_nntp(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-pcnfs.c hydra-2.4-m0j0/hydra-pcnfs.c
--- hydra-2.4/hydra-pcnfs.c	2003-08-20 04:43:23.000000000 -0500
+++ hydra-2.4-m0j0/hydra-pcnfs.c	2003-10-14 14:42:30.000000000 -0500
@@ -33,7 +33,7 @@
 
 // Lets start ...
 
-int start_pcnfs(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_pcnfs(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[LEN_HDR_RPC+LEN_AUTH_UNIX+LEN_HDR_PCN_AUTH];
     char *ptr, *pkt = buffer;
@@ -112,7 +112,7 @@
     }   
 
     if (buf[27] == 32 && buf[28] == 32 && buf[29] == 32 ) {
-        hydra_report_found(port, "pcnfs", fp);
+        hydra_report_found_host(port, ip, "pcnfs", fp);
         hydra_completed_pair_found();
         free(buf);
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -160,7 +160,7 @@
                     break;
                    }
             case 2: /* run the cracking function */
-                    next_run = start_pcnfs(sock, port, options, miscptr, fp);
+                    next_run = start_pcnfs(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-pop3.c hydra-2.4-m0j0/hydra-pop3.c
--- hydra-2.4/hydra-pop3.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-pop3.c	2003-10-14 14:43:07.000000000 -0500
@@ -4,7 +4,7 @@
 
 char *buf;
 
-int start_pop3(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_pop3(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "\"\"";
     char *login, *pass, buffer[300];
 
@@ -34,7 +34,7 @@
     }
     if ((buf = hydra_receive_line(s)) == NULL) return(1);
     if (buf[0] == '+') {
-        hydra_report_found(port, "pop3", fp);
+        hydra_report_found_host(port, ip, "pop3", fp);
         hydra_completed_pair_found();
         free(buf);
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -85,7 +85,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_pop3(sock, port, options, miscptr, fp);
+                    next_run = start_pop3(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-rexec.c hydra-2.4-m0j0/hydra-rexec.c
--- hydra-2.4/hydra-rexec.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-rexec.c	2003-10-14 14:43:48.000000000 -0500
@@ -5,7 +5,7 @@
 extern char *HYDRA_EXIT;
 char *buf;
 
-int start_rexec(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_rexec(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[300] = "", buffer2[100], *bptr = buffer2;
     int ret;
@@ -31,7 +31,7 @@
     ret = hydra_recv(s, buffer, sizeof(buffer));
 
     if (ret > 0 && buffer[0] == 0) {
-        hydra_report_found(port, "rexec", fp);
+        hydra_report_found_host(port, ip, "rexec", fp);
         hydra_completed_pair_found();
     } else
         hydra_completed_pair();
@@ -72,7 +72,7 @@
                     break;
                    }
             case 2: /* run the cracking function */
-                    next_run = start_rexec(sock, port, options, miscptr, fp);
+                    next_run = start_rexec(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-smb.c hydra-2.4-m0j0/hydra-smb.c
--- hydra-2.4/hydra-smb.c	2003-05-09 07:25:23.000000000 -0500
+++ hydra-2.4-m0j0/hydra-smb.c	2003-10-14 14:45:38.000000000 -0500
@@ -85,8 +85,7 @@
  	return -1;	/* failed */
 }
 
-int 
-smb_login(int s, char *login, char *password) {
+int smb_login(int s, char *login, char *password) {
     int len = strlen(login) + strlen(password) + 57;
     int bcc = 2 + strlen(login) + strlen(password);
     int len_hi = len / 256, len_low = len % 256;
@@ -132,7 +131,7 @@
        return -1;
 }
 
-int start_smb(int s, int port, unsigned char options, char *miscptr, FILE *fp) {
+int start_smb(int s, unsigned long int ip, int port, unsigned char options, char *miscptr, FILE *fp) {
     char *empty = "";
     char *login, *pass;
 
@@ -140,7 +139,7 @@
     if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
 	
     if(smb_login(s, login, pass) == 0) {
-        hydra_report_found(port, "smb", fp);
+        hydra_report_found_host(port, ip, "smb", fp);
         hydra_completed_pair_found();
         free(buf);
 	hydra_disconnect(s);
@@ -191,7 +190,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_smb(sock, port, options, miscptr, fp);
+                    next_run = start_smb(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-smbnt.c hydra-2.4-m0j0/hydra-smbnt.c
--- hydra-2.4/hydra-smbnt.c	1969-12-31 18:00:00.000000000 -0600
+++ hydra-2.4-m0j0/hydra-smbnt.c	2003-10-14 14:24:28.000000000 -0500
@@ -0,0 +1,379 @@
+#include "hydra-mod.h"
+#include "md4.h"
+#include <des.h>
+
+/*
+   SMB NTLM Password/HASH Checking Hydra Module
+   Copyright (C) m0j0.j0j0
+   m0j0.j0j0 / m0j0@foofus.net 
+   09/30/2003
+
+   Based on code from: SMB Auditing Tool
+   [Copyright (C) Patrik Karlsson 2001]
+
+   This code allows Hydra to directly test NTLM hashes against
+   a Windows host via '-m HASH'. This may be useful for an 
+   auditor who has aquired a sam._ or pwdump file and would 
+   like to quickly determine which are valid entries. This 
+   module can also be used to test SMB passwords against devices 
+   that do not allow clear text LanMan passwords.
+
+   See http://www.foofus.net/m0j0/passhash.html for further
+   examples.
+
+   Greets: Foofus, Phenfen & Fizzgig  
+*/
+
+extern char *HYDRA_EXIT;
+char challenge[8];
+
+static u_char Get7Bits(u_char *input, int startBit) {
+  register unsigned int word;
+
+  word  = (unsigned)input[startBit / 8] << 8;
+  word |= (unsigned)input[startBit / 8 + 1];
+
+  word >>= 15 - (startBit % 8 + 7);
+
+  return word & 0xFE;
+}
+
+// Make the key
+static void MakeKey(u_char *key, u_char *des_key) {
+  des_key[0] = Get7Bits(key,  0);
+  des_key[1] = Get7Bits(key,  7);
+  des_key[2] = Get7Bits(key, 14);
+  des_key[3] = Get7Bits(key, 21);
+  des_key[4] = Get7Bits(key, 28);
+  des_key[5] = Get7Bits(key, 35);
+  des_key[6] = Get7Bits(key, 42);
+  des_key[7] = Get7Bits(key, 49);
+
+  des_set_odd_parity((des_cblock *)des_key);
+}
+
+// Do the DesEncryption
+void DesEncrypt(u_char *clear, u_char *key, u_char *cipher) {
+  des_cblock         des_key;
+  des_key_schedule   key_schedule;
+
+  MakeKey(key, des_key);
+  des_set_key(&des_key, key_schedule);
+  des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
+}
+
+/*
+  HashNTLM
+  Function: Create a NTLM hash from the challenge
+  Variables:
+        ntlmhash  = the hash created from this function
+        pass      = users password
+        challenge = the challenge recieved from the server
+*/
+void HashNTLM(u_char **ntlmhash, u_char *pass, u_char *challenge, char *miscptr) {
+  MD4_CTX             md4Context;
+  u_char              hash[16];                   // MD4_SIGNATURE_SIZE = 16
+  u_char              unicodePassword[256 * 2];   // MAX_NT_PASSWORD = 256
+  u_char              p21[21];
+  u_char              ntlm_response[24];
+  int                 i=0,j=0;
+  int                 mdlen = strlen(pass) * 2 * 8;
+  u_char              *p;
+  
+  /* Use NTLM Hash instead of password */
+  if ((miscptr != NULL) && (strcmp(miscptr, "HASH") == 0)) { 
+    // 1000:D42E35E1A1E4C22BD32E2170E4857C20:5E20780DD45857A68402938C7629D3B2:::
+    p = pass;
+    while ((*p != '\0') && (i < 2)) {
+      if (*p == ':') i++;
+      p++;
+    }
+
+    if (*p == '\0') {
+      fprintf(stderr, "Error reading PWDUMP file.\n");
+      exit(1);
+    }
+
+    char HexChar;
+    int HexValue;
+    for (i=0; i<16; i++) {
+      HexValue = 0x0;
+      for (j=0; j<2; j++) {
+        HexChar = (char)p[2*i+j];
+
+        if (HexChar > 0x39)
+          HexChar = HexChar | 0x20;  /* convert upper case to lower */
+
+        if (!(((HexChar >= 0x30) && (HexChar <= 0x39))||   /* 0 - 9 */
+              ((HexChar >= 0x61) && (HexChar <= 0x66)))) {    /* a - f */
+          //fprintf(stderr, "Error invalid char (%c) for hash.\n", HexChar);
+          //exit(1);
+          HexChar = 0x30;
+        }
+
+        HexChar -= 0x30;
+        if (HexChar > 0x09)  /* HexChar is "a" - "f" */
+          HexChar -= 0x27;
+
+        HexValue = (HexValue << 4) | (char)HexChar;
+      }
+      hash[i] = (u_char)HexValue;
+    }
+  } else {
+    /* 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(pass); i++)
+      unicodePassword[i * 2] = (u_char)pass[i];
+
+    MD4Init(&md4Context);
+    MD4Update(&md4Context, unicodePassword, mdlen);
+    MD4Final(hash, &md4Context);        /* Tell MD4 we're done */
+  }
+
+  memset(p21, '\0', 21);
+  memcpy(p21, hash, 16);
+
+  DesEncrypt(challenge, p21 +  0, ntlm_response + 0);
+  DesEncrypt(challenge, p21 +  7, ntlm_response + 8);
+  DesEncrypt(challenge, p21 + 14, ntlm_response + 16);
+                                                                                                                                                
+  memcpy(*ntlmhash, ntlm_response, 24);
+}
+
+/*
+   NBS Session Request
+   Function: Request a new session from the server
+   Returns: TRUE on success else FALSE.
+*/
+int NBSSessionRequest(int s) {
+  char nb_name[32];      // netbiosname
+  char nb_local[32];     // netbios localredirector
+  char rqbuf[7] = {0x81, 0x00, 0x00, 0x48, 0x20, 0x00, 0x20};
+  char *buf;
+  u_char rbuf[400];
+
+  // convert computer name to netbios name
+  memset(nb_name, 0, 32);
+  memset(nb_local, 0, 32);
+  memcpy(nb_name, "CKFDENECFDEFFCFGEFFCCACACACACACA", 32); // *SMBSERVER
+  memcpy(nb_local, "EIFJEEFCEBCACACACACACACACACACACA", 32); // HYDRA
+
+  buf = (char *) malloc(100);
+  memset(buf, 0, 100);
+  memcpy(buf, rqbuf, 5);
+  memcpy(buf+5, nb_name, 32);
+  memcpy(buf+37, rqbuf+5, 2);
+  memcpy(buf+39, nb_local, 32);
+  memcpy(buf+71, rqbuf+5, 1);
+
+  hydra_send(s, buf, 72, 0);
+  free(buf);
+
+  memset(rbuf, 0, 400);
+  hydra_recv(s, rbuf, sizeof(rbuf)); 
+
+  if (rbuf[0] == 0x82)
+    return 0;	    /* success */
+  else
+    return -1;     /* failed */
+}
+
+
+/*
+   SMBNegProt
+   Function: Negotiate protocol with server ...
+       Actually a pseudo negotiation since the whole
+       program counts on NTLM support :)
+
+    The challenge is retrieved from the answer
+    No error checking is performed i.e cross your fingers....
+*/
+int SMBNegProt(int s) {
+  char buf[168] = {0x00, 0x00, 0x00, 0xa4, 0xff, 0x53, 0x4d, 0x42,
+      0x72, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x40,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7d,
+      0x00, 0x00, 0x01, 0x00, 0x00, 0x81, 0x00, 0x02,
+      0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
+      0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
+      0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
+      0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f, 0x46,
+      0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52,
+      0x4b, 0x53, 0x20, 0x31, 0x2e, 0x30, 0x33, 0x00,
+      0x02, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f,
+      0x46, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
+      0x52, 0x4b, 0x53, 0x20, 0x33, 0x2e, 0x30, 0x00,
+      0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31,
+      0x2e, 0x30, 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e,
+      0x32, 0x58, 0x30, 0x30, 0x32, 0x00, 0x02, 0x53,
+      0x61, 0x6d, 0x62, 0x61, 0x00, 0x02, 0x4e, 0x54,
+      0x20, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x20,
+      0x31, 0x2e, 0x30, 0x00, 0x02, 0x4e, 0x54, 0x20,
+      0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00};
+
+  char rbuf[400];
+  memset(rbuf, 0, 400);
+
+  hydra_send(s, buf, 168, 0);
+  hydra_recv(s, rbuf, sizeof(rbuf)); 
+
+  // retrieve the challenge
+  memcpy(challenge, rbuf+73, sizeof(challenge));
+
+  return 2;
+}
+
+
+/*
+  SMBSessionSetup
+  Function: Send username + response to the challenge from
+            the server.
+       Currently we're sendin ZEROES for the LMHASH since
+       NT4/2000 doesn't seem to look at this if we got a
+       valid NTLM hash.
+  Returns: TRUE on success else FALSE.
+*/
+int SMBSessionSetup(int s, char *user, char *pass, char *miscptr) {
+  char b[137] = {0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d,
+        0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01,
+        0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+        0x7d, 0x00, 0x00, 0x01, 0x00, 0x0d, 0xff, 0x00,
+        0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x3c, 0x7d,
+        0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+        0x48, 0x00, 0xdf, 0x82, 0xb9, 0x2f, 0xda, 0xdb,
+        0x43, 0x47, 0x09, 0xdb, 0x7f, 0xfc, 0xb0, 0xa8,
+        0xf0, 0x46, 0xe2, 0xfe, 0x64, 0x6d, 0x67, 0x58,
+        0xe0, 0xf9, 0xca, 0x9f, 0x5e, 0xdb, 0xe0, 0x15,
+        0x80, 0xf8, 0x54, 0xe3, 0x6e, 0xe9, 0xf8, 0x88,
+        0x80, 0x19, 0xb6, 0xf9, 0xae, 0xb7, 0xa6, 0x62,
+        0x14, 0xfc, 0x54, 0x45, 0x53, 0x54, 0x00, 0x4d,
+        0x59, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x00, 0x55,
+        0x6e, 0x69, 0x78, 0x00, 0x53, 0x61, 0x6d, 0x62,
+        0x61, 0x00};
+
+  u_char buf[512];
+  u_char *NTLMhash;
+  u_char LMhash[24];
+  u_char workgroup[16];
+  u_char rbuf[400];
+  int userlen;
+
+  NTLMhash   = (u_char *) malloc(24);
+
+  memset(NTLMhash, 0, 24);
+  memset(LMhash, 0, 24);
+  memset(workgroup, 0, 16);
+  memset(rbuf, 0, 400);
+
+  HashNTLM(&NTLMhash, pass, challenge, miscptr);
+
+  memset(buf, 0, 512);
+  memcpy(buf, b, 89);
+  memcpy(buf+65, LMhash, 24);
+  memcpy(buf+89, NTLMhash, 24);
+
+  userlen = strlen(user);
+
+  memcpy(buf+113, user, userlen);
+  memset(buf+(113+userlen), 0, 1);
+  memcpy(buf+(114+userlen), workgroup, strlen(workgroup));
+  memcpy(buf+(114+userlen+strlen(workgroup)), b+125, 12);
+
+  // set the header length
+  buf[3] = ( userlen + strlen(workgroup) + 0x7A ) % 256;
+  buf[2] = ( userlen + strlen(workgroup) + 0x7A ) / 256;
+
+  // set data length
+  buf[63] = 0x1F + strlen(workgroup) + userlen;
+
+  hydra_send(s, buf, 126+userlen+strlen(workgroup), 0);
+
+  hydra_recv(s, rbuf, sizeof(rbuf));
+  return rbuf[9];
+}
+
+int start_smbnt(int s, unsigned long int ip, int port, unsigned char options, char *miscptr, FILE *fp) {
+  char *empty = "";
+  char *login, *pass;
+
+  if (strlen(login = hydra_get_next_login()) == 0) login = empty;
+  if (strlen(pass = hydra_get_next_password()) == 0) pass = empty;
+
+  int SMBerr = SMBSessionSetup(s, login, pass, miscptr);
+
+  if ( 0x00 == SMBerr ) {                  // success
+    hydra_report_found_host(port, ip, "smb", 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);
+    hydra_completed_pair_found();
+  }
+  else if ( 0x72 == SMBerr ) {             // account disabled
+    hydra_report_found_host(port, ip, "smb (account disabled)", fp);
+    hydra_completed_pair();
+  }
+  else if ( 0x34 == SMBerr ) {             // account locked out
+    fprintf(stderr, "[%d][smb] Account: %s is locked out\n", port, login); 
+    hydra_completed_pair();
+  }
+  else {                                   // failed
+    hydra_completed_pair();
+  }
+
+  hydra_disconnect(s);
+  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+    return 3;
+  return 1;
+}
+
+void 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;
+
+  hydra_register_socket(sp);
+  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
+    return;
+  for(;;) {
+    switch(run) {
+      case 1: /* connect and service init function */
+          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 (sock < 0) {
+            fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
+            hydra_child_exit();
+          }
+          if ( NBSSessionRequest(sock) < 0 ) {
+            fprintf(stderr, "Session Setup Failed: ");
+            fprintf(stderr, "(Is the server service running?)\n");
+            exit(-1);
+          }
+          next_run = SMBNegProt(sock);
+          break;
+      case 2: /* run the cracking function */
+          next_run = start_smbnt(sock, ip, port, options, miscptr, fp);
+          break;
+      case 3: /* clean exit */
+          if (sock >= 0) sock = hydra_disconnect(sock);
+          hydra_child_exit();
+          return;
+      default: fprintf(stderr,"Caught unknown return code (%d), exiting!\n", run);
+           hydra_child_exit();
+           exit(-1);
+    }
+    run = next_run;
+  }
+}
diff -uN hydra-2.4/hydra-socks5.c hydra-2.4-m0j0/hydra-socks5.c
--- hydra-2.4/hydra-socks5.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-socks5.c	2003-10-14 14:45:27.000000000 -0500
@@ -4,7 +4,7 @@
 
 unsigned char *buf;
 
-int start_socks5(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_socks5(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[300];
 
@@ -30,7 +30,7 @@
 
     if ((buf = hydra_receive_line(s)) == NULL) return(1);
     if (buf[1] != 255) {
-	hydra_report_found(port, "socks5", fp);
+	hydra_report_found_host(port, ip, "socks5", fp);
         hydra_completed_pair();
 	free(buf);
         if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -63,11 +63,11 @@
                     if ((options & OPTION_SSL) == 0) {
                         if (port != 0) myport = port;
                         sock = hydra_connect_tcp(ip, myport);
-			port = myport;
+                        port = myport;
                     } else {
                         if (port != 0) mysslport = port;
                         sock = hydra_connect_ssl(ip, mysslport);
-			port = mysslport;
+                        port = mysslport;
                     }
                     if (sock < 0) {
                         fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
@@ -76,7 +76,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_socks5(sock, port, options, miscptr, fp);
+                    next_run = start_socks5(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-telnet.c hydra-2.4-m0j0/hydra-telnet.c
--- hydra-2.4/hydra-telnet.c	2002-03-24 05:53:07.000000000 -0600
+++ hydra-2.4-m0j0/hydra-telnet.c	2003-10-14 14:48:55.000000000 -0500
@@ -7,7 +7,7 @@
 
 // added extra null byte sending via "+ 1" below ... should work!
 
-int start_telnet(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_telnet(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *login, *pass, buffer[300];
     int i = 0;
@@ -33,7 +33,7 @@
         if ((buf = hydra_receive_line(s)) == NULL)
 	    return 1;
         if (index(buf, '/') != NULL || index(buf, '>') != NULL || index(buf, '%') != NULL || index(buf, '$') != NULL || index(buf, '#') != NULL || index(buf, '%') != NULL) {
-            hydra_report_found(port, "telnet", fp);
+            hydra_report_found_host(port, ip, "telnet", fp);
             hydra_completed_pair_found();
             if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
                 return 3;
@@ -67,7 +67,7 @@
     while ((buf = hydra_receive_line(s)) != NULL && make_to_lower(buf) && 
            (strstr(buf, "login:") == NULL || strstr(buf, "last login:") != NULL) && strstr(buf, "sername:") == NULL) {
         if (index(buf, '/') != NULL || index(buf, '>') != NULL || index(buf, '%') != NULL || index(buf, '$') != NULL || index(buf, '#') != NULL || index(buf, '%') != NULL) {
-            hydra_report_found(port, "telnet", fp);
+            hydra_report_found_host(port, ip, "telnet", fp);
             hydra_completed_pair_found();
             free(buf);
             if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -154,7 +154,7 @@
                     next_run = 2;
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_telnet(sock, port, options, miscptr, fp);
+                    next_run = start_telnet(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/hydra-vnc.c hydra-2.4-m0j0/hydra-vnc.c
--- hydra-2.4/hydra-vnc.c	2003-08-20 04:36:35.000000000 -0500
+++ hydra-2.4-m0j0/hydra-vnc.c	2003-10-14 14:48:18.000000000 -0500
@@ -39,7 +39,7 @@
     }
 }
 
-int start_vnc(int s,int port, unsigned char options,char *miscptr,FILE *fp) {
+int start_vnc(int s, unsigned long int ip, int port, unsigned char options,char *miscptr,FILE *fp) {
     char *empty = "";
     char *pass;
 
@@ -57,7 +57,7 @@
 
     if ((buf = hydra_receive_line(s)) == NULL) return(1);
     switch (buf[3]) {
-        case 0: hydra_report_found(port, "vnc", fp);
+        case 0: hydra_report_found_host(port, ip, "vnc", fp);
                 hydra_completed_pair_found();
                 free(buf);
                 if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
@@ -96,11 +96,11 @@
                     if ((options & OPTION_SSL) == 0) {
                         if (port != 0) myport = port;
                         sock = hydra_connect_tcp(ip, myport);
-			port = myport;
+                        port = myport;
                     } else {
                         if (port != 0) mysslport = port;
                         sock = hydra_connect_ssl(ip, mysslport);
-			port = mysslport;
+                        port = mysslport;
                     }
                     if (sock < 0) {
                         fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid());
@@ -142,7 +142,7 @@
                     free(buf);
                     break;
             case 2: /* run the cracking function */
-                    next_run = start_vnc(sock, port, options, miscptr, fp);
+                    next_run = start_vnc(sock, ip, port, options, miscptr, fp);
                     break;
             case 3: /* clean exit */
                     if (sock >= 0) sock = hydra_disconnect(sock);
diff -uN hydra-2.4/ips.txt hydra-2.4-m0j0/ips.txt
--- hydra-2.4/ips.txt	1969-12-31 18:00:00.000000000 -0600
+++ hydra-2.4-m0j0/ips.txt	2003-10-14 15:38:19.000000000 -0500
@@ -0,0 +1,2 @@
+mike
+jack
diff -uN hydra-2.4/Makefile.am hydra-2.4-m0j0/Makefile.am
--- hydra-2.4/Makefile.am	2003-08-20 04:34:21.000000000 -0500
+++ hydra-2.4-m0j0/Makefile.am	2003-10-01 10:11:28.000000000 -0500
@@ -4,26 +4,26 @@
 
 CC = gcc
 OPTS = -O2 -I. -Wall
-LIBS = 
+LIBS =
 DIR = /bin
 
 SRC = hydra-vnc.c hydra-pcnfs.c hydra-rexec.c hydra-nntp.c hydra-socks5.c \
       hydra-telnet.c hydra-cisco.c hydra-http.c hydra-ftp.c hydra-imap.c \
       hydra-pop3.c hydra-smb.c hydra-icq.c hydra-cisco-enable.c hydra-ldap.c \
-      hydra-mysql.c d3des.c hydra-mod.c hydra.c
+      hydra-mysql.c hydra-smbnt.c d3des.c md4.c hydra-mod.c hydra.c
 OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
       hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
       hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
-      hydra-mysql.o d3des.o hydra-mod.o hydra.o
+      hydra-mysql.o hydra-smbnt.o d3des.o md4.o hydra-mod.o hydra.o
 BIN = hydra
 
 EXTRA_DIST = README CHANGES TODO INSTALL LICENSE.GNU LICENCE.HYDRA \
-             hydra-mod.h hydra.h d3des.h
+             hydra-mod.h hydra.h d3des.h md4.h
 
 all:	hydra
 
 hydra:	$(OBJ)
-	$(CC) $(OPTS) $(LIBS) -o $(BIN) $(OBJ) $(LIB) $(XLIBS) $(XLIBPATHS)
+	$(CC) $(OPTS) $(LIBS) -o $(BIN) $(OBJ) $(LIB) $(XLIBS) $(XLIBPATHS) $(LIBDES)
 	@echo
 	@echo If men could get pregnant, abortion would be a sacrament
 	@echo
diff -uN hydra-2.4/md4.c hydra-2.4-m0j0/md4.c
--- hydra-2.4/md4.c	1969-12-31 18:00:00.000000000 -0600
+++ hydra-2.4-m0j0/md4.c	2003-09-29 14:30:22.000000000 -0500
@@ -0,0 +1,297 @@
+/*
+** ********************************************************************
+** md4.c -- Implementation of MD4 Message Digest Algorithm           **
+** Updated: 2/16/90 by Ronald L. Rivest                              **
+** (C) 1990 RSA Data Security, Inc.                                  **
+** ********************************************************************
+*/
+
+/*
+** To use MD4:
+**   -- Include md4.h in your program
+**   -- Declare an MDstruct MD to hold the state of the digest
+**          computation.
+**   -- Initialize MD using MDbegin(&MD)
+**   -- For each full block (64 bytes) X you wish to process, call
+**          MD4Update(&MD,X,512)
+**      (512 is the number of bits in a full block.)
+**   -- For the last block (less than 64 bytes) you wish to process,
+**          MD4Update(&MD,X,n)
+**      where n is the number of bits in the partial block. A partial
+**      block terminates the computation, so every MD computation
+**      should terminate by processing a partial block, even if it
+**      has n = 0.
+**   -- The message digest is available in MD.buffer[0] ...
+**      MD.buffer[3].  (Least-significant byte of each word
+**      should be output first.)
+**   -- You can print out the digest using MDprint(&MD)
+*/
+
+/* Implementation notes:
+** This implementation assumes that ints are 32-bit quantities.
+*/
+
+#define TRUE  1
+#define FALSE 0
+
+/* Compile-time includes
+*/
+#include <stdio.h>
+#include "md4.h"
+
+/* Compile-time declarations of MD4 "magic constants".
+*/
+#define I0  0x67452301       /* Initial values for MD buffer */
+#define I1  0xefcdab89
+#define I2  0x98badcfe
+#define I3  0x10325476
+#define C2  013240474631     /* round 2 constant = sqrt(2) in octal */
+#define C3  015666365641     /* round 3 constant = sqrt(3) in octal */
+/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+** Table 2, page 660.
+*/
+
+#define fs1  3               /* round 1 shift amounts */
+#define fs2  7
+#define fs3 11
+#define fs4 19
+#define gs1  3               /* round 2 shift amounts */
+#define gs2  5
+#define gs3  9
+#define gs4 13
+#define hs1  3               /* round 3 shift amounts */
+#define hs2  9
+#define hs3 11
+#define hs4 15
+
+/* Compile-time macro declarations for MD4.
+** Note: The "rot" operator uses the variable "tmp".
+** It assumes tmp is declared as unsigned int, so that the >>
+** operator will shift in zeros rather than extending the sign bit.
+*/
+#define f(X,Y,Z)             ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z)             ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z)             (X^Y^Z)
+#define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s)      A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s)      A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s)      A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+/* MD4print(MDp)
+** Print message digest buffer MDp as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte of
+** buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+** This is a user-callable routine.
+*/
+void
+MD4Print(MDp)
+MD4_CTX *MDp;
+{
+  int i,j;
+  for (i=0;i<4;i++)
+    for (j=0;j<32;j=j+8)
+      printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+}
+
+/* MD4Init(MDp)
+** Initialize message digest buffer MDp.
+** This is a user-callable routine.
+*/
+void
+MD4Init(MDp)
+MD4_CTX *MDp;
+{
+  int i;
+  MDp->buffer[0] = I0;
+  MDp->buffer[1] = I1;
+  MDp->buffer[2] = I2;
+  MDp->buffer[3] = I3;
+  for (i=0;i<8;i++) MDp->count[i] = 0;
+  MDp->done = 0;
+}
+
+/* MDblock(MDp,X)
+** Update message digest buffer MDp->buffer using 16-word data block X.
+** Assumes all 16 words of X are full of data.
+** Does not update MDp->count.
+** This routine is not user-callable.
+*/
+static void
+MDblock(MDp,Xb)
+MD4_CTX *MDp;
+unsigned char *Xb;
+{
+  register unsigned int tmp, A, B, C, D;
+  unsigned int X[16];
+  int i;
+
+  for (i = 0; i < 16; ++i) {
+    X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
+    Xb += 4;
+  }
+
+  A = MDp->buffer[0];
+  B = MDp->buffer[1];
+  C = MDp->buffer[2];
+  D = MDp->buffer[3];
+  /* Update the message digest buffer */
+  ff(A , B , C , D ,  0 , fs1); /* Round 1 */
+  ff(D , A , B , C ,  1 , fs2);
+  ff(C , D , A , B ,  2 , fs3);
+  ff(B , C , D , A ,  3 , fs4);
+  ff(A , B , C , D ,  4 , fs1);
+  ff(D , A , B , C ,  5 , fs2);
+  ff(C , D , A , B ,  6 , fs3);
+  ff(B , C , D , A ,  7 , fs4);
+  ff(A , B , C , D ,  8 , fs1);
+  ff(D , A , B , C ,  9 , fs2);
+  ff(C , D , A , B , 10 , fs3);
+  ff(B , C , D , A , 11 , fs4);
+  ff(A , B , C , D , 12 , fs1);
+  ff(D , A , B , C , 13 , fs2);
+  ff(C , D , A , B , 14 , fs3);
+  ff(B , C , D , A , 15 , fs4);
+  gg(A , B , C , D ,  0 , gs1); /* Round 2 */
+  gg(D , A , B , C ,  4 , gs2);
+  gg(C , D , A , B ,  8 , gs3);
+  gg(B , C , D , A , 12 , gs4);
+  gg(A , B , C , D ,  1 , gs1);
+  gg(D , A , B , C ,  5 , gs2);
+  gg(C , D , A , B ,  9 , gs3);
+  gg(B , C , D , A , 13 , gs4);
+  gg(A , B , C , D ,  2 , gs1);
+  gg(D , A , B , C ,  6 , gs2);
+  gg(C , D , A , B , 10 , gs3);
+  gg(B , C , D , A , 14 , gs4);
+  gg(A , B , C , D ,  3 , gs1);
+  gg(D , A , B , C ,  7 , gs2);
+  gg(C , D , A , B , 11 , gs3);
+  gg(B , C , D , A , 15 , gs4);
+  hh(A , B , C , D ,  0 , hs1); /* Round 3 */
+  hh(D , A , B , C ,  8 , hs2);
+  hh(C , D , A , B ,  4 , hs3);
+  hh(B , C , D , A , 12 , hs4);
+  hh(A , B , C , D ,  2 , hs1);
+  hh(D , A , B , C , 10 , hs2);
+  hh(C , D , A , B ,  6 , hs3);
+  hh(B , C , D , A , 14 , hs4);
+  hh(A , B , C , D ,  1 , hs1);
+  hh(D , A , B , C ,  9 , hs2);
+  hh(C , D , A , B ,  5 , hs3);
+  hh(B , C , D , A , 13 , hs4);
+  hh(A , B , C , D ,  3 , hs1);
+  hh(D , A , B , C , 11 , hs2);
+  hh(C , D , A , B ,  7 , hs3);
+  hh(B , C , D , A , 15 , hs4);
+  MDp->buffer[0] += A;
+  MDp->buffer[1] += B;
+  MDp->buffer[2] += C;
+  MDp->buffer[3] += D;
+}
+
+/* MD4Update(MDp,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+**        count -- the number of bits of X to use.
+**          (if not a multiple of 8, uses high bits of last byte.)
+** Update MDp using the number of bits of X given by count.
+** This is the basic input routine for an MD4 user.
+** The routine completes the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512.  A call with count 0 will be ignored if the
+** MD has already been terminated (done != 0), so an extra call with
+** count 0 can be given as a "courtesy close" to force termination
+** if desired.
+*/
+void
+MD4Update(MDp,X,count)
+MD4_CTX *MDp;
+unsigned char *X;
+unsigned int count;
+{
+  unsigned int i, tmp, bit, byte, mask;
+  unsigned char XX[64];
+  unsigned char *p;
+
+  /* return with no error if this is a courtesy close with count
+  ** zero and MDp->done is true.
+  */
+  if (count == 0 && MDp->done) return;
+  /* check to see if MD is already done and report error */
+  if (MDp->done)
+  { printf("\nError: MD4Update MD already done."); return; }
+
+  /* Add count to MDp->count */
+  tmp = count;
+  p = MDp->count;
+  while (tmp)
+  { tmp += *p;
+  *p++ = tmp;
+  tmp = tmp >> 8;
+  }
+
+  /* Process data */
+  if (count == 512)
+  { /* Full block of data to handle */
+    MDblock(MDp,X);
+  }
+  else if (count > 512) /* Check for count too large */
+  {
+    printf("\nError: MD4Update called with illegal count value %d.",
+	   count);
+    return;
+  }
+  else /* partial block -- must be last block so finish up */
+  {
+    /* Find out how many bytes and residual bits there are */
+    byte = count >> 3;
+    bit =  count & 7;
+    /* Copy X into XX since we need to modify it */
+    for (i=0;i<=byte;i++)   XX[i] = X[i];
+    for (i=byte+1;i<64;i++) XX[i] = 0;
+    /* Add padding '1' bit and low-order zeros in last byte */
+    mask = 1 << (7 - bit);
+    XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+    /* If room for bit count, finish up with this block */
+    if (byte <= 55)
+    {
+      for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+      MDblock(MDp,XX);
+    }
+    else /* need to do two blocks to finish up */
+    {
+      MDblock(MDp,XX);
+      for (i=0;i<56;i++) XX[i] = 0;
+      for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
+      MDblock(MDp,XX);
+    }
+    /* Set flag saying we're done with MD computation */
+    MDp->done = 1;
+  }
+}
+
+/*
+** Finish up MD4 computation and return message digest.
+*/
+void
+MD4Final(buf, MD)
+unsigned char *buf;
+MD4_CTX *MD;
+{
+  int i, j;
+  unsigned int w;
+
+  MD4Update(MD, NULL, 0);
+  for (i = 0; i < 4; ++i) {
+    w = MD->buffer[i];
+    for (j = 0; j < 4; ++j) {
+      *buf++ = w;
+      w >>= 8;
+    }
+  }
+}
+
+/*
+** End of md4.c
+****************************(cut)***********************************/
diff -uN hydra-2.4/md4.h hydra-2.4-m0j0/md4.h
--- hydra-2.4/md4.h	1969-12-31 18:00:00.000000000 -0600
+++ hydra-2.4-m0j0/md4.h	2003-09-29 14:32:08.000000000 -0500
@@ -0,0 +1,64 @@
+
+/*
+** ********************************************************************
+** md4.h -- Header file for implementation of                        **
+** MD4 Message Digest Algorithm                                      **
+** Updated: 2/13/90 by Ronald L. Rivest                              **
+** (C) 1990 RSA Data Security, Inc.                                  **
+** ********************************************************************
+*/
+
+#ifndef __P
+# if defined(__STDC__) || defined(__GNUC__)
+#  define __P(x) x
+# else
+#  define __P(x) ()
+# endif
+#endif
+
+
+/* MDstruct is the data structure for a message digest computation.
+*/
+typedef struct {
+	unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+	unsigned char count[8]; /* Number of bits processed so far */
+	unsigned int done;      /* Nonzero means MD computation finished */
+} MD4_CTX;
+
+/* MD4Init(MD4_CTX *)
+** Initialize the MD4_CTX prepatory to doing a message digest
+** computation.
+*/
+extern void MD4Init __P((MD4_CTX *MD));
+
+/* MD4Update(MD,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+**        count -- the number of bits of X to use (an unsigned int).
+** Updates MD using the first "count" bits of X.
+** The array pointed to by X is not modified.
+** If count is not a multiple of 8, MD4Update uses high bits of
+** last byte.
+** This is the basic input routine for a user.
+** The routine terminates the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512.  Zero is OK for a count.
+*/
+extern void MD4Update __P((MD4_CTX *MD, unsigned char *X, unsigned int count));
+
+/* MD4Print(MD)
+** Prints message digest buffer MD as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte
+** of buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+*/
+extern void MD4Print __P((MD4_CTX *));
+
+/* MD4Final(buf, MD)
+** Returns message digest from MD and terminates the message
+** digest computation.
+*/
+extern void MD4Final __P((unsigned char *, MD4_CTX *));
+
+/*
+** End of md4.h
+****************************(cut)***********************************/
Common subdirectories: hydra-2.4/old and hydra-2.4-m0j0/old
