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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
#!/usr/bin/env python3
'''
greps inside hccapx/pmkid structs by essid, mac_ap or mac_sta
This software is Copyright (c) 2019-2023, Alex Stanev <alex at stanev.org>
and it is hereby released to the general public under the following terms:
Redistribution and use in source and binary forms, with or without
modification, are permitted.
'''
import argparse
import os
import sys
import binascii
import struct
import re
maketrans = bytearray.maketrans
def parse_hccapx(hccapx):
'''hccapx decompose
https://hashcat.net/wiki/doku.php?id=hccapx
struct hccapx
{
u32 signature;
u32 version;
u8 message_pair;
u8 essid_len;
u8 essid[32];
u8 keyver;
u8 keymic[16];
u8 mac_ap[6];
u8 nonce_ap[32];
u8 mac_sta[6];
u8 nonce_sta[32];
u16 eapol_len;
u8 eapol[256];
} __attribute__((packed));
'''
hccapx_fmt = '< 4x 4x x B 32s x 16x 6s 32x 6s 32x 2x 256x'
try:
(essid_len, essid,
mac_ap, mac_sta) = struct.unpack(hccapx_fmt, hccapx)
except struct.error:
sys.stderr.write('Can\'t parse hcccapx struct!\n')
sys.exit(1)
# fixup
if args.t == 'essid':
return essid[:essid_len]
if args.t == 'mac_ap':
return binascii.hexlify(mac_ap).zfill(12)
if args.t == 'mac_sta':
return binascii.hexlify(mac_sta).zfill(12)
return None
def parse_pmkid(pmkid):
'''pmkid decompose
format:
pmkid*mac_ap*mac_sta*essid
'''
arr = pmkid.split(b'*', 4)
if len(arr) == 4:
try:
if args.t == 'essid':
return binascii.unhexlify(arr[3].strip())
if args.t == 'mac_ap':
return arr[1]
if args.t == 'mac_sta':
return arr[2]
except TypeError:
sys.stderr.write('Can\'t decode: {}\n'.format(arr[3].strip().decode()))
sys.exit(1)
return None
def parse_combined(hashline):
'''m22000 hashline decompose
format:
SIGNATURE*TYPE*PMKID/MIC*MACAP*MACSTA*ESSID*ANONCE*EAPOL*MESSAGEPAIR
'''
arr = hashline.split(b'*', 9)
if len(arr) == 9:
try:
if args.t == 'essid':
return binascii.unhexlify(arr[5].strip())
if args.t == 'mac_ap':
return arr[3]
if args.t == 'mac_sta':
return arr[4]
except TypeError:
sys.stderr.write('Can\'t decode: {}\n'.format(arr[5].strip().decode()))
sys.exit(1)
return None
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Extract records from m22000 hashline/hccapx/pmkid file with regexp')
parser.add_argument(
'-f', '--file', type=argparse.FileType('r'),
help='Obtain patterns from FILE, one per line.')
parser.add_argument(
'PATTERNS', type=str, nargs='?',
help='RegExp pattern')
parser.add_argument(
'-v', '--invert-match', dest='v', action='store_true',
help='Invert the sense of matching, to select non-matching nets')
parser.add_argument(
'-t', '--type', dest='t',
choices=['essid', 'mac_ap', 'mac_sta'], default='essid',
help='Field to apply matching, default essid')
parser.add_argument(
'infile', type=str, nargs='?',
help='hccapx/pmkid file to process')
try:
args = parser.parse_args()
except IOError as ex:
parser.error(str(ex))
# shift parameters
if args.file and args.PATTERNS:
args.infile = args.PATTERNS
args.PATTERNS = None
# no patterns set
if args.PATTERNS is None and args.file is None:
parser.print_help(sys.stderr)
sys.stderr.write('You must provide PATTERNS or -f FILE\n')
sys.exit(1)
# read patterns from file
if args.PATTERNS is None:
args.PATTERNS = '|'.join('(?:{0})'.format(x.strip()) for x in args.file)
try:
regexp = re.compile(bytes(args.PATTERNS, 'utf-8'))
except re.error as ex:
sys.stderr.write('Wrong regexp {0}: {1} \n'.format(args.PATTERNS, ex))
sys.exit(1)
if args.infile is not None and os.path.isfile(args.infile):
fd = open(args.infile, 'rb')
else:
fd = sys.stdin.buffer
while True:
buf = fd.read(4)
if buf == b'WPA*':
buf = buf + fd.readline()
target = parse_combined(buf)
elif buf == b'HCPX':
buf = buf + fd.read(393 - 4)
target = parse_hccapx(buf)
else:
buf = buf + fd.readline()
target = parse_pmkid(buf)
if not buf:
break
if target is None:
sys.stderr.write('Unrecognized input format\n')
sys.exit(1)
res = regexp.search(target)
if (res is not None and not args.v) or (res is None and args.v):
sys.stdout.buffer.write(buf)
|