Do not overwrite quit status when user forced it with keypress
[hashcat.git] / src / hashcat.c
index 6656862..4baaa90 100644 (file)
@@ -362,7 +362,7 @@ const char *USAGE_BIG[] =
   "- [ Options ] -",
   "",
   " Options Short / Long          | Type | Description                                          | Example",
-  "===============================|======|======================================================|=======================",
+  "===============================+======+======================================================+=======================",
   " -m, --hash-type               | Num  | Hash-type, see references below                      | -m 1000",
   " -a, --attack-mode             | Num  | Attack-mode, see references below                    | -a 3",
   " -V, --version                 |      | Print version                                        |",
@@ -391,8 +391,8 @@ const char *USAGE_BIG[] =
   "     --outfile-check-timer     | Num  | Sets seconds between outfile checks to X             | --outfile-check=30",
   " -p, --separator               | Char | Separator char for hashlists and outfile             | -p :",
   "     --stdout                  |      | Do not crack a hash, instead print candidates only   |",
-  "     --show                    |      | Show cracked passwords only                          |",
-  "     --left                    |      | Show un-cracked passwords only                       |",
+  "     --show                    |      | Compare hashlist with potfile; Show cracked hashes   |",
+  "     --left                    |      | Compare hashlist with potfile; Show uncracked hashes |",
   "     --username                |      | Enable ignoring of usernames in hashfile             |",
   "     --remove                  |      | Enable remove of hash once it is cracked             |",
   "     --remove-timer            | Num  | Update input hash file each X seconds                | --remove-timer=30",
@@ -413,7 +413,7 @@ const char *USAGE_BIG[] =
   "     --cpu-affinity            | Str  | Locks to CPU devices, separate with comma            | --cpu-affinity=1,2,3",
   "     --opencl-platforms        | Str  | OpenCL platforms to use, separate with comma         | --opencl-platforms=2",
   " -d, --opencl-devices          | Str  | OpenCL devices to use, separate with comma           | -d 1",
-  "     --opencl-device-types     | Str  | OpenCL device-types to use, separate with comma      | --opencl-device-type=1",
+  " -D, --opencl-device-types     | Str  | OpenCL device-types to use, separate with comma      | -D 1",
   "     --opencl-vector-width     | Num  | Manual override OpenCL vector-width to X             | --opencl-vector=4",
   " -w, --workload-profile        | Num  | Enable a specific workload profile, see pool below   | -w 3",
   " -n, --kernel-accel            | Num  | Manual workload tuning, set outerloop step size to X | -n 64",
@@ -429,9 +429,9 @@ const char *USAGE_BIG[] =
   " -s, --skip                    | Num  | Skip X words from the start                          | -s 1000000",
   " -l, --limit                   | Num  | Limit X words from the start + skipped words         | -l 1000000",
   "     --keyspace                |      | Show keyspace base:mod values and quit               |",
-  " -j, --rule-left               | Rule | Single Rule applied to each word from left wordlist  | -j 'c'",
-  " -k, --rule-right              | Rule | Single Rule applied to each word from right wordlist | -k '^-'",
-  " -r, --rules-file              | File | Multiple Rules applied to each word from wordlists   | -r rules/best64.rule",
+  " -j, --rule-left               | Rule | Single rule applied to each word from left wordlist  | -j 'c'",
+  " -k, --rule-right              | Rule | Single rule applied to each word from right wordlist | -k '^-'",
+  " -r, --rules-file              | File | Multiple rules applied to each word from wordlists   | -r rules/best64.rule",
   " -g, --generate-rules          | Num  | Generate X random rules                              | -g 10000",
   "     --generate-rules-func-min | Num  | Force min X funcs per rule                           |",
   "     --generate-rules-func-max | Num  | Force max X funcs per rule                           |",
@@ -728,11 +728,20 @@ const char *USAGE_BIG[] =
   "  3 | High        |  96 ms  | High              | Unresponsive",
   "  4 | Nightmare   | 480 ms  | Insane            | Headless",
   "",
