mode 3000(LM) skip 0x61~0x7A even if ?b used
#1
Hi, I'm trying to crack a LM hash, but I found that hashcat can't crash hashes if they're from password contains 0x61~0x7A

Here are 2 hashes I tested

bc7428e54df23ab9:$HEX[a141]
cda35c9a7e8590be:$HEX[a161]

If I use:
Code:
hashcat -m 3000 -a 3 hashes ?b?b

Only the first one would be found

Is there anything I can do to force hashcat to use all 0x00~0xFF ?

btw, the hashcat version is 6.2.4
#2
how are these hashes generated ?

the algorithm details say, that the password always needs to be converted to upper-case (hashcat does this internally, like all the other correct generators).

also see https://en.wikipedia.org/wiki/LAN_Manage..._algorithm

maybe you testing is wrong and you are generating them incorrectly ? otherwise you probably wouldn't ask for a-z characters (if the hash algorithm says that everything needs to be upper-cased internally).

I think this is a misconception/misunderstanding
#3
(10-29-2021, 05:00 PM)philsmd Wrote: how are these hashes generated ?

the algorithm details say, that the password always needs to be converted to upper-case (hashcat does this internally, like all the other correct generators).

also see https://en.wikipedia.org/wiki/LAN_Manage..._algorithm

maybe you testing is wrong and you are generating them incorrectly ? otherwise you probably wouldn't ask for a-z characters (if the hash algorithm says that everything needs to be upper-cased internally).

I think this is a misconception/misunderstanding

 
The hashes I tested are dumped from my computer by mimikatz after I changed my password, so they do really exist

The case conversion happens only if the character is a lowercase letter, but what my password contains are chinese characters, input by alt code and encoded in codepage 950(usually labelled as big5)

I think that's the reason why a 0x61~0x7A byte could be used as input when generating the hash
#4
(10-30-2021, 05:28 AM)cwmd86124 Wrote:
(10-29-2021, 05:00 PM)philsmd Wrote: how are these hashes generated ?

the algorithm details say, that the password always needs to be converted to upper-case (hashcat does this internally, like all the other correct generators).

also see https://en.wikipedia.org/wiki/LAN_Manage..._algorithm

maybe you testing is wrong and you are generating them incorrectly ? otherwise you probably wouldn't ask for a-z characters (if the hash algorithm says that everything needs to be upper-cased internally).

I think this is a misconception/misunderstanding

 
The hashes I tested are dumped from my computer by mimikatz after I changed my password, so they do really exist

The case conversion happens only if the character is a lowercase letter, but what my password contains are chinese characters, input by alt code and encoded in codepage 950(usually labelled as big5)

I think that's the reason why a 0x61~0x7A byte could be used as input when generating the hash

Can you please post your chinese char used? or give the alt code?
#5
(11-01-2021, 07:54 PM)Snoopy Wrote: Can you please post your chinese char used? or give the alt code?
 


They're 0xA141 and 0xA161 in code page 950, the hashes in #1 were generated by them
#6
I've investigated this hash and problem now a little bit and come to the conclusion that:
1. yeah you are right with different encodings (or code pages) the "uppercasing" rule is different and 0x61 ("a") isn't translated to 0x41 ("A") if for instance code page 950 is in use
2. the hash was indeed generated by the bytes 0xa161 (including "nomally" called "lower-case" characters, e.g. "a") and 0xa161 matches the hash cda35c9a7e8590be
3. there are some possibilities to skip (or work around) the automatic upper-case mechanism of hashcat for -m 3000 = LM, see below

So the first stragetgy (actually just a work around) to proof that #3 is possible (skip the upper case in case a different/unusual upper-casing-mechanism is used for an unusual/different encoding/code page), you could just use the "l" (lowercase L) rule of hashcat with -r/-j/-k in the attack modes -a 0 and -a 1.

for instance, a rule file (a.rule) like this would work:
Code:
l

This strategy only works, because -m 3000 = LM is a special case for hashcat and the dictionary words are already upper-cased as soon as reading the lines from the dictionary (the upper casing is just ASCII code uppercaseing, i.e. a-z will become A-Z automatically)... but after that you could still apply some rules within the kernels and therefore the "l" rule with -r or -j or -k will lower-case (the upper-cased) chars again and therefore undo the upper-casing...

This of course does NOT work for other attack modes (like -a 3, mask attack)....
but also for that case, there is a little fix/workaround:

