Skip to content

Add directory support for --dict switch#455

Merged
kimocoder merged 1 commit intomasterfrom
claude/add-dict-path-support-h95DW
Mar 6, 2026
Merged

Add directory support for --dict switch#455
kimocoder merged 1 commit intomasterfrom
claude/add-dict-path-support-h95DW

Conversation

@kimocoder
Copy link
Copy Markdown
Owner

When --dict is given a directory path instead of a file, wifite now collects all files in the directory and uses them as wordlists for cracking. Each wordlist is tried sequentially until a password is found or all wordlists are exhausted.

Changes:

  • config.py: Add wordlists list, handle directory paths in --dict
  • args.py: Update help text to indicate file/directory support
  • tools: Add optional wordlist parameter to all cracking tools (hashcat, aircrack, john, cowpatty)
  • attacks: Iterate through multiple wordlists in WPA, PMKID, and PMKID passive attacks
  • util/crack.py: Support directory input in manual crack mode

When --dict is given a directory path instead of a file, wifite now
collects all files in the directory and uses them as wordlists for
cracking. Each wordlist is tried sequentially until a password is
found or all wordlists are exhausted.

Changes:
- config.py: Add wordlists list, handle directory paths in --dict
- args.py: Update help text to indicate file/directory support
- tools: Add optional wordlist parameter to all cracking tools
  (hashcat, aircrack, john, cowpatty)
- attacks: Iterate through multiple wordlists in WPA, PMKID, and
  PMKID passive attacks
- util/crack.py: Support directory input in manual crack mode

https://claude.ai/code/session_01SLvptkig8m8QXCLeBLFcQ3
Copilot AI review requested due to automatic review settings March 6, 2026 02:54
@kimocoder kimocoder merged commit 8747b2f into master Mar 6, 2026
11 of 12 checks passed
@kimocoder kimocoder deleted the claude/add-dict-path-support-h95DW branch March 6, 2026 02:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for passing a directory to --dict so Wifite can iterate through multiple wordlists sequentially during cracking, improving usability for users who maintain wordlists as folders.

Changes:

  • Extend configuration/CLI handling to accept --dict as either a file or directory (expanding directories into a sorted list of files).
  • Update cracking flows (WPA + PMKID + manual crack helper) to try multiple wordlists until a key is found.
  • Add optional wordlist parameter to cracking tool wrappers (hashcat/aircrack/john/cowpatty) so callers can override the active wordlist per attempt.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
wifite/config.py Adds Configuration.wordlists and expands --dict directory inputs into multiple wordlists.
wifite/args.py Updates --dict help/metavar to reflect file-or-directory behavior.
wifite/util/crack.py Manual cracking mode now accepts a wordlist directory and iterates through expanded files.
wifite/attack/wpa.py WPA cracking now iterates across multiple wordlists with per-wordlist progress/logging.
wifite/attack/pmkid.py PMKID cracking now iterates through multiple wordlists.
wifite/attack/pmkid_passive.py Passive PMKID cracking now iterates through multiple wordlists.
wifite/tools/hashcat.py Adds wordlist override to handshake + PMKID cracking (and propagates to aircrack fallback).
wifite/tools/aircrack.py Adds wordlist override to handshake cracking.
wifite/tools/john.py Adds wordlist override to handshake cracking.
wifite/tools/cowpatty.py Adds wordlist override to handshake cracking.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

wep_restart_aircrack = None
wep_restart_stale_ivs = None
wordlist = None
wordlists = []
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wordlists is defined as a mutable class attribute ([]). This can lead to surprising shared state across imports/runs in long-lived processes. Prefer initializing it to None at the class level (like most other config fields) and assigning a fresh list in initialize() / arg parsing.

Suggested change
wordlists = []
wordlists = None

