]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/pm3_mfdread.py
ADD: @zhovner 's mfd file parser https://github.com/zhovner/mfdread Looks really...
[proxmark3-svn] / client / pm3_mfdread.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # mfdread.py - Mifare dumps parser in human readable format
5 # Pavel Zhovner <pavel@zhovner.com>
6 # https://github.com/zhovner/mfdread
7
8
9
10 import codecs
11 import sys
12 from struct import unpack
13 from datetime import datetime
14 from bitstring import BitArray
15
16
17 if len(sys.argv) == 1:
18 print('''
19 ------------------
20 Usage: mfdread.py ./dump.mfd
21 Mifare dumps reader.
22
23 ''')
24 sys.exit();
25
26
27
28
29 class bashcolors:
30 BLUE = '\033[34m'
31 RED = '\033[91m'
32 GREEN = '\033[32m'
33 WARNING = '\033[93m'
34 ENDC = '\033[0m'
35
36
37 def accbits_for_blocknum(accbits_str, blocknum):
38 '''
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.
42 '''
43 bits = BitArray([0])
44 inverted = BitArray([0])
45 # Block 0 access bits
46 if blocknum == 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]])
49
50 # Block 0 access bits
51 elif blocknum == 1:
52 bits = BitArray([accbits_str[10], accbits_str[22], accbits_str[18]])
53 inverted = BitArray([accbits_str[6], accbits_str[2], accbits_str[14]])
54 # Block 0 access bits
55 elif blocknum == 2:
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
59 elif blocknum == 3:
60 bits = BitArray([accbits_str[8], accbits_str[20], accbits_str[16]])
61 inverted = BitArray([accbits_str[4], accbits_str[0], accbits_str[12]])
62
63 # Check the decoded bits
64 inverted.invert()
65 if bits.bin == inverted.bin:
66 return bits
67 else:
68 return False
69
70
71
72
73 def accbit_info(accbits):
74 '''
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.
77 '''
78 decAccbits = {}
79 # Decode access bits for all 4 blocks of the sector
80 for i in range(0, 4):
81 decAccbits[i] = accbits_for_blocknum(accbits, i)
82 return decAccbits
83
84
85
86
87
88 def print_info(data):
89
90 blocksmatrix = []
91 blockrights = {}
92
93 # determine what dump we get 1k or 4k
94 if len(data) == 4096:
95 cardsize = 64
96 elif len(data) == 1024:
97 cardsize = 16
98 else:
99 print("Wrong file size: %d bytes.\nOnly 1024 or 4096 allowed." % len(data))
100 sys.exit();
101
102 # read all sectors
103 for i in range(0, cardsize):
104 start = i * 64
105 end = (i + 1) * 64
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)])
111
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
121
122
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("╠═════════╬═════╬══════════════════════════════════╬═══════════════╣")
133
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
137 accbits = ""
138 if isinstance(blockrights[q][z], BitArray):
139 accbits = bashcolors.GREEN + blockrights[q][z].bin + bashcolors.ENDC
140 else:
141 accbits = bashcolors.WARNING + "ERR" + bashcolors.ENDC
142
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
147 if (z == 2):
148 print("║ %d%s %d %s %s ║" %(q,padding,z,blocksmatrix[q][z], accbits))
149 else:
150 print("║ ║ %d %s %s ║" %(z,blocksmatrix[q][z], accbits))
151 print("╚═════════╩═════╩══════════════════════════════════╩═══════════════╝")
152
153
154 def main(filename):
155 with open(filename, "rb") as f:
156 data = f.read()
157 print_info(data)
158
159 if __name__ == "__main__":
160 main(sys.argv[1])
Impressum, Datenschutz