For the brute-force case or "more general skip the upper-casing case", I would suggest to "git clone" (https://github.com/hashcat/hashcat) the git repository of hashcat and make these modifications:
1. remove (or comment out) OPTS_TYPE_PT_UPPER in src/modules/module_03000.c
2. remove (or comment out) OPTS_TYPE_PT_LM in src/modules/module_03000.c
3. fix the example hashes (use a lower-case example password) e.g. "hashcat"

The below patch will show you how to do this:
Code:
diff --git a/src/modules/module_03000.c b/src/modules/module_03000.c
index 25cac60fc..2c1d4ef32 100644
--- a/src/modules/module_03000.c
+++ b/src/modules/module_03000.c
@@ -22,15 +22,15 @@ static const char *HASH_NAME      = "LM";
static const u64   KERN_TYPE      = 3000;
static const u32   OPTI_TYPE      = OPTI_TYPE_ZERO_BYTE;
static const u64   OPTS_TYPE      = OPTS_TYPE_PT_GENERATE_LE
-                                  | OPTS_TYPE_PT_UPPER
+//                                  | OPTS_TYPE_PT_UPPER
                                   | OPTS_TYPE_TM_KERNEL
                                   | OPTS_TYPE_PT_ALWAYS_ASCII
-                                  | OPTS_TYPE_PT_LM
+//                                  | OPTS_TYPE_PT_LM
                                   | OPTS_TYPE_HASH_SPLIT;
static const u32   PWDUMP_COLUMN  = PWDUMP_COLUMN_LM_HASH;
static const u32   SALT_TYPE      = SALT_TYPE_NONE;
-static const char *ST_PASS        = "HASHCAT";
-static const char *ST_HASH        = "299bd128c1101fd6";
+static const char *ST_PASS        = "hashcat";
+static const char *ST_HASH        = "e8891aea2cf66bcb";

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;       }

https://pastebin.com/raw/SURSpC9x

with "git apply" you could patch a modified hashcat version (PLEASE make sure you are using a different path/folder/installation of hashcat that you name accordingly, e.g. "hashcat_modified_lowercase_LM" or something, just to not confuse a vanilla version of hashcat with your modified version).

Of course, this later step is more advanced than only the rule-based tests/workaround.... but it's still worth it if you need a -a 3 attack...

make sure to not forget to always remove the cached kernel (either by using "make clean" or "rm -rf kernels").
you of course also need to build new binary files by using the "make" command after applying the patch (all of this is explained in the guide under docs/hashcat-plugin-development-guide.md).

I don't think it's worth it to change the current/master version of hashcat with patches like these, because there is no way we can deal with all the encodings and know exactly when a character needs to be upper-cased for all the different encodings etc.... the current version of hashcat is able to deal with the most common encodings and it willl work for most of the users (I don't remember that we had any other similar encoding problem with -m 3000 like this before).

of course there are still some open question, for instance, for which characters do you need to apply a upper-case translation for code page 950 (or any other encodings different from ASCII/utf8 etc) ? I'm not sure if there are some translation rules with code page 950, probably there are some characters that one could identify as the upper-case version of another character and maybe this needs to be done manually now (within your dict or mask etc).

I hope this helps, please try. thx
#7
(11-12-2021, 05:24 PM)philsmd Wrote:
Code:
diff --git a/src/modules/module_03000.c b/src/modules/module_03000.c
index 25cac60fc..2c1d4ef32 100644
--- a/src/modules/module_03000.c
+++ b/src/modules/module_03000.c
@@ -22,15 +22,15 @@ static const char *HASH_NAME      = "LM";
static const u64  KERN_TYPE      = 3000;
static const u32  OPTI_TYPE      = OPTI_TYPE_ZERO_BYTE;
static const u64  OPTS_TYPE      = OPTS_TYPE_PT_GENERATE_LE
-                                  | OPTS_TYPE_PT_UPPER
+//                                  | OPTS_TYPE_PT_UPPER
                                  | OPTS_TYPE_TM_KERNEL
                                  | OPTS_TYPE_PT_ALWAYS_ASCII
-                                  | OPTS_TYPE_PT_LM
+//                                  | OPTS_TYPE_PT_LM
                                  | OPTS_TYPE_HASH_SPLIT;
static const u32  PWDUMP_COLUMN  = PWDUMP_COLUMN_LM_HASH;
static const u32  SALT_TYPE      = SALT_TYPE_NONE;
-static const char *ST_PASS        = "HASHCAT";
-static const char *ST_HASH        = "299bd128c1101fd6";
+static const char *ST_PASS        = "hashcat";
+static const char *ST_HASH        = "e8891aea2cf66bcb";

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;      }
 
Thanks, I've just tried this and it works really fine!
 
And about the question, I've checked other double-byte character set(DBCS), like japanese(cp932/Shift-JIS), korean(cp949/UHC), simplified chinese(cp936/GB2312), the ascii characters encoded into 1 byte in all of these code pages and just the same as ASCII, and the upper-case translation should only work for these characters too, so with this patch, I think there should be no more problem.
 
Anyway, my problem has been solved now, thanks again!