mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-05 04:25:20 +08:00
added a python3 script that given a folder will try to extract all keys in the dump files and create a unique dictionary text file
This commit is contained in:
parent
c1ec770a69
commit
cd167b4632
2 changed files with 155 additions and 0 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added `pm3_gen_dictionary.py` - python script to extract and save all keys from MFC dump files. (@iceman1001)
|
||||
- Changed `hf mfu info` - now detect MIFARE Ultralight AES (@iceman1001)
|
||||
- Changed `hf mf autopwn` - now supports multiple user supplied keys (@iceman1001)
|
||||
- Added `hf mf gchpwd` command for change Gen4 GTU card access password (@merlokk)
|
||||
|
|
154
tools/pm3_gen_dictionary.py
Executable file
154
tools/pm3_gen_dictionary.py
Executable file
|
@ -0,0 +1,154 @@
|
|||
#!/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()
|
Loading…
Reference in a new issue