Skip to content

Instantly share code, notes, and snippets.

@jakobfriedl
Created November 25, 2025 13:57
Show Gist options
  • Select an option

  • Save jakobfriedl/e33329cad0aac995e198ee406d96f75f to your computer and use it in GitHub Desktop.

Select an option

Save jakobfriedl/e33329cad0aac995e198ee406d96f75f to your computer and use it in GitHub Desktop.
Extract one hash per username from NTLMv1/NTLMv2 hashes collected by Responder.
#!/usr/bin/env python3
"""
NTLMv2 Hash Deduplicator
Finds the first occurrence of each user from a file containing NTLMv2 hashes
and writes unique entries to a new file.
"""
import sys
import os
from collections import OrderedDict
def extract_username_from_hash(hash_line):
"""
Extract username from NTLMv2 hash line.
NTLMv2 format: username::domain:challenge:response
"""
try:
parts = hash_line.strip().split(':')
if len(parts) >= 4:
return parts[0].lower() # Username is the first part, normalize to lowercase
except:
pass
return None
def process_ntlmv2_file(input_file, output_file):
"""
Process NTLMv2 hash file and extract first occurrence of each user.
"""
seen_users = OrderedDict()
processed_count = 0
duplicate_count = 0
try:
with open(input_file, 'r', encoding='utf-8', errors='ignore') as infile:
for line_num, line in enumerate(infile, 1):
line = line.strip()
# Skip empty lines
if not line:
continue
username = extract_username_from_hash(line)
if username:
if username not in seen_users:
seen_users[username] = line
processed_count += 1
print(f"Found user: {username}")
else:
duplicate_count += 1
print(f"Duplicate found for user: {username} (line {line_num})")
else:
print(f"Warning: Could not parse line {line_num}: {line[:50]}...")
# Write unique hashes to output file
with open(output_file, 'w', encoding='utf-8') as outfile:
for hash_line in seen_users.values():
outfile.write(hash_line + '\n')
print(f"\nProcessing complete!")
print(f"Unique users found: {processed_count}")
print(f"Duplicates removed: {duplicate_count}")
print(f"Output written to: {output_file}")
except FileNotFoundError:
print(f"Error: Input file '{input_file}' not found.")
sys.exit(1)
except Exception as e:
print(f"Error processing file: {e}")
sys.exit(1)
def main():
if len(sys.argv) != 3:
print("Usage: python ntlmv2_dedup.py <input_file> <output_file>")
print("Example: python ntlmv2_dedup.py hashes.txt unique_hashes.txt")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
# Check if input file exists
if not os.path.exists(input_file):
print(f"Error: Input file '{input_file}' does not exist.")
sys.exit(1)
# Confirm overwrite if output file exists
if os.path.exists(output_file):
response = input(f"Output file '{output_file}' already exists. Overwrite? (y/N): ")
if response.lower() != 'y':
print("Operation cancelled.")
sys.exit(0)
process_ntlmv2_file(input_file, output_file)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment