mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-15 14:20:51 +08:00
154 lines
4.3 KiB
Python
Executable file
154 lines
4.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import pexpect
|
|
from colors import color
|
|
import re
|
|
import argparse
|
|
import os
|
|
import fnmatch
|
|
|
|
'''
|
|
# pm3_gen_dictionary.py
|
|
# Christian Herrmann, Iceman, <iceman@icesql.se> 2023
|
|
# version = 'v1.0.0'
|
|
#
|
|
# This code is copyright (c) Christian Herrmann, 2023, All rights reserved.
|
|
# For non-commercial use only, the following terms apply - for all other
|
|
# uses, please contact the author:
|
|
#
|
|
# This code is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This code is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
#
|
|
# Dependencies:
|
|
#
|
|
# pip3 install pexpect ansicolors
|
|
#
|
|
# Usage:
|
|
#
|
|
# ./pm3_gen_dictionary.py --path folder --fn mydictionary.dic -v
|
|
#
|
|
# Info:
|
|
# Will search all dump files files in given folder and all its subfolders
|
|
# With the option to save found keys to a text file.
|
|
#
|
|
'''
|
|
|
|
def escape_ansi(line):
|
|
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
|
|
return ansi_escape.sub('', str(line)).lower()
|
|
|
|
def parse_keys(line):
|
|
"""
|
|
Parse keys from a line and return them as a set.
|
|
Keys must be 12 hex characters long
|
|
:param line: string containing keys.
|
|
:return: A set of keys read from the line
|
|
"""
|
|
keys = set()
|
|
key_regex = re.compile('[0-9a-fA-F]{12}')
|
|
|
|
key = key_regex.findall(line)
|
|
if not key:
|
|
return []
|
|
|
|
try:
|
|
keys.add(key[0])
|
|
keys.add(key[1])
|
|
except AttributeError:
|
|
pass
|
|
return keys
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--path", help="Path to folder")
|
|
parser.add_argument("--fn", help="Dictionary file name")
|
|
parser.add_argument("-v", help="verbose output", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
path = args.path
|
|
verbose = args.v
|
|
# Check if the directory exists
|
|
if not os.path.isdir(path):
|
|
print("The provided directory does not exist.")
|
|
return
|
|
|
|
# start pm3
|
|
child = pexpect.spawnu('./pm3 -o')
|
|
i = child.expect('pm3 --> ')
|
|
print("[+] Proxmark3 client open")
|
|
|
|
|
|
# MIFARE CLASSIC dumps
|
|
pattern = 'hf-mf-*-dump*'
|
|
|
|
print(f'[+] Iterating all dumpfiles in... ', color(f'{path}', fg='cyan'))
|
|
# Walk through the directory
|
|
keys = set()
|
|
for root, dirs, files in os.walk(path):
|
|
for file in files:
|
|
# Check if the file name starts with the given prefix
|
|
if fnmatch.fnmatch(file, pattern):
|
|
if ":Zone.Identifier" in file:
|
|
continue
|
|
if ":OECustomProperty" in file:
|
|
continue
|
|
|
|
f = os.path.join(root, file)
|
|
cmd = f'hf mf view -v -f {f}'
|
|
if verbose:
|
|
print(cmd)
|
|
|
|
# Send proxmark3 commnad
|
|
child.sendline(cmd)
|
|
i = child.expect('pm3 --> ')
|
|
msg = escape_ansi(str(child.before))
|
|
|
|
# extract key table from msg
|
|
found = False
|
|
for line in msg.splitlines():
|
|
|
|
if found == False:
|
|
key_row = line.find('000 | 003')
|
|
if key_row > -1:
|
|
found = True
|
|
|
|
if found:
|
|
foo = parse_keys(line)
|
|
if not foo:
|
|
found = False
|
|
continue
|
|
|
|
# append found set
|
|
keys |= foo
|
|
|
|
# shut down proxmark3 client connection
|
|
child.sendline('quit')
|
|
child.expect(pexpect.EOF)
|
|
print("[+] Proxmark3 client closed")
|
|
|
|
# print all found keys
|
|
if verbose:
|
|
for k in keys:
|
|
print(f'{k}')
|
|
print("")
|
|
|
|
# save keys
|
|
if args.fn:
|
|
print(f'[+] Writing keys to dictionary file... ', color(f'{args.fn}', fg='cyan'))
|
|
with open(args.fn, 'w') as f:
|
|
for k in keys:
|
|
f.write(f'{k}\n')
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
main()
|