diff --git a/OpenCL/m29600-pure.cl b/OpenCL/m29600-pure.cl index 4e1ec612e..85406f53e 100644 --- a/OpenCL/m29600-pure.cl +++ b/OpenCL/m29600-pure.cl @@ -25,6 +25,7 @@ typedef struct pbkdf_sha1_tmp u32 dgst[32]; u32 out[32]; + } pbkdf_sha1_tmp_t; typedef struct terra diff --git a/docs/readme.txt b/docs/readme.txt index 30251ffae..da59272de 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -420,6 +420,7 @@ NVIDIA GPUs require "NVIDIA Driver" (440.64 or later) and "CUDA Toolkit" (9.0 or - MultiBit Classic .wallet (scrypt) - MultiBit HD (scrypt) - Exodus Desktop Wallet (scrypt) +- Terra Station Wallet (AES256-CBC(PBKDF2($pass))) ## ## Attack-Modes diff --git a/src/modules/module_29600.c b/src/modules/module_29600.c index a0d4cd47f..0bda91daf 100644 --- a/src/modules/module_29600.c +++ b/src/modules/module_29600.c @@ -1,5 +1,3 @@ - - /** * Author......: See docs/credits.txt * License.....: MIT @@ -19,15 +17,16 @@ static const u32 DGST_POS1 = 1; static const u32 DGST_POS2 = 2; static const u32 DGST_POS3 = 3; static const u32 DGST_SIZE = DGST_SIZE_4_4; -static const u32 HASH_CATEGORY = HASH_CATEGORY_NETWORK_PROTOCOL; -static const char *HASH_NAME = "terra"; +static const u32 HASH_CATEGORY = HASH_CATEGORY_CRYPTOCURRENCY_WALLET; +static const char *HASH_NAME = "Terra Station Wallet (AES256-CBC(PBKDF2($pass)))"; static const u64 KERN_TYPE = 29600; static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE; static const u64 OPTS_TYPE = OPTS_TYPE_STOCK_MODULE + | OPTS_TYPE_ST_HEX | OPTS_TYPE_PT_GENERATE_BE; static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED; -static const char *ST_PASS = "hashcathas"; -static const char *ST_HASH = "a25b0fde71ebe13803a4707a657c54dd688a1659fb1e9bfd9f04412ea5dcc47e9sNxXqi14uSPbnjI+5gFanekzSwdOgwxUnbJA0xcxajPRwyNFomS7xaia3xidrx752LteXNligDb7Qs/cTwFAOm5OKzeh5b1o3OI5MrPEXU="; +static const char *ST_PASS = "hashcat"; +static const char *ST_HASH = "67445496c838e96c1424a8dae4b146f0fc247c8c34ef33feffeb1e4412018512wZGtBMeN84XZE2LoOKwTGvA4Ee4m7PR1lDGIdWUV6OSUZKRiKFx9tlrnZLt8r8OfOzbwUS2a2Uo+nrrP6F85fh4eHstwPJw0KwzHWB8br58="; u32 module_attack_exec (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ATTACK_EXEC; } u32 module_dgst_pos0 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS0; } @@ -61,10 +60,8 @@ typedef struct terra u32 salt_buf[8]; u32 ct[16]; // 16 * 4 = 64 bytes (we have extra 16 bytes in digest: 64 + 16 = 80) u32 iv[4]; - } terra_t; - u64 module_esalt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { const u64 esalt_size = (const u64) sizeof (terra_t); @@ -89,9 +86,22 @@ u32 module_pw_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED con return pw_max; } +u32 module_salt_min (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) +{ + const u32 salt_min = 16; + + return salt_min; +} + +u32 module_salt_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) +{ + const u32 salt_max = 16; + + return salt_max; +} + int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED void *hook_salt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len) { - terra_t *terra = (terra_t *) esalt_buf; u32 *digest = (u32 *) digest_buf; @@ -113,7 +123,6 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE token.len[2] = 108; token.attr[2] = TOKEN_ATTR_FIXED_LENGTH | TOKEN_ATTR_VERIFY_BASE64A; - const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); @@ -126,10 +135,10 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE const int iv_len = token.len[1]; const u8 *hash_pos = token.buf[2]; const int hash_len = token.len[2]; - + // Populating salt buf even though it's unused - we use esalt below - const bool parse_rc = generic_salt_decode (hashconfig, salt_pos, salt_len, (u8 *)salt->salt_buf, (int *)&salt->salt_len); + const bool parse_rc = generic_salt_decode (hashconfig, salt_pos, salt_len, (u8 *) salt->salt_buf, (int *) &salt->salt_len); if (parse_rc == false) return (PARSER_SALT_LENGTH); @@ -159,7 +168,6 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE if (tmp_len != 0x50) return (PARSER_HASH_LENGTH); - u32* whole_digest = (u32*) tmp_buf; // Penultimate block, i.e. IV, xored with a whole padding block @@ -244,7 +252,7 @@ void module_init (module_ctx_t *module_ctx) module_ctx->module_benchmark_hook_salt = MODULE_DEFAULT; module_ctx->module_benchmark_mask = MODULE_DEFAULT; module_ctx->module_benchmark_charset = MODULE_DEFAULT; - module_ctx->module_benchmark_salt = MODULE_DEFAULT; + module_ctx->module_benchmark_salt = MODULE_DEFAULT; module_ctx->module_build_plain_postprocess = MODULE_DEFAULT; module_ctx->module_deep_comp_kernel = MODULE_DEFAULT; module_ctx->module_deprecated_notice = MODULE_DEFAULT; @@ -303,8 +311,8 @@ void module_init (module_ctx_t *module_ctx) module_ctx->module_pwdump_column = MODULE_DEFAULT; module_ctx->module_pw_max = module_pw_max; module_ctx->module_pw_min = MODULE_DEFAULT; - module_ctx->module_salt_max = MODULE_DEFAULT; - module_ctx->module_salt_min = MODULE_DEFAULT; + module_ctx->module_salt_max = module_salt_max; + module_ctx->module_salt_min = module_salt_min; module_ctx->module_salt_type = module_salt_type; module_ctx->module_separator = MODULE_DEFAULT; module_ctx->module_st_hash = module_st_hash; diff --git a/tools/test.sh b/tools/test.sh index 177e5a361..1fd7d3998 100755 --- a/tools/test.sh +++ b/tools/test.sh @@ -5,7 +5,7 @@ ## License.....: MIT ## -OPTS="--quiet --potfile-disable --hwmon-disable" +OPTS="--quiet --potfile-disable --hwmon-disable --logfile-disable" FORCE=0 RUNTIME=400 diff --git a/tools/test_modules/m29600.pm b/tools/test_modules/m29600.pm new file mode 100644 index 000000000..0f054ef73 --- /dev/null +++ b/tools/test_modules/m29600.pm @@ -0,0 +1,107 @@ +#!/usr/bin/env perl + +## +## Author......: See docs/credits.txt +## License.....: MIT +## + +use strict; +use warnings; + +use MIME::Base64 qw (encode_base64 decode_base64); +use Crypt::CBC; +use Crypt::PBKDF2; + +sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] } + +my $ITERATIONS = 100; + +sub module_generate_hash +{ + my $word = shift; + my $salt = shift; + my $iv = shift; + my $data = shift; + + my $pbkdf2 = Crypt::PBKDF2->new + ( + hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'), + iterations => $ITERATIONS, + output_len => 32 + ); + + my $key = $pbkdf2->PBKDF2 ($salt, $word); + + if (! defined ($iv)) + { + $iv = random_bytes (16); + } + + my $cipher = Crypt::CBC->new ({ + key => $key, + cipher => "Crypt::Rijndael", + iv => $iv, + literal_key => 1, + keysize => 32, + header => "none", + padding => "none", + }); + + if (! defined ($data)) + { + $data = random_hex_string (64); + + $data .= "\x10" x 16 # padding block + } + else + { + $data = $cipher->decrypt ($data); + + my $padding_block = substr ($data, 64, 16); + + if ($padding_block ne "\x10" x 16) + { + $data = "\x00" x 80; # FAKE data (length: 64 + 16) + } + } + + my $encrypted_data = $cipher->encrypt ($data); + + my $hash = sprintf ("%s%s%s", unpack ("H*", $salt), unpack ("H*", $iv), encode_base64 ($encrypted_data, "")); + + return $hash; +} + +sub module_verify_hash +{ + my $line = shift; + + my ($hash, $word) = split (":", $line); + + return unless (defined ($hash)); + return unless (defined ($word)); + + return unless (length ($hash) == (32 + 32 + 108)); + + my $salt = substr ($hash, 0, 32); + my $iv = substr ($hash, 32, 32); + my $data = substr ($hash, 64, 108); # or until the end + + return unless ($salt =~ m/^[0-9a-fA-F]{32}$/); + return unless ($iv =~ m/^[0-9a-fA-F]{32}$/); + return unless ($data =~ m/^[A-Za-z0-9+\/=]{108}$/); + + $salt = pack ("H*", $salt); + $iv = pack ("H*", $iv); + $data = decode_base64 ($data); + + return unless (length ($data) == (64 + 16)); # 80 + + $word = pack_if_HEX_notation ($word); + + my $new_hash = module_generate_hash ($word, $salt, $iv, $data); + + return ($new_hash, $word); +} + +1;