Copilot uses AI. Check for mistakes.
Comment on lines +787 to +801
files = sorted([
os.path.join(dict_dir, f)
for f in os.listdir(dict_dir)
if os.path.isfile(os.path.join(dict_dir, f))
])
if files:
cls.wordlists = files
cls.wordlist = files[0]
Color.pl('{+} {C}option:{W} using {G}%d{W} wordlist(s) from directory {G}%s{W} for cracking'
% (len(files), dict_dir))
else:
cls.wordlist = None
cls.wordlists = []
Color.pl('{+} {C}option:{O} wordlist directory {R}%s{O} contains no files. Wifite will NOT '
'attempt to crack handshakes' % dict_dir)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directory wordlist expansion uses os.listdir(dict_dir) without handling OSError (e.g., permission denied, transient IO issues). That can crash argument parsing even though the path exists. Wrap the directory scan in try/except OSError and emit a user-facing message (and disable cracking) on failure.

Suggested change
files = sorted([
os.path.join(dict_dir, f)
for f in os.listdir(dict_dir)
if os.path.isfile(os.path.join(dict_dir, f))
])
if files:
cls.wordlists = files
cls.wordlist = files[0]
Color.pl('{+} {C}option:{W} using {G}%d{W} wordlist(s) from directory {G}%s{W} for cracking'
% (len(files), dict_dir))
else:
cls.wordlist = None
cls.wordlists = []
Color.pl('{+} {C}option:{O} wordlist directory {R}%s{O} contains no files. Wifite will NOT '
'attempt to crack handshakes' % dict_dir)
try:
files = sorted([
os.path.join(dict_dir, f)
for f in os.listdir(dict_dir)
if os.path.isfile(os.path.join(dict_dir, f))
])
except OSError as e:
cls.wordlist = None
cls.wordlists = []
Color.pl('{+} {C}option:{O} could not read wordlist directory {R}%s{O}: %s. Wifite will NOT '
'attempt to crack handshakes' % (dict_dir, e))
else:
if files:
cls.wordlists = files
cls.wordlist = files[0]
Color.pl('{+} {C}option:{W} using {G}%d{W} wordlist(s) from directory {G}%s{W} for cracking'
% (len(files), dict_dir))
else:
cls.wordlist = None
cls.wordlists = []
Color.pl('{+} {C}option:{O} wordlist directory {R}%s{O} contains no files. Wifite will NOT '
'attempt to crack handshakes' % dict_dir)

Copilot uses AI. Check for mistakes.
Comment on lines +116 to +118
files = sorted([
os.path.join(user_input, f)
for f in os.listdir(user_input)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directory wordlist expansion uses os.listdir(user_input) without handling OSError (e.g., permission denied). Since this is interactive mode, an unhandled exception will drop the user back to a traceback. Wrap the directory scan in try/except OSError and show a clear error before exiting.

Suggested change
files = sorted([
os.path.join(user_input, f)
for f in os.listdir(user_input)
try:
entries = os.listdir(user_input)
except OSError as e:
Color.pl('{!} {R}Failed to read directory {O}%s{R}: %s. Exiting.' % (user_input, e))
return
files = sorted([
os.path.join(user_input, f)
for f in entries

Copilot uses AI. Check for mistakes.
Color.pl('{!} {O}Not cracking handshake because wordlist {R}%s{O} was not found' % Configuration.wordlist)

# Get list of wordlists to try
wordlists_to_try = [wl for wl in Configuration.wordlists if os.path.exists(wl)]
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wordlists_to_try is derived only from Configuration.wordlists. If Configuration.wordlist is set but Configuration.wordlists is empty (e.g., session restore sets wordlist but not wordlists), this will incorrectly skip cracking with “no valid wordlist files”. Consider falling back to [Configuration.wordlist] when Configuration.wordlists is empty, and filtering with os.path.isfile() (not just exists()).

Suggested change
wordlists_to_try = [wl for wl in Configuration.wordlists if os.path.exists(wl)]
base_wordlists = Configuration.wordlists if getattr(Configuration, 'wordlists', None) else [Configuration.wordlist]
wordlists_to_try = [wl for wl in base_wordlists if os.path.isfile(wl)]

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants