1
0
mirror of https://github.com/hashcat/hashcat.git synced 2025-07-28 17:38:43 +00:00
hashcat/src/bridges.c
2025-07-06 08:06:24 +02:00

277 lines
8.6 KiB
C

/**
* 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);
}