2 # -*- coding: utf-8 -*-
5 from colors
import color
12 # pm3_gen_dictionary.py
13 # Christian Herrmann, Iceman, <iceman@icesql.se> 2023
16 # This code is copyright (c) Christian Herrmann, 2023, All rights reserved.
17 # For non-commercial use only, the following terms apply - for all other
18 # uses, please contact the author:
20 # This code is free software; you can redistribute it and/or modify
21 # it under the terms of the GNU General Public License as published by
22 # the Free Software Foundation; either version 3 of the License, or
23 # (at your option) any later version.
25 # This code is distributed in the hope that it will be useful,
26 # but WITHOUT ANY WARRANTY; without even the implied warranty of
27 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 # GNU General Public License for more details.
33 # pip3 install pexpect ansicolors
37 # ./pm3_gen_dictionary.py --path folder --fn mydictionary.dic -v
40 # Will search all dump files files in given folder and all its subfolders
41 # With the option to save found keys to a text file.
45 def escape_ansi(line
):
46 ansi_escape
= re
.compile(r
'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
47 return ansi_escape
.sub('', str(line
)).lower()
51 Parse keys from a line and return them as a set.
52 Keys must be 12 hex characters long
53 :param line: string containing keys.
54 :return: A set of keys read from the line
57 key_regex
= re
.compile('[0-9a-fA-F]{12}')
59 key
= key_regex
.findall(line
)
66 except AttributeError:
71 parser
= argparse
.ArgumentParser()
72 parser
.add_argument("--path", help="Path to folder")
73 parser
.add_argument("--fn", help="Dictionary file name")
74 parser
.add_argument("-v", help="verbose output", action
="store_true")
75 args
= parser
.parse_args()
79 # Check if the directory exists
80 if not os
.path
.isdir(path
):
81 print("The provided directory does not exist.")
85 child
= pexpect
.spawnu('./pm3 -o')
86 i
= child
.expect('pm3 --> ')
87 print("[+] Proxmark3 client open")
90 # MIFARE CLASSIC dumps
91 pattern
= 'hf-mf-*-dump*'
93 print(f
'[+] Iterating all dumpfiles in... ', color(f
'{path}', fg
='cyan'))
94 # Walk through the directory
96 for root
, dirs
, files
in os
.walk(path
):
98 # Check if the file name starts with the given prefix
99 if fnmatch
.fnmatch(file, pattern
):
100 if ":Zone.Identifier" in file:
102 if ":OECustomProperty" in file:
105 f
= os
.path
.join(root
, file)
106 cmd
= f
'hf mf view -v -f {f}'
110 # Send proxmark3 commnad
112 i
= child
.expect('pm3 --> ')
113 msg
= escape_ansi(str(child
.before
))
115 # extract key table from msg
117 for line
in msg
.splitlines():
120 key_row
= line
.find('000 | 003')
125 foo
= parse_keys(line
)
133 # shut down proxmark3 client connection
134 child
.sendline('quit')
135 child
.expect(pexpect
.EOF
)
136 print("[+] Proxmark3 client closed")
138 # print all found keys
146 print(f
'[+] Writing keys to dictionary file... ', color(f
'{args.fn}', fg
='cyan'))
147 with
open(args
.fn
, 'w') as f
:
153 if __name__
== "__main__":