/** * Author......: See docs/credits.txt * License.....: MIT */ #include "common.h" #include "types.h" #include "memory.h" #include "event.h" #include "shared.h" #include "modules.h" #include "backend.h" #include "dynloader.h" #include "bridges.h" #include "interface.h" /** * parsing */ int bridge_filename (const folder_config_t *folder_config, const char *bridge_name, char *out_buf, const size_t out_size) { // native compiled #if defined (_WIN) || defined (__CYGWIN__) return snprintf (out_buf, out_size, "%s/bridges/bridge_%s.dll", folder_config->shared_dir, bridge_name); #else return snprintf (out_buf, out_size, "%s/bridges/bridge_%s.so", folder_config->shared_dir, bridge_name); #endif } bool bridge_load (hashcat_ctx_t *hashcat_ctx, bridge_ctx_t *bridge_ctx, const char *bridge_name) { const folder_config_t *folder_config = hashcat_ctx->folder_config; char *bridge_file = (char *) hcmalloc (HCBUFSIZ_TINY); bridge_filename (folder_config, bridge_name, bridge_file, HCBUFSIZ_TINY); struct stat s; memset (&s, 0, sizeof (struct stat)); if (stat (bridge_file, &s) == -1) { event_log_warning (hashcat_ctx, "The bridge plugin '%s' couldn't be found.", bridge_file); event_log_warning (hashcat_ctx, NULL); } bridge_ctx->bridge_handle = hc_dlopen (bridge_file); if (bridge_ctx->bridge_handle == NULL) { #if defined (_WIN) event_log_error (hashcat_ctx, "Cannot load bridge %s", bridge_file); // todo: maybe there's a dlerror () equivalent #else event_log_error (hashcat_ctx, "%s", dlerror ()); #endif return false; } bridge_ctx->bridge_init = (BRIDGE_INIT) hc_dlsym (bridge_ctx->bridge_handle, "bridge_init"); if (bridge_ctx->bridge_init == NULL) { event_log_error (hashcat_ctx, "Cannot load symbol 'bridge_init' in bridge %s", bridge_file); return false; } hcfree (bridge_file); return true; } void bridge_unload (bridge_ctx_t *bridge_ctx) { if (bridge_ctx->bridge_handle) { hc_dlclose (bridge_ctx->bridge_handle); } } bool bridges_init (hashcat_ctx_t *hashcat_ctx) { bridge_ctx_t *bridge_ctx = hashcat_ctx->bridge_ctx; user_options_t *user_options = hashcat_ctx->user_options; hashconfig_t *hashconfig = hashcat_ctx->hashconfig; if (user_options->backend_info > 0) return true; if (user_options->hash_info > 0) return true; if (user_options->usage > 0) return true; if (user_options->left == true) return true; if (user_options->show == true) return true; if (user_options->version == true) return true; // There is a problem here. At this point, hashconfig is not yet initialized. // This is because initializing hashconfig requires the module to be loaded, // but in order to load the module, we need to know the backend devices. // However, the backend devices are also not yet initialized, because // they require the virtualization count, which we only determine here. // To break this chicken-and-egg problem, we cheat by quick-loading the module // and unloading it afterwards, so it can be properly initialized later. const int hashconfig_init_rc = hashconfig_init (hashcat_ctx); if (hashconfig_init_rc == -1) return false; // ok, we can start if (hashconfig->bridge_type == BRIDGE_TYPE_NONE) { hashconfig_destroy (hashcat_ctx); return true; } bridge_ctx->enabled = true; // finally, the real stuff const bool rc_load = bridge_load (hashcat_ctx, bridge_ctx, hashconfig->bridge_name); if (rc_load == false) return false; bridge_ctx->bridge_init (bridge_ctx); if (bridge_ctx->bridge_context_size != BRIDGE_CONTEXT_SIZE_CURRENT) { event_log_error (hashcat_ctx, "bridge context size is invalid. Old template?"); return false; } if (bridge_ctx->bridge_interface_version < BRIDGE_INTERFACE_VERSION_MINIMUM) { event_log_error (hashcat_ctx, "bridge interface version is outdated, please compile"); return false; } // check for missing pointer assignements #define CHECK_DEFINED(func) \ if ((func) == NULL) \ { \ event_log_error (hashcat_ctx, "Missing symbol definitions in bridge '%s'. Old template?", hashconfig->bridge_name); \ \ return false; \ } CHECK_DEFINED (bridge_ctx->platform_init); CHECK_DEFINED (bridge_ctx->platform_term); CHECK_DEFINED (bridge_ctx->get_unit_count); CHECK_DEFINED (bridge_ctx->get_unit_info); CHECK_DEFINED (bridge_ctx->get_workitem_count); CHECK_DEFINED (bridge_ctx->thread_init); CHECK_DEFINED (bridge_ctx->thread_term); CHECK_DEFINED (bridge_ctx->salt_prepare); CHECK_DEFINED (bridge_ctx->salt_destroy); CHECK_DEFINED (bridge_ctx->launch_loop); CHECK_DEFINED (bridge_ctx->launch_loop2); CHECK_DEFINED (bridge_ctx->st_update_hash); CHECK_DEFINED (bridge_ctx->st_update_pass); #undef CHECK_DEFINED // mandatory functions check #define CHECK_MANDATORY(func) \ if ((func) == MODULE_DEFAULT) \ { \ event_log_error (hashcat_ctx, "Missing mandatory symbol definitions"); \ \ return false; \ } CHECK_MANDATORY (bridge_ctx->platform_init); CHECK_MANDATORY (bridge_ctx->platform_term); CHECK_MANDATORY (bridge_ctx->get_unit_count); CHECK_MANDATORY (bridge_ctx->get_unit_info); CHECK_MANDATORY (bridge_ctx->get_workitem_count); if (hashconfig->bridge_type & BRIDGE_TYPE_REPLACE_LOOP) CHECK_MANDATORY (bridge_ctx->launch_loop); if (hashconfig->bridge_type & BRIDGE_TYPE_REPLACE_LOOP2) CHECK_MANDATORY (bridge_ctx->launch_loop2); if (hashconfig->bridge_type & BRIDGE_TYPE_LAUNCH_LOOP) CHECK_MANDATORY (bridge_ctx->launch_loop); if (hashconfig->bridge_type & BRIDGE_TYPE_LAUNCH_LOOP2) CHECK_MANDATORY (bridge_ctx->launch_loop2); #undef CHECK_MANDATORY bridge_ctx->platform_context = bridge_ctx->platform_init (user_options); if (bridge_ctx->platform_context == NULL) { event_log_error (hashcat_ctx, "Platform initialization failed"); return false; } // auto adjust workitem counts if (hashconfig->bridge_type & BRIDGE_TYPE_MATCH_TUNINGS) { if ((hashconfig->opts_type & OPTS_TYPE_NATIVE_THREADS) == 0) { event_log_error (hashcat_ctx, "BRIDGE_TYPE_MATCH_TUNINGS requires OPTS_TYPE_NATIVE_THREADS"); return false; } if ((hashconfig->opts_type & OPTS_TYPE_MP_MULTI_DISABLE) == 0) { event_log_error (hashcat_ctx, "BRIDGE_TYPE_MATCH_TUNINGS requires OPTS_TYPE_MP_MULTI_DISABLE"); return false; } } // clean up hashconfig_destroy (hashcat_ctx); return true; } void bridges_destroy (hashcat_ctx_t *hashcat_ctx) { bridge_ctx_t *bridge_ctx = hashcat_ctx->bridge_ctx; if (bridge_ctx->enabled == false) return; bridge_ctx->platform_term (bridge_ctx->platform_context); bridge_unload (bridge_ctx); } bool bridges_salt_prepare (hashcat_ctx_t *hashcat_ctx) { bridge_ctx_t *bridge_ctx = hashcat_ctx->bridge_ctx; hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; user_options_t *user_options = hashcat_ctx->user_options; if (user_options->backend_info > 0) return true; if (user_options->hash_info > 0) return true; if (user_options->usage > 0) return true; if (user_options->left == true) return true; if (user_options->show == true) return true; if (user_options->version == true) return true; if (bridge_ctx->enabled == false) return true; if (bridge_ctx->salt_prepare == MODULE_DEFAULT) return true; if (bridge_ctx->salt_prepare (bridge_ctx->platform_context, hashconfig, hashes) == false) { event_log_error (hashcat_ctx, "Couldn't prepare salt specific data in bridge"); return false; } return true; } void bridges_salt_destroy (hashcat_ctx_t *hashcat_ctx) { bridge_ctx_t *bridge_ctx = hashcat_ctx->bridge_ctx; hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; if (bridge_ctx->enabled == false) return; if (bridge_ctx->salt_destroy == MODULE_DEFAULT) return; bridge_ctx->salt_destroy (bridge_ctx->platform_context, hashconfig, hashes); }