How To Create Wordlists For Hacking & Cracking
- Biohazard

- Jul 19
- 5 min read

Creating Wordlists for Hacking/Cracking
Here's how to build custom wordlists from scratch for hacking & cracking — from scraping a target to raw brute-force generation. This article is on how to create wordlists for hacking & cracking.
CeWL - Scrape A Target Website
Best method for creating a wordlist specific to the target organization.
bash
# Basic scrape
cewl https://target-org.com -w custom_words.txt
# Full production scrape
cewl https://target-org.com \
-d 3 \ # spider depth (3 levels deep)
-m 5 \ # minimum word length
--lowercase \ # all lowercase output
--with-numbers \ # append numbers to words
-e \ # include email addresses
--email_file emails.txt \ # separate email file
-w target_full.txt
# Target intranet / documentation / blog only
cewl https://target-org.com/blog -d 2 -m 6 -w blog_words.txt
cewl https://docs.target-org.com -d 3 -m 5 -w docs_words.txt
# Combine and deduplicate
cat *_words.txt | sort -u > combined.txt
What CeWL captures: product names, internal project names, employee names from "About" pages, jargon, acronyms, departmental terms.
Crunch - Pattern-Based Generation
When you know the password policy but need to generate all possibilities.
bash
# Syntax: crunch <min> <max> <charset> [options]
crunch 6 8 abc123 -o output.txt
# Common patterns
crunch 6 8 -t Pass@@@@ -o output.txt # Pass + 4 lowercase
crunch 8 8 -t Corp%%^^ -o output.txt # Corp + 2 digits + 2 symbols
# Pattern characters:
# @ = lowercase
# , = uppercase
# % = numbers
# ^ = symbols
# Using pre-defined charsets
crunch 8 8 -f /usr/share/crunch/charset.lst mixalpha -o alpha8.txt
crunch 10 10 -f /usr/share/crunch/charset.lst mixalpha-numeric-all -o all10.txt
# Known prefix/suffix (company name patterns)
crunch 10 10 -t Target%%% -o target_numbers.txt # Target123, Target456...
crunch 10 10 -t %%%Company -o numbers_company.txt # 123Company, 456Company...
crunch 10 10 -t Target!%%@ -o target_complex.txt # Target!12a...
Estimate size before generating:
bash
# crunch prints estimate before starting
crunch 6 8 abc123
# Manual: charset_length ^ password_length
# abc123 = 6 chars, 8 positions = 6^8 = 1,679,616 combinationsHashcat Rules - Expand A Small Seed List
Take a small list of target-specific words and apply transformation rules.
bash
# Start with target-specific seed words
cat > seeds.txt << EOF
targetcorp
admin
winter2024
projectx
ceoname
cityname
EOF
# Apply rule sets
hashcat --stdout seeds.txt -r /usr/share/hashcat/rules/best64.rule > expanded.txt
hashcat --stdout seeds.txt -r /usr/share/hashcat/rules/d3ad0ne.rule > huge_expanded.txt
# String multiple rule passes
hashcat --stdout seeds.txt -r /usr/share/hashcat/rules/leetspeak.rule \
| hashcat --stdout -r /usr/share/hashcat/rules/best64.rule \
> super_expanded.txt
# Sort and deduplicate
sort -u huge_expanded.txt > final.txt
Key rule files:
bash
/usr/share/hashcat/rules/best64.rule # 64 most effective rules
/usr/share/hashcat/rules/d3ad0ne.rule # 35,000+ rules
/usr/share/hashcat/rules/OneRuleToRuleThemAll.rule # 50,000+ rules
/usr/share/hashcat/rules/rockyou-30000.rule # RockYou-derived rules
/usr/share/hashcat/rules/leetspeak.rule # l33t substitutions only
/usr/share/hashcat/rules/append1.rule # Append 1 charCustom Rules - Write Your Own
Hashcat rules are extremely flexible. Build them for target-specific patterns.
bash
# Create custom rule file
cat > my_rules.rule << 'EOF'
# Append common years
$2 $0 $2 $4
$2 $0 $2 $5
$2 $0 $2 $6
# Append special chars
$!
$@
$#
$$
# Capitalize first letter
c
# Capitalize all
u
# l33t speak
sa@
se3
si1
so0
# Append seasons and years
$s $p $r $i $n $g $2 $4
$s $u $m $m $e $r $2 $4
$f $a $l $l $2 $4
$w $i $n $t $e $r $2 $4
# Company-specific patterns
$T $a $r $g $e $t
$2 $0 $2 $4 $!
EOF
# Apply
hashcat --stdout seeds.txt -r my_rules.rule > custom_expanded.txtBash / Python Mutation Scripts
For patterns that hashcat rules can't easily express.
Append Numbers (0-999)
bash
cat seeds.txt | while read word; do
echo "$word"
for i in $(seq 0 999); do
echo "${word}${i}"
echo "${word}$(printf '%03d' $i)" # zero-padded
done
done > with_numbers.txt
Append Special Characters
bash
cat seeds.txt | while read word; do
echo "$word"
for char in '!' '@' '#' '$' '%' '&' '*' '?' '-'; do
echo "${word}${char}"
done
done > with_special.txt
Capitalization Variants
bash
cat seeds.txt | while read word; do
echo "$word" # original
echo "${word^}" # First letter capital
echo "${word^^}" # ALL CAPS
echo "${word,,}" # all lowercase
done > case_variants.txt
Python — Full Custom Generator
python
#!/usr/bin/env python3
"""Generate a custom wordlist for a specific target."""
import itertools
import argparse
def generate(company, locations, departments, years, special_chars):
words = []
# Base terms
base = [company.lower(), company.upper(), company.capitalize()]
# Add locations
for loc in locations:
base.extend([loc.lower(), loc.capitalize()])
# Add departments
for dept in departments:
base.extend([dept.lower(), dept.capitalize()])
# Simple mutations
for word in base:
words.append(word)
# Append years
for year in years:
words.append(f"{word}{year}")
words.append(f"{word}_{year}")
# Append special chars
for char in special_chars:
words.append(f"{word}{char}")
# Capitalize + year + special
words.append(f"{word.capitalize()}{years[0]}{special_chars[0]}")
# Numbered combinations
for word in base:
for i in range(0, 100):
words.append(f"{word}{i:02d}")
# Leet speak
leet_map = str.maketrans('aeiots', '431075')
for word in base:
words.append(word.translate(leet_map))
return sorted(set(words))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--company', required=True)
parser.add_argument('-l', '--locations', nargs='+', default=[])
parser.add_argument('-d', '--departments', nargs='+', default=['IT','HR','Sales','Finance','Dev'])
parser.add_argument('-y', '--years', nargs='+', default=['2024','2025','2026'])
parser.add_argument('-s', '--special', nargs='+', default=['!','@','#','$'])
parser.add_argument('-o', '--output', default='custom_wordlist.txt')
args = parser.parse_args()
words = generate(
args.company, args.locations, args.departments,
args.years, args.special
)
with open(args.output, 'w') as f:
f.write('\n'.join(words))
print(f"[+] Generated {len(words):,} words → {args.output}")
# Usage:
# python wordgen.py -c TargetCorp -l "NewYork" "Dallas" "Remote" -d "DevOps" "SecOps" -y "2024" "2025"
Keyboard Walk Generator
Generate patterns people actually type — keyboard walks.
bash
pip install kwprocessor
# Generate keyboard walks of 6-12 characters
kwp /usr/share/kwprocessor/keymaps/en-us.keymap \
-s 6 -e 12 -o keyboard_walks.txt
# Common keyboard-only passwords:
start position: q → qwerty, qwertyuiop, qazwsx...
start position: 1 → 123456, 1qaz2wsx, 1q2w3e4r...Date-Based Patterns
People love using dates. Generate all reasonable combinations.
bash
# Python date generator
python3 << 'EOF'
import datetime
formats = [
"%m%d%Y", # 04201988
"%m%d%y", # 042088
"%m-%d-%Y", # 04-20-1988
"%m/%d/%Y", # 04/20/1988
"%B%Y", # April1988
"%b%Y", # Apr1988
"%b%d", # Apr20
"%Y%m%d", # 19880420
]
start = datetime.date(1950, 1, 1)
end = datetime.date(2010, 12, 31)
current = start
with open("dates.txt", "w") as f:
while current <= end:
for fmt in formats:
f.write(current.strftime(fmt) + "\n")
current += datetime.timedelta(days=1)
EOF
# This generates millions — filter for minimum length
awk 'length($0) >= 8' dates.txt > dates_min8.txtCombine Everything Into A Final Wordlist
bash
#!/bin/bash
# build_wordlist.sh — assemble a targeted wordlist
TARGET="$1"
OUTPUT="${2:-final_wordlist.txt}"
echo "[*] Building wordlist for: $TARGET"
# 1. Crawl target website
echo "[1/6] Crawling website..."
cewl "https://$TARGET" -d 2 -m 4 --lowercase -w crawl_raw.txt 2>/dev/null
# 2. Add related terms
echo "[2/6] Adding seed terms..."
cat > seeds.txt << EOF
$TARGET
$(echo $TARGET | tr -d '.com' | tr -d '.org')
admin
administrator
root
password
welcome
default
EOF
# 3. Combine crawl + seeds
cat crawl_raw.txt seeds.txt > combined.txt
# 4. Apply hashcat rules
echo "[3/6] Applying rules..."
hashcat --stdout combined.txt -r /usr/share/hashcat/rules/best64.rule 2>/dev/null > expanded.txt
# 5. Add year/special mutations
echo "[4/6] Adding year/special mutations..."
cat expanded.txt | while read word; do
echo "$word"
for year in 2024 2025 2026; do
echo "${word}${year}"
done
for char in '!' '@' '#'; do
echo "${word}${char}"
done
done > mutated.txt
# 6. Sort, deduplicate, filter
echo "[5/6] Cleaning..."
sort -u mutated.txt | awk 'length($0) >= 6 && length($0) <= 32' > "$OUTPUT"
echo "[6/6] Done: ${OUTPUT} — $(wc -l < "$OUTPUT") words"
# Cleanup
rm crawl_raw.txt seeds.txt combined.txt expanded.txt mutated.txt
Usage:
bash
chmod +x build_wordlist.sh
./build_wordlist.sh target-org.com
Wordlist Optimization
Before using, optimize for the target:
bash
# Filter by password policy
awk 'length($0) >= 8 && length($0) <= 24' input.txt > filtered.txt
# Must contain at least one digit
grep '[0-9]' input.txt > with_digit.txt
# Must contain upper, lower, and digit
grep -P '^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)' input.txt > complex.txt
# Remove pure numbers (rarely work for humans)
grep -v '^[0-9]*$' input.txt > no_pure_numbers.txt
# Prioritization — most common patterns first
# Words with numbers at end are more common
sort input.txt -o sorted.txt
# Then manually move high-value targets to topQuick Size Reference
Method | Input Size | Output Size | Time |
CeWL (crawl) | 1 website | 500–5,000 words | 1–5 min |
Hashcat best64.rule | 1,000 words | ~64,000 words | Seconds |
Hashcat d3ad0ne.rule | 1,000 words | ~35 million words | Minutes |
Crunch (6-char numeric) | — | 1 million | Seconds |
Crunch (8-char alpha) | — | 208 billion | DON'T |
Date generator | — | ~2 million | Minutes |
Keyboard walks | — | ~500,000 | Seconds |






Comments