-  "If you have no idea what just happened then visit the following pages:",
+  "- [ Basic Examples ] -",
+  "",
+  "  Attack-          | Hash- |",
+  "  Mode             | Type  | Example command",
+  " ==================+=======+==================================================================",
+  "  Wordlist         | $P$   | %s -a 0 -m 400 example400.hash example.dict",
+  "  Wordlist + Rules | MD5   | %s -a 0 -m 0 example0.hash example.dict -r rules/best64.rule",
+  "  Brute-Force      | MD5   | %s -a 3 -m 0 example0.hash ?a?a?a?a?a?a",
+  "  Combinator       | MD5   | %s -a 1 -m 0 example0.hash example.dict example.dict",
+  "",
+  "If you still have no idea what just happened try following pages:",
   "",
   "* https://hashcat.net/wiki/#howtos_videos_papers_articles_etc_in_the_wild",
   "* https://hashcat.net/wiki/#frequently_asked_questions",
-  "",
   NULL
 };
 
@@ -923,7 +932,6 @@ void status_display ()
 {
   if (data.devices_status == STATUS_INIT)     return;
   if (data.devices_status == STATUS_STARTING) return;
-  if (data.devices_status == STATUS_BYPASS)   return;
 
   if (data.machine_readable == 1)
   {
@@ -1682,7 +1690,6 @@ static void status_benchmark ()
 {
   if (data.devices_status == STATUS_INIT)     return;
   if (data.devices_status == STATUS_STARTING) return;
-  if (data.devices_status == STATUS_BYPASS)   return;
 
   if (data.machine_readable == 1)
   {
@@ -4773,7 +4780,7 @@ static uint get_work (hc_device_param_t *device_param, const u64 max)
   hc_thread_mutex_lock (mux_dispatcher);
 
   const u64 words_cur  = data.words_cur;
-  const u64 words_base = (data.limit == 0) ? data.words_base : data.limit;
+  const u64 words_base = (data.limit == 0) ? data.words_base : MIN (data.limit, data.words_base);
 
   device_param->words_off = words_cur;
 
@@ -5959,7 +5966,7 @@ int main (int argc, char **argv)
   #define IDX_CPU_AFFINITY              0xff25
   #define IDX_OPENCL_DEVICES            'd'
   #define IDX_OPENCL_PLATFORMS          0xff72
-  #define IDX_OPENCL_DEVICE_TYPES       0xff73
+  #define IDX_OPENCL_DEVICE_TYPES       'D'
   #define IDX_OPENCL_VECTOR_WIDTH       0xff74
   #define IDX_WORKLOAD_PROFILE          'w'
   #define IDX_KERNEL_ACCEL              'n'
@@ -5983,7 +5990,7 @@ int main (int argc, char **argv)
   #define IDX_CUSTOM_CHARSET_3          '3'
   #define IDX_CUSTOM_CHARSET_4          '4'
 
-  char short_options[] = "hVvm:a:r:j:k:g:o:t:d:n:u:c:p:s:l:1:2:3:4:ibw:";
+  char short_options[] = "hVvm:a:r:j:k:g:o:t:d:D:n:u:c:p:s:l:1:2:3:4:ibw:";
 
   struct option long_options[] =
   {
@@ -6422,6 +6429,10 @@ int main (int argc, char **argv)
     {
       // do nothing
     }
+    else if (keyspace == 1)
+    {
+      // do nothing
+    }
     else
     {
       log_info ("%s (%s) starting...", PROGNAME, VERSION_TAG);
@@ -7332,6 +7343,35 @@ int main (int argc, char **argv)
     }
   }
 
+  /**
+   * status, monitor and outfile remove threads
+   */
+
+  uint wordlist_mode = ((optind + 1) < myargc) ? WL_MODE_FILE : WL_MODE_STDIN;
+
+  data.wordlist_mode = wordlist_mode;
+
+  if (wordlist_mode == WL_MODE_STDIN)
+  {
+    status = 1;
+
+    data.status = status;
+  }
+
+  uint i_threads_cnt = 0;
+
+  hc_thread_t *i_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
+
+  if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
+  {
+    if ((data.wordlist_mode == WL_MODE_FILE) || (data.wordlist_mode == WL_MODE_MASK))
+    {
+      hc_thread_create (i_threads[i_threads_cnt], thread_keypress, NULL);
+
+      i_threads_cnt++;
+    }
+  }
+
   /**
    * config
    */
@@ -8086,27 +8126,6 @@ int main (int argc, char **argv)
                    dgst_pos3   = 1;
                    break;
 
-      case   190:  hash_type   = HASH_TYPE_SHA1;
-                   salt_type   = SALT_TYPE_NONE;
-                   attack_exec = ATTACK_EXEC_INSIDE_KERNEL;
-                   opts_type   = OPTS_TYPE_PT_GENERATE_BE
-                               | OPTS_TYPE_PT_ADD80
-                               | OPTS_TYPE_PT_ADDBITS15;
-                   kern_type   = KERN_TYPE_SHA1_LINKEDIN;
-                   dgst_size   = DGST_SIZE_4_5;
-                   parse_func  = sha1linkedin_parse_hash;
-                   sort_by_digest = sort_by_digest_4_5;
-                   opti_type   = OPTI_TYPE_ZERO_BYTE
-                               | OPTI_TYPE_PRECOMPUTE_INIT
-                               | OPTI_TYPE_EARLY_SKIP
-                               | OPTI_TYPE_NOT_ITERATED
-                               | OPTI_TYPE_NOT_SALTED;
-                   dgst_pos0   = 0;
-                   dgst_pos1   = 4;
-                   dgst_pos2   = 3;
-                   dgst_pos3   = 2;
-                   break;
-
       case   200:  hash_type   = HASH_TYPE_MYSQL;
                    salt_type   = SALT_TYPE_NONE;
                    attack_exec = ATTACK_EXEC_INSIDE_KERNEL;
@@ -15337,7 +15356,11 @@ int main (int argc, char **argv)
         // now check if all device-memory sizes which depend on the kernel_accel_max amplifier are within its boundaries
         // if not, decrease amplifier and try again
 
-        int skip = 0;
+        int memory_limit_hit = 0;
+
+        if (size_pws   > device_param->device_maxmem_alloc) memory_limit_hit = 1;
+        if (size_tmps  > device_param->device_maxmem_alloc) memory_limit_hit = 1;
+        if (size_hooks > device_param->device_maxmem_alloc) memory_limit_hit = 1;
 
         const u64 size_total
           = bitmap_size
@@ -15367,12 +15390,9 @@ int main (int argc, char **argv)
           + size_tm
           + size_tmps;
 
-        // Don't ask me, ask AMD!
-
-        if (size_total > device_param->device_maxmem_alloc) skip = 1;
-        if (size_total > device_param->device_global_mem)   skip = 1;
+        if (size_total > device_param->device_global_mem) memory_limit_hit = 1;
 
-        if (skip == 1)
+        if (memory_limit_hit == 1)
         {
           kernel_accel_max--;
 
@@ -15382,14 +15402,12 @@ int main (int argc, char **argv)
         break;
       }
 
-      /*
-      if (kernel_accel_max == 0)
+      if (kernel_accel_max < kernel_accel_min)
       {
-        log_error ("- Device #%u: Device does not provide enough allocatable device-memory to handle hash-type %u", device_id + 1, data.hash_mode);
+        log_error ("- Device #%u: Device does not provide enough allocatable device-memory to handle this attack", device_id + 1);
 
         return -1;
       }
-      */
 
       device_param->kernel_accel_min = kernel_accel_min;
       device_param->kernel_accel_max = kernel_accel_max;
@@ -15415,32 +15433,59 @@ int main (int argc, char **argv)
        * default building options
        */
 
-      char build_opts[1024] = { 0 };
+      char cpath[1024] = { 0 };
 
-      // we don't have sm_* on vendors not NV but it doesn't matter
+      char build_opts[1024] = { 0 };
 
       #if _WIN
-      snprintf (build_opts, sizeof (build_opts) - 1, "-I \"%s\\OpenCL\\\" -I '%s\\OpenCL\\' -I %s\\OpenCL\\ -I\"%s\\OpenCL\\\" -I'%s\\OpenCL\\' -I%s\\OpenCL\\", shared_dir, shared_dir, shared_dir, shared_dir, shared_dir, shared_dir);
-      #else
-      snprintf (build_opts, sizeof (build_opts) - 1, "-I \"%s/OpenCL/\" -I '%s/OpenCL/' -I %s/OpenCL/ -I\"%s/OpenCL/\" -I'%s/OpenCL/' -I%s/OpenCL/", shared_dir, shared_dir, shared_dir, shared_dir, shared_dir, shared_dir);
-      #endif
-
-      char build_opts_new[1024] = { 0 };
 
-      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -DVENDOR_ID=%u -DCUDA_ARCH=%d -DVECT_SIZE=%u -DDEVICE_TYPE=%u -DKERN_TYPE=%u -D_unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, kern_type);
+      snprintf (cpath, sizeof (cpath) - 1, "%s\\OpenCL\\", shared_dir);
 
-      strncpy (build_opts, build_opts_new, sizeof (build_opts) - 1);
+      char *cpath_real = mymalloc (MAX_PATH);
 
-      /*
-      if (device_param->device_vendor_id == VENDOR_ID_INTEL_SDK)
+      if (GetFullPathName (cpath, MAX_PATH, cpath_real, NULL) == 0)
       {
-        // we do vectorizing much better than the auto-vectorizer
+        log_error ("ERROR: %s: %s", cpath, "GetFullPathName()");
+
+        return -1;
+      }
+
+      naive_replace (cpath_real, '\\', '/');
+
+      // not escaping here, windows has quotes
+
+      snprintf (build_opts, sizeof (build_opts) - 1, "-I \"%s\"", cpath_real);
 
-        snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -cl-opt-disable", build_opts);
+      myfree (cpath_real);
+
+      #else
+
+      snprintf (cpath, sizeof (cpath) - 1, "%s/OpenCL/", shared_dir);
+
+      char *cpath_real = mymalloc (PATH_MAX);
+
+      if (realpath (cpath, cpath_real) == NULL)
+      {
+        log_error ("ERROR: %s: %s", cpath, strerror (errno));
 
-        strncpy (build_opts, build_opts_new, sizeof (build_opts) - 1);
+        return -1;
       }
-      */
+
+      naive_escape (cpath_real, PATH_MAX,  ' ', '\\');
+
+      snprintf (build_opts, sizeof (build_opts) - 1, "-I %s", cpath_real);
+
+      myfree (cpath_real);
+
+      #endif
+
+      // we don't have sm_* on vendors not NV but it doesn't matter
+
+      char build_opts_new[1024] = { 0 };
+
+      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -D VENDOR_ID=%u -D CUDA_ARCH=%d -D VECT_SIZE=%u -D DEVICE_TYPE=%u -D KERN_TYPE=%u -D _unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, kern_type);
+
+      strncpy (build_opts, build_opts_new, sizeof (build_opts));
 
       #ifdef DEBUG
       log_info ("- Device #%u: build_opts '%s'\n", device_id + 1, build_opts);
@@ -16390,10 +16435,6 @@ int main (int argc, char **argv)
     wl_data->cnt   = 0;
     wl_data->pos   = 0;
 
-    uint wordlist_mode = ((optind + 1) < myargc) ? WL_MODE_FILE : WL_MODE_STDIN;
-
-    data.wordlist_mode = wordlist_mode;
-
     cs_t  *css_buf   = NULL;
     uint   css_cnt   = 0;
     uint   dictcnt   = 0;
@@ -17186,29 +17227,16 @@ int main (int argc, char **argv)
      * status and monitor threads
      */
 
-    if (data.devices_status != STATUS_CRACKED) data.devices_status = STATUS_STARTING;
-
-    uint i_threads_cnt = 0;
-
-    hc_thread_t *i_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
-
-    if ((data.wordlist_mode == WL_MODE_FILE) || (data.wordlist_mode == WL_MODE_MASK))
+    if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
     {
-      if (stdout_flag == 0)
-      {
-        hc_thread_create (i_threads[i_threads_cnt], thread_keypress, &benchmark);
-
-        i_threads_cnt++;
-      }
+      data.devices_status = STATUS_STARTING;
     }
 
-    if (wordlist_mode == WL_MODE_STDIN) data.status = 1;
-
     uint ni_threads_cnt = 0;
 
     hc_thread_t *ni_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
 
-    if (stdout_flag == 0)
+    if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
     {
       hc_thread_create (ni_threads[ni_threads_cnt], thread_monitor, NULL);
 
@@ -17219,7 +17247,7 @@ int main (int argc, char **argv)
       * Outfile remove
       */
 
-    if (keyspace == 0)
+    if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
     {
       if (outfile_check_timer != 0)
       {
@@ -17278,9 +17306,9 @@ int main (int argc, char **argv)
 
     for (uint maskpos = rd->maskpos; maskpos < maskcnt; maskpos++)
     {
-      if (data.devices_status == STATUS_CRACKED) break;
-
-      data.devices_status = STATUS_INIT;
+      if (data.devices_status == STATUS_CRACKED) continue;
+      if (data.devices_status == STATUS_ABORTED) continue;
+      if (data.devices_status == STATUS_QUIT)    continue;
 
       if (maskpos > rd->maskpos)
       {
@@ -17519,15 +17547,24 @@ int main (int argc, char **argv)
         }
       }
 
-      for (uint dictpos = rd->dictpos; dictpos < dictcnt; )
+      for (uint dictpos = rd->dictpos; dictpos < dictcnt; dictpos++)
       {
+        if (data.devices_status == STATUS_CRACKED) continue;
+        if (data.devices_status == STATUS_ABORTED) continue;
+        if (data.devices_status == STATUS_QUIT)    continue;
+
+        rd->dictpos = dictpos;
+
         char *subid = logfile_generate_subid ();
 
         data.subid = subid;
 
         logfile_sub_msg ("START");
 
-        data.devices_status = STATUS_INIT;
+        if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+        {
+          data.devices_status = STATUS_INIT;
+        }
 
         memset (data.words_progress_done,     0, data.salts_cnt * sizeof (u64));
         memset (data.words_progress_rejected, 0, data.salts_cnt * sizeof (u64));
@@ -17627,10 +17664,7 @@ int main (int argc, char **argv)
 
             if (data.words_cnt == 0)
             {
-              if (data.devices_status == STATUS_CRACKED) break;
-              if (data.devices_status == STATUS_ABORTED) break;
-
-              dictpos++;
+              logfile_sub_msg ("STOP");
 
               continue;
             }
@@ -17677,10 +17711,7 @@ int main (int argc, char **argv)
 
           if (data.words_cnt == 0)
           {
-            if (data.devices_status == STATUS_CRACKED) break;
-            if (data.devices_status == STATUS_ABORTED) break;
-
-            dictpos++;
+            logfile_sub_msg ("STOP");
 
             continue;
           }
@@ -17720,10 +17751,7 @@ int main (int argc, char **argv)
 
           if (data.words_cnt == 0)
           {
-            if (data.devices_status == STATUS_CRACKED) break;
-            if (data.devices_status == STATUS_ABORTED) break;
-
-            dictpos++;
+            logfile_sub_msg ("STOP");
 
             continue;
           }
@@ -17787,10 +17815,6 @@ int main (int argc, char **argv)
 
             // skip to next mask
 
-            dictpos++;
-
-            rd->dictpos = dictpos;
-
             logfile_sub_msg ("STOP");
 
             continue;
@@ -18068,7 +18092,10 @@ int main (int argc, char **argv)
 
         hc_thread_t *c_threads = (hc_thread_t *) mycalloc (data.devices_cnt, sizeof (hc_thread_t));
 
-        data.devices_status = STATUS_AUTOTUNE;
+        if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+        {
+          data.devices_status = STATUS_AUTOTUNE;
+        }
 
         for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
         {
@@ -18106,6 +18133,8 @@ int main (int argc, char **argv)
           {
             if (quiet == 0)
             {
+              clear_prompt ();
+
               log_info ("ATTENTION!");
               log_info ("  The wordlist or mask you are using is too small.");
               log_info ("  Therefore, hashcat is unable to utilize the full parallelization power of your device(s).");
@@ -18120,7 +18149,10 @@ int main (int argc, char **argv)
          * create cracker threads
          */
 
-        data.devices_status = STATUS_RUNNING;
+        if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+        {
+          data.devices_status = STATUS_RUNNING;
+        }
 
         if (initial_restore_done == 0)
         {
@@ -18169,21 +18201,14 @@ int main (int argc, char **argv)
 
         local_free (c_threads);
 
-        data.restore = 0;
-
-        // finalize task
+        if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT) && (data.devices_status != STATUS_BYPASS))
+        {
+          data.devices_status = STATUS_EXHAUSTED;
+        }
 
         logfile_sub_var_uint ("status-after-work", data.devices_status);
 
-        if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
-
-        if (data.devices_status == STATUS_CRACKED) break;
-        if (data.devices_status == STATUS_ABORTED) break;
-
-        if (data.devices_status == STATUS_BYPASS)
-        {
-          data.devices_status = STATUS_RUNNING;
-        }
+        data.restore = 0;
 
         if (induction_dictionaries_cnt)
         {
@@ -18199,47 +18224,34 @@ int main (int argc, char **argv)
           induction_dictionaries_cnt = count_dictionaries (induction_dictionaries);
         }
 
-        if (benchmark == 0)
+        if (benchmark == 1)
         {
-          if (((dictpos + 1) < dictcnt) || ((maskpos + 1) < maskcnt) || induction_dictionaries_cnt)
-          {
-            if (quiet == 0) clear_prompt ();
-
-            if (quiet == 0) log_info ("");
-
-            if (status == 1)
-            {
-              status_display ();
-            }
-            else
-            {
-              if (quiet == 0) status_display ();
-            }
+          status_benchmark ();
 
-            if (quiet == 0) log_info ("");
+          if (machine_readable == 0)
+          {
+            log_info ("");
           }
         }
-
-        if (attack_mode == ATTACK_MODE_BF)
-        {
-          dictpos++;
-
-          rd->dictpos = dictpos;
-        }
         else
         {
-          if (induction_dictionaries_cnt)
-          {
-            qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
-          }
-          else
+          if (quiet == 0)
           {
-            dictpos++;
+            clear_prompt ();
 
-            rd->dictpos = dictpos;
+            log_info ("");
+
+            if (stdout_flag == 0) status_display ();
+
+            log_info ("");
           }
         }
 
+        if (induction_dictionaries_cnt)
+        {
+          qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
+        }
+
         time_t runtime_stop;
 
         time (&runtime_stop);
@@ -18252,22 +18264,27 @@ int main (int argc, char **argv)
         logfile_sub_msg ("STOP");
 
         global_free (subid);
-      }
 
-      if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
+        // from this point we handle bypass as exhausted
+
+        if (data.devices_status == STATUS_BYPASS)
+        {
+          data.devices_status = STATUS_EXHAUSTED;
+        }
+
+        // finalize task
+
+        if (data.devices_status == STATUS_CRACKED) break;
+        if (data.devices_status == STATUS_ABORTED) break;
+        if (data.devices_status == STATUS_QUIT)    break;
+      }
 
       if (data.devices_status == STATUS_CRACKED) break;
       if (data.devices_status == STATUS_ABORTED) break;
       if (data.devices_status == STATUS_QUIT)    break;
-
-      if (data.devices_status == STATUS_BYPASS)
-      {
-        data.devices_status = STATUS_RUNNING;
-      }
     }
 
     // problems could occur if already at startup everything was cracked (because of .pot file reading etc), we must set some variables here to avoid NULL pointers
-
     if (attack_mode == ATTACK_MODE_STRAIGHT)
     {
       if (data.wordlist_mode == WL_MODE_FILE)
@@ -18306,11 +18323,6 @@ int main (int argc, char **argv)
       }
     }
 
-    if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
-    {
-      data.devices_status = STATUS_EXHAUSTED;
-    }
-
     // if cracked / aborted remove last induction dictionary
 
     for (int file_pos = 0; file_pos < induction_dictionaries_cnt; file_pos++)
@@ -18332,15 +18344,6 @@ int main (int argc, char **argv)
 
     local_free (ni_threads);
 
-    // wait for interactive threads
-
-    for (uint thread_idx = 0; thread_idx < i_threads_cnt; thread_idx++)
-    {
-      hc_thread_wait (1, &i_threads[thread_idx]);
-    }
-
-    local_free (i_threads);
-
     // we dont need restore file anymore
     if (data.restore_disable == 0)
     {
@@ -18366,33 +18369,6 @@ int main (int argc, char **argv)
      * Clean up
      */
 
-    if (benchmark == 1)
-    {
-      status_benchmark ();
-
-      if (machine_readable == 0)
-      {
-        log_info ("");
-      }
-    }
-    else
-    {
-      if (quiet == 0) clear_prompt ();
-
-      if (quiet == 0) log_info ("");
-
-      if (status == 1)
-      {
-        status_display ();
-      }
-      else
-      {
-        if (quiet == 0) status_display ();
-      }
-
-      if (quiet == 0) log_info ("");
-    }
-
     for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
     {
       hc_device_param_t *device_param = &data.devices_param[device_id];
@@ -18400,15 +18376,10 @@ int main (int argc, char **argv)
       if (device_param->skipped) continue;
 
       local_free (device_param->combs_buf);
-
       local_free (device_param->hooks_buf);
-
       local_free (device_param->device_name);
-
       local_free (device_param->device_name_chksum);
-
       local_free (device_param->device_version);
-
       local_free (device_param->driver_version);
 
       if (device_param->pws_buf)            myfree                    (device_param->pws_buf);
@@ -18693,6 +18664,15 @@ int main (int argc, char **argv)
     if (data.devices_status == STATUS_QUIT) break;
   }
 
+  // wait for interactive threads
+
+  for (uint thread_idx = 0; thread_idx < i_threads_cnt; thread_idx++)
+  {
+    hc_thread_wait (1, &i_threads[thread_idx]);
+  }
+
+  local_free (i_threads);
+
   // destroy others mutex
 
   hc_thread_mutex_delete (mux_dispatcher);