Old-style Windows NT LM hash recovery: Difference between revisions
m (→Manual recovery: Make hash filename consistent) |
(→Manual recovery: Be clear that this is not yet a proper LM hash) |
||
Line 30: | Line 30: | ||
## For the example account, Key 1 will be: <code>f4 01 00 00 f4 01 00</code> |
## For the example account, Key 1 will be: <code>f4 01 00 00 f4 01 00</code> |
||
## For the example account, Key 2 will be: <code>00 f4 01 00 00 f4 01</code> |
## For the example account, Key 2 will be: <code>00 f4 01 00 00 f4 01</code> |
||
# Split the LM hash into two 8-byte chunks. |
# Split the encrypted LM hash into two 8-byte chunks. |
||
## For the example account, Chunk 1 is: <code>09e72baf281e2a2e</code> |
## For the example account, Chunk 1 is: <code>09e72baf281e2a2e</code> |
||
## For the example account, Chunk 2 is: <code>00092899a8cb74f3</code> |
## For the example account, Chunk 2 is: <code>00092899a8cb74f3</code> |
Latest revision as of 07:24, 5 February 2024
Old-style Windows NT LM hash recovery, specifically for the pre-NT4 SP3 world, does not seem to be documented. I recently had to figure this out for recovering the Administrator password for the Motorola Net6200/166, which was running the PowerPC version of Windows NT 4.0 SP2. I hope this information can be useful for others.
Attempted tools
The following tools were attempted to be used to recover the LM hash for the Administrator account. All of them either bombed out with an error message or crashed.
- Cain & Abel v4.9.56
- "SAM account's F value has a wrong size"
- chntpw version 1.00 140201
- "** No LANMAN hash found either. Try login with no password!"
- creddump ed95e1a9a920e04733a2950f7de0ff5bdfec631c (specifically, pwdump.py)
- incorrectly returns the null LM hash
- impacket 0.11.0 (specifically, secretsdump.py)
- "TypeError: 'NoneType' object is not subscriptable"
The crux of the incompatibility appears to be that Microsoft changed the format of the structures in SAM in NT4 SP3 to add support for the then-new Syskey utility, adding another layer of encryption provided by a boot key. This boot key is stored in the registry by default, but Syskey can require it to be entered upon boot. The old SAM format does not have any concept of this, but the four tested tools all expect it to exist.
Manual recovery
- Obtain an offline registry editor. I used Registry Spy 1.1.0 by Andy Smith.[1]
sudo apt install libxcb-cursor0
python3 -m venv env
source env/bin/activate
python3 setup.py install
registryspy
- Get a copy of
%WINDIR%\System32\Config\SAM
from the pre-NT4 SP3 machine. - Navigate to
\SAM\Domains\Account\Users\000001F4
. This represents the Administrator account.000001F4
is its ID (decimal 500). - Copy the 32nd last to 16th last bytes of the hexadecimal view of
V
somewhere, without whitespace. This should be your encrypted LM hash. Mine looked like this:09e72baf281e2a2e00092899a8cb74f3
- Compute the little-endian representation of the account's ID. For the Administrator account, this will be:
f4 01 00 00
- Repeat this representation three and a half times, to get fourteen bytes. Split this in half to get two 56-bit DES keys.
- For the example account, Key 1 will be:
f4 01 00 00 f4 01 00
- For the example account, Key 2 will be:
00 f4 01 00 00 f4 01
- For the example account, Key 1 will be:
- Split the encrypted LM hash into two 8-byte chunks.
- For the example account, Chunk 1 is:
09e72baf281e2a2e
- For the example account, Chunk 2 is:
00092899a8cb74f3
- For the example account, Chunk 1 is:
- DES-decrypt Chunk 1 with Key 1 and Chunk 2 with Key 2, then concatenate both decrypted chunks. This is your decrypted LM hash. Mine looked like this:
ae6e1b1fccb24d5b944e2df489a880e4
- As a quick-and-dirty solution, I took the Wine implementation of DES,[2] removed the two
#include
statements, and appended this:#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *k1 = "\xf4\x01\x00\x00\xf4\x01\x00"; char *k2 = "\x00\xf4\x01\x00\x00\xf4\x01"; char *in1 = "\x09\xe7\x2b\xaf\x28\x1e\x2a\x2e"; char *in2 = "\x00\x09\x28\x99\xa8\xcb\x74\xf3"; char out1[8]; char out2[8]; CRYPT_DESunhash(out1, k1, in1); CRYPT_DESunhash(out2, k2, in2); for (int i = 0; i < 8; i++) printf("%x", (unsigned char)out1[i]); for (int i = 0; i < 8; i++) printf("%x", (unsigned char)out2[i]); puts(""); return EXIT_SUCCESS; }
- As a quick-and-dirty solution, I took the Wine implementation of DES,[2] removed the two
- Create a text file named
hashes.txt
that contains the decrypted LM hash in a colon-delimited format.- An example looks like this:
Administrator:500:ae6e1b1fccb24d5b944e2df489a880e4::::
- An example looks like this:
- Run
hashcat -m 3000 -a 3 hashes.txt
to recover the password.- If you have a GPU, this will execute in the order of seconds.
- If you do not have a GPU, this will execute in the order of tens of minutes.
- Run
hashcat -m 3000 -a 3 hashes.txt --show
to see the password.- Do not trust the password output of the command from the previous step. It will only show the recovered password for the first half of the LM hash even though both halves were recovered and needed to successfully login.
- The output will be in LM Hash : Uppercase Password format, like this:
ae6e1b1fccb24d5b944e2df489a880e4:COMPUTER
- Take the uppercase password and attempt to login to the pre-NT4 SP3 machine with some permutation of casing.
- While the LM hash is computed from an uppercase version of the password, the machine might still need the correct casing in order to login. For me, the correct casing was
computer
. - It is likely best to attempt all-uppercase, all-lowercase, and sentence-case versions first, before brute-forcing all 2^n possibilities, where n is the count of alphabetical characters in the recovered password.
- While the LM hash is computed from an uppercase version of the password, the machine might still need the correct casing in order to login. For me, the correct casing was