Skip to content

Commit

Permalink
Merge pull request #2 from spextrow/develop
Browse files Browse the repository at this point in the history
Added decoded access bits as separate column
  • Loading branch information
zhovner committed May 15, 2016
2 parents 1216d25 + 53fe784 commit fe43f8e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Mifare dumps parser

Mifare Classic 1k and 4k dumps parser in human readable format.
Dumps can be grabbed by mfoc or nfc-mfclassic tools from libnfc.org
Dump file size must be 4096 bytes.
Dump file size must be 1024 or 4096 bytes.

Also try this https://github.com/asdil12/mifare-view-dump

Expand Down
88 changes: 76 additions & 12 deletions mfdread.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import sys
from struct import unpack
from datetime import datetime

from bitstring import BitArray


if len(sys.argv) == 1:
Expand All @@ -33,9 +33,61 @@ class bashcolors:
ENDC = '\033[0m'


def accbits_for_blocknum(accbits_str, blocknum):
'''
Decodes the access bit string for block "blocknum".
Returns the three access bits for the block or False if the
inverted bits do not match the access bits.
'''
bits = BitArray([0])
inverted = BitArray([0])
# Block 0 access bits
if blocknum == 0:
bits = BitArray([accbits_str[11], accbits_str[23], accbits_str[19]])
inverted = BitArray([accbits_str[7], accbits_str[3], accbits_str[15]])

# Block 0 access bits
elif blocknum == 1:
bits = BitArray([accbits_str[10], accbits_str[22], accbits_str[18]])
inverted = BitArray([accbits_str[6], accbits_str[2], accbits_str[14]])
# Block 0 access bits
elif blocknum == 2:
bits = BitArray([accbits_str[9], accbits_str[21], accbits_str[17]])
inverted = BitArray([accbits_str[5], accbits_str[1], accbits_str[13]])
# Sector trailer / Block 3 access bits
elif blocknum == 3:
bits = BitArray([accbits_str[8], accbits_str[20], accbits_str[16]])
inverted = BitArray([accbits_str[4], accbits_str[0], accbits_str[12]])

# Check the decoded bits
inverted.invert()
if bits.bin == inverted.bin:
return bits
else:
return False




def accbit_info(accbits):
'''
Returns a dictionary of a access bits for all three blocks in a sector.
If the access bits for block could not be decoded properly, the value is set to False.
'''
decAccbits = {}
# Decode access bits for all 4 blocks of the sector
for i in range(0, 4):
decAccbits[i] = accbits_for_blocknum(accbits, i)
return decAccbits





def print_info(data):

blocksmatrix = []
blockrights = {}

# determine what dump we get 1k or 4k
if len(data) == 4096:
Expand All @@ -58,32 +110,44 @@ def print_info(data):

# add colors for each keyA, access bits, KeyB
for c in range(0, len(blocksmatrix)):
# Fill in the access bits
blockrights[c] = accbit_info(BitArray('0x'+blocksmatrix[c][3][12:20]))
# Prepare colored output of the sector trailor
keyA = bashcolors.RED + blocksmatrix[c][3][0:12] + bashcolors.ENDC
accbits = bashcolors.GREEN + blocksmatrix[c][3][12:20] + bashcolors.ENDC
keyB = bashcolors.BLUE + blocksmatrix[c][3][20:32] + bashcolors.ENDC
blocksmatrix[c][3] = keyA + accbits + keyB


print("File size: %d bytes. Expected %d sectors" %(len(data),cardsize))
print("\n\tUID: " + blocksmatrix[0][0][0:8])
print("\tBCC: " + blocksmatrix[0][0][8:10])
print("\tSAK: " + blocksmatrix[0][0][10:12])
print("\tATQA: " + blocksmatrix[0][0][12:14])
print(" %sKey A%s %sAccess Bits%s %sKey B%s" %(bashcolors.RED,bashcolors.ENDC,bashcolors.GREEN,bashcolors.ENDC,bashcolors.BLUE,bashcolors.ENDC))
print("╔═════════╦═════╦══════════════════════════════════╗")
print("║ Sector ║Block║ Data ║")
print("╔═════════╦═════╦══════════════════════════════════╦═══════════════╗")
print("║ Sector ║Block║ Data ║ Access Bits ║")
for q in range(0, len(blocksmatrix)):
print("╠═════════╬═════╬══════════════════════════════════╣")
print("╠═════════╬═════╬══════════════════════════════════╬═══════════════╣")

# z is the block in each sector
for z in range(0, len(blocksmatrix[q])):
# Format the access bits. Print ERR in case of an error
accbits = ""
if isinstance(blockrights[q][z], BitArray):
accbits = bashcolors.GREEN + blockrights[q][z].bin + bashcolors.ENDC
else:
accbits = bashcolors.WARNING + "ERR" + bashcolors.ENDC

# Add Padding after the sector number
padLen = max(1, 5 - len(str(q)))
padding = " " * padLen
# Only print the sector number in the second third row
if (z == 2):
if (len(str(q)) == 1):
print("║ %d ║ %d ║ %s ║" %(q,z,blocksmatrix[q][z]))
if (len(str(q)) == 2):
print("║ %d ║ %d ║ %s ║" %(q,z,blocksmatrix[q][z]))
if (len(str(q)) == 3):
print("║ %d ║ %d ║ %s ║" %(q,z,blocksmatrix[q][z]))
print("║ %d%s║ %d ║ %s ║ %s ║" %(q,padding,z,blocksmatrix[q][z], accbits))
else:
print("║ ║ %d ║ %s ║" %(z,blocksmatrix[q][z]))
print("╚═════════╩═════╩══════════════════════════════════╝")
print("║ ║ %d ║ %s ║ %s ║" %(z,blocksmatrix[q][z], accbits))
print("╚═════════╩═════╩══════════════════════════════════╩═══════════════╝")


def main(filename):
Expand Down

0 comments on commit fe43f8e

Please sign in to comment.