LM Hashes¶
The lm module is used after LM password recovery to:
- Map recovered LM passwords back to user accounts (
map) - Generate password capitalisation candidates for recovered Domain Administrator passwords (
generate)
-h
usage: main.py lm [-h] {map,generate} ...
LM password processing utilities used to reconstruct recovered LM passwords,
map them to user accounts, and generate candidate password variants for
privileged accounts.
positional arguments:
{map,generate}
map Map recovered LM passwords to user accounts
generate Generate LM Domain Admin candidates
options:
-h, --help show this help message and exit
Examples:
password-audit lm map \
-N company.ntds \
-P hashcat.potfile \
-R lm-results.txt
password-audit lm generate \
-L ntds-organiser/mapped-lm-passwords.txt
Map¶
$ password-audit lm map -h
usage: main.py lm map [-h] -N NTDS -P POTFILE -R LM_RESULTS [-O OUTPUT_DIR]
Reconstruct recovered LM passwords using Hashcat show results
and map them back to user accounts within the NTDS dataset.
options:
-h, --help show this help message and exit
required arguments:
-N, --ntds NTDS SecretsDump NTDS file
-P, --potfile POTFILE
Hashcat potfile containing recovered passwords
-R, --lm-results LM_RESULTS
LM recovery results generated using hashcat --show
optional arguments:
-O, --output-dir OUTPUT_DIR
Output directory (default: ntds-organiser)
Example:
password-audit lm map \
-N company.ntds \
-P hashcat.potfile \
-R lm-results.txt
If LM hashes are present within NTDS, organise identifies and extracts them:
$ password-audit organise \
-N example.ntds \
-B bloodhound.zip
[*] Password Audit Organise
NTDS Summary
| Object | Value |
|-------------------|-------|
| Enabled Accounts | 481 |
| Disabled Accounts | 42 |
| User Accounts | 273 |
| Machine Accounts | 208 |
| NTLM Hashes | 164 |
| LM Hashes | 88 |
| Domain Admins | 23 |
| Company Words | 3 |
[+] Output written to: ntds-organiser
These can be cracked as normal using the crack run command using Hashcat's LM mode (3000):
Info
For an example JSON file see Campaign Structure.
password-audit crack run \
-C example-lm-config.json \
-H ntds-organiser/lm-hashes.txt \
-G example-lm-test
After cracking is complete, the recovered passwords must be mapped back to their users. This requires an extra step that is not yet integrated within password-audit:
Note
Mapped LM passwords may outnumber recovered LM hashes due to password reuse and LM hash structure.
# Write the LM dataset to a file
$ hashcat -m3000 \
--show ntds-organiser/lm-hashes.txt \
--potfile-path hashcat.potfile \
> lm-results.txt
# Map recovered passwords back to their users
$ password-audit lm map \
-N example.ntds \
-P hashcat.potfile \
-R ntds-organiser/lm-results.txt
LM Password Mapping
| Object | Value |
|---------------------|-------|
| Mapped LM Passwords | 15 |
[+] Output Directory: ntds-organiser
The generated dataset will contain the recovered passwords in uppercase form:
$ grep 'WELCOME123!' ntds-organiser/mapped-lm-passwords.txt
domain.local\mike:WELCOME123!
The LM dataset can now be analysed and integrated within the final report and/or used to generate password candidates if a Domain Admin exists within it.
Reporting¶
The LM dataset can be analysed to add LM-related findings to the final report (alongside the NTLM dataset):
$ password-audit analyse \
-M ntds-organiser/mapped-ntlm-passwords.txt \
-L ntds-organiser/mapped-lm-passwords.txt
[+] Report written to: report.md
[+] Findings written to: findings.json
The following LM findings are currently present:
- LM hash exposure
- Unique and duplicate LM hash analysis
- LM password recovery statistics
- LM Domain Administrator exposure
Generate¶
The LM dataset can be processed further using the generate module.
$ password-audit lm generate -h
usage: main.py lm generate [-h] -L MAPPED_LM_PASSWORDS [-D DOMAIN_ADMINS] [-O OUTPUT_DIR]
Identify recovered LM passwords belonging to Domain Administrators
and generate all possible password capitalisation variants.
options:
-h, --help show this help message and exit
required arguments:
-L, --mapped-lm-passwords MAPPED_LM_PASSWORDS
Recovered LM passwords
optional arguments:
-D, --domain-admins DOMAIN_ADMINS
Domain Admin account list (default: ./ntds-organiser/domain-admins.txt)
-O, --output-dir OUTPUT_DIR
Output directory (default: ntds-organiser)
Example:
password-audit lm generate \
-L ntds-organiser/mapped-lm-passwords.txt
Because LM hashes do not preserve character casing, recovered passwords are presented in uppercase form and may not reflect the user's original password. The generate module identifies recovered LM passwords belonging to Domain Administrator accounts and generates all possible capitalisation variants, enabling recovery of the original password casing through password spraying:
Example
The recovered password WELCOME123! contains seven alphabetic characters, each of which can be either uppercase or lowercase. As a result,
2^7 = 128 possible capitalisation variants are generated, one of which represents the user's original password.
$ password-audit lm generate \
-L ntds-organiser/mapped-lm-passwords.txt
LM Candidate Generation
| Object | Value |
|------------------|-------|
| LM DA Users | 0 |
| LM DA Candidates | 0 |
[+] Output Directory: ntds-organiser
# Recovered LM passwords belonging to Domain Administrators
$ head lm-da-passwords.txt
domain.local\mike:WELCOME123!
# Generated capitalisation variants
$ head -n5 lm-da-candidates.txt
WELCOME123!
WELCOMe123!
WELCOmE123!
WELCoME123!
WELcOME123!
The lm generate command generates three files:
lm-da-users.txtcontaining Domain Administrator usernameslm-da-passwords.txtcontaining recovered LM passwords belonging to Domain Administratorslm-da-candidates.txtcontaining all generated capitalisation variants
The generated user and candidate datasets can then be used for password spraying (e.g. conpass) to determine the original password capitalisation:
conpass -d <domain> \
-u <user> \
-p <pass> \
-U lm-da-users.txt \
-P lm-da-candidates.txt \
--dc-ip <dc-ip>
Why the Extra Step?¶
Unlike NTLM hashes, LM passwords are processed in two independent 7-character halves. Each half produces a separate LM hash value, resulting in a 32-character LM hash composed of two 16-character hash halves:
Hashcat stores recovered LM hash (16-character) halves in the potfile rather than the full 32-character values. Consequently, the potfile cannot be used directly to map recovered LM passwords back to user accounts:
# Full 32-character hash within the LM dataset
$ head -1 ntds-organiser/lm-hashes.txt
c23413a8a1e7665f1bf3ece46b279e12
# Stored halves within the potfile
$ grep 'c23413a8a1e7665f' hashcat.potfile
c23413a8a1e7665f:WELCOME
$ grep '1bf3ece46b279e12' hashcat.potfile
1bf3ece46b279e12:123!
As a result, an additional hashcat --show step is required to reconstruct the full LM hash and map recovered passwords back to user accounts:
Warning
Perform this step from Bash. PowerShell may modify the potfile encoding and affect LM password reconstruction.
# Validate that the full LM hash is shown
$ hashcat -m3000 \
--show ntds-organiser/lm-hashes.txt \
--potfile-path hashcat.potfile \
| grep 'WELCOME'
c23413a8a1e7665f1bf3ece46b279e12:WELCOME123!
