Skip to content

Instantly share code, notes, and snippets.

@dogtopus
Created February 24, 2023 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dogtopus/3e04554275982f3a86c75a6b6596a558 to your computer and use it in GitHub Desktop.
Save dogtopus/3e04554275982f3a86c75a6b6596a558 to your computer and use it in GitHub Desktop.
Raw Mifare Classic dump to Flipper NFC file v3
import itertools
import pathlib
import sys
FLIPPER_HEADER_CONST = '''
Filetype: Flipper NFC device
Version: 3
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
Device type: Mifare Classic
# UID, ATQA and SAK are common for all formats
'''
ATQA_SAK_TYPES = {
1: ((0x00, 0x04), 0x08),
4: ((0x00, 0x02), 0x18)
}
def emit_header(out, mfd):
tag_type = len(mfd) // 1024
atqa, sak = ATQA_SAK_TYPES[tag_type]
out.write(FLIPPER_HEADER_CONST.strip())
out.write('\n')
out.write(f'UID: {mfd[0]:02x} {mfd[1]:02x} {mfd[2]:02x} {mfd[3]:02x}\n')
out.write(f'ATQA: {atqa[0]:02x} {atqa[1]:02x}\n')
out.write(f'SAK: {sak:02x}\n')
def emit_mfcdata(out, mfd):
tag_type = len(mfd) // 1024
out.write('# Mifare Classic specific data\n')
out.write(f'Mifare Classic type: {tag_type}K\n')
out.write('Data format version: 2\n')
out.write("# Mifare Classic blocks, '??' means unknown data\n")
for i, sector in enumerate(zip(*(16*[iter(mfd)]))):
sector_hex = ' '.join(f'{byte:02x}' for byte in sector)
out.write(f'Block {i}: {sector_hex}\n')
if __name__ == '__main__':
mfd = pathlib.Path(sys.argv[1])
fnfc = pathlib.Path(sys.argv[2])
dump_size = mfd.stat().st_size
if dump_size not in (1024, 4096):
raise RuntimeError('Unexpected dump size')
mfd_data = mfd.read_bytes()
with fnfc.open('w') as fnfc_file:
emit_header(fnfc_file, mfd_data)
emit_mfcdata(fnfc_file, mfd_data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment