]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/pm3_mfdread.py
2 # -*- coding: utf-8 -*-
4 # mfdread.py - Mifare dumps parser in human readable format
5 # Pavel Zhovner <pavel@zhovner.com>
6 # https://github.com/zhovner/mfdread
12 from struct
import unpack
13 from datetime
import datetime
14 from bitstring
import BitArray
17 if len(sys
.argv
) == 1:
20 Usage: mfdread.py ./dump.mfd
37 def accbits_for_blocknum(accbits_str
, blocknum
):
39 Decodes the access bit string for block "blocknum".
40 Returns the three access bits for the block or False if the
41 inverted bits do not match the access bits.
44 inverted
= BitArray([0])
47 bits
= BitArray([accbits_str
[11], accbits_str
[23], accbits_str
[19]])
48 inverted
= BitArray([accbits_str
[7], accbits_str
[3], accbits_str
[15]])
52 bits
= BitArray([accbits_str
[10], accbits_str
[22], accbits_str
[18]])
53 inverted
= BitArray([accbits_str
[6], accbits_str
[2], accbits_str
[14]])
56 bits
= BitArray([accbits_str
[9], accbits_str
[21], accbits_str
[17]])
57 inverted
= BitArray([accbits_str
[5], accbits_str
[1], accbits_str
[13]])
58 # Sector trailer / Block 3 access bits
60 bits
= BitArray([accbits_str
[8], accbits_str
[20], accbits_str
[16]])
61 inverted
= BitArray([accbits_str
[4], accbits_str
[0], accbits_str
[12]])
63 # Check the decoded bits
65 if bits
.bin
== inverted
.bin
:
73 def accbit_info(accbits
):
75 Returns a dictionary of a access bits for all three blocks in a sector.
76 If the access bits for block could not be decoded properly, the value is set to False.
79 # Decode access bits for all 4 blocks of the sector
81 decAccbits
[i
] = accbits_for_blocknum(accbits
, i
)
93 # determine what dump we get 1k or 4k
96 elif len(data
) == 1024:
99 print("Wrong file size: %d bytes.\nOnly 1024 or 4096 allowed." % len(data
))
103 for i
in range(0, cardsize
):
106 sector
= data
[start
:end
]
107 sector
= codecs
.encode(sector
, 'hex')
108 if not type(sector
) is str:
109 sector
= str(sector
, 'ascii')
110 blocksmatrix
.append([sector
[x
:x
+32] for x
in range(0, len(sector
), 32)])
112 # add colors for each keyA, access bits, KeyB
113 for c
in range(0, len(blocksmatrix
)):
114 # Fill in the access bits
115 blockrights
[c
] = accbit_info(BitArray('0x'+blocksmatrix
[c
][3][12:20]))
116 # Prepare colored output of the sector trailor
117 keyA
= bashcolors
.RED
+ blocksmatrix
[c
][3][0:12] + bashcolors
.ENDC
118 accbits
= bashcolors
.GREEN
+ blocksmatrix
[c
][3][12:20] + bashcolors
.ENDC
119 keyB
= bashcolors
.BLUE
+ blocksmatrix
[c
][3][20:32] + bashcolors
.ENDC
120 blocksmatrix
[c
][3] = keyA
+ accbits
+ keyB
123 print("File size: %d bytes. Expected %d sectors" %(len(data
),cardsize
))
124 print("\n\tUID: " + blocksmatrix
[0][0][0:8])
125 print("\tBCC: " + blocksmatrix
[0][0][8:10])
126 print("\tSAK: " + blocksmatrix
[0][0][10:12])
127 print("\tATQA: " + blocksmatrix
[0][0][12:14])
128 print(" %sKey A%s %sAccess Bits%s %sKey B%s" %(bashcolors
.RED
,bashcolors
.ENDC
,bashcolors
.GREEN
,bashcolors
.ENDC
,bashcolors
.BLUE
,bashcolors
.ENDC
))
129 print("╔═════════╦═════╦══════════════════════════════════╦═══════════════╗")
130 print("║ Sector ║Block║ Data ║ Access Bits ║")
131 for q
in range(0, len(blocksmatrix
)):
132 print("╠═════════╬═════╬══════════════════════════════════╬═══════════════╣")
134 # z is the block in each sector
135 for z
in range(0, len(blocksmatrix
[q
])):
136 # Format the access bits. Print ERR in case of an error
138 if isinstance(blockrights
[q
][z
], BitArray
):
139 accbits
= bashcolors
.GREEN
+ blockrights
[q
][z
].bin
+ bashcolors
.ENDC
141 accbits
= bashcolors
.WARNING
+ "ERR" + bashcolors
.ENDC
143 # Add Padding after the sector number
144 padLen
= max(1, 5 - len(str(q
)))
145 padding
= " " * padLen
146 # Only print the sector number in the second third row
148 print("║ %d%s║ %d ║ %s ║ %s ║" %(q
,padding
,z
,blocksmatrix
[q
][z
], accbits
))
150 print("║ ║ %d ║ %s ║ %s ║" %(z
,blocksmatrix
[q
][z
], accbits
))
151 print("╚═════════╩═════╩══════════════════════════════════╩═══════════════╝")
155 with
open(filename
, "rb") as f
:
159 if __name__
== "__main__":