]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/scripts/formatMifare.lua
fix/add support for 4K (and other non 1K) card sizes in hf mf commands
[proxmark3-svn] / client / scripts / formatMifare.lua
1 local cmds = require('commands')
2 local getopt = require('getopt')
3 local bin = require('bin')
4 local lib14a = require('read14a')
5 local utils = require('utils')
6
7 example =[[
8 1. script run formatMifare
9 2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780
10 ]]
11 author = "Iceman"
12 usage = "script run formatMifare -k <key>"
13 desc =[[
14 This script will generate 'hf mf wrbl' commands for each block to format a Mifare card.
15
16 Alla datablocks gets 0x00
17 As default the script sets the keys A/B to 0xFFFFFFFFFFFF
18 and the access bytes will become 0x78,0x77,0x88
19 The GDB will become 0x00
20
21 The script will skip the manufactoring block 0.
22
23 Arguments:
24 -h - this help
25 -k <key> - the current six byte key with write access
26 -n <key> - the new key that will be written to the card
27 -a <access> - the new access bytes that will be written to the card
28 ]]
29 local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
30 local DEBUG = true -- the debug flag
31 local CmdString = 'hf mf wrbl %d B %s %s'
32 local numBlocks = 64
33 local numSectors = 16
34 ---
35 -- A debug printout-function
36 function dbg(args)
37 if not DEBUG then
38 return
39 end
40
41 if type(args) == "table" then
42 local i = 1
43 while result[i] do
44 dbg(result[i])
45 i = i+1
46 end
47 else
48 print("###", args)
49 end
50 end
51 ---
52 -- This is only meant to be used when errors occur
53 function oops(err)
54 print("ERROR: ",err)
55 end
56 ---
57 -- Usage help
58 function help()
59 print(desc)
60 print("Example usage")
61 print(example)
62 end
63 --
64 -- Exit message
65 function ExitMsg(msg)
66 print( string.rep('--',20) )
67 print( string.rep('--',20) )
68 print(msg)
69 print()
70 end
71 --
72 -- Read information from a card
73 function GetCardInfo()
74 result, err = lib14a.read1443a(false)
75 if not result then
76 print(err)
77 return
78 end
79 print(("Found: %s"):format(result.name))
80
81 core.clearCommandBuffer()
82
83 if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k
84 -- IFARE Classic 4K offers 4096 bytes split into forty sectors,
85 -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
86 numSectors = 40
87 elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
88 -- 1K offers 1024 bytes of data storage, split into 16 sector
89 numSectors = 16
90 elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
91 -- MIFARE Classic mini offers 320 bytes split into five sectors.
92 numSectors = 5
93 elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k"
94 numSectors = 32
95 else
96 print("I don't know how many sectors there are on this type of card, defaulting to 16")
97 end
98 --[[
99 The mifare Classic 1k card has 16 sectors of 4 data blocks each.
100 The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
101 8 sectors consist of 16 data blocks.
102 --]]
103
104 -- Defaults to 16 * 4 = 64 - 1 = 63
105 numBlocks = numSectors * 4 - 1
106
107 if numSectors > 32 then
108 numBlocks = 32*4+ (numSectors-32)*16 -1
109 end
110
111 end
112
113 local function main(args)
114
115 print( string.rep('--',20) )
116 print( string.rep('--',20) )
117 print()
118
119 local OldKey
120 local NewKey
121 local Accessbytes
122
123 -- Arguments for the script
124 for o, a in getopt.getopt(args, 'hk:n:a:') do
125 if o == "h" then return help() end
126 if o == "k" then OldKey = a end
127 if o == "n" then NewKey = a end
128 if o == "a" then Accessbytes = a end
129 end
130
131 -- validate input args.
132 OldKey = OldKey or 'FFFFFFFFFFFF'
133 if #(OldKey) ~= 12 then
134 return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))
135 end
136
137 NewKey = NewKey or 'FFFFFFFFFFFF'
138 if #(NewKey) ~= 12 then
139 return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))
140 end
141
142 --Accessbytes = Accessbytes or '787788'
143 Accessbytes = Accessbytes or 'FF0780'
144 if #(Accessbytes) ~= 6 then
145 return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))
146 end
147
148 GetCardInfo()
149
150 -- Show info
151 print( string.format('Estimating number of blocks: %d', numBlocks))
152 print( string.format('Old key: %s', OldKey))
153 print( string.format('New key: %s', NewKey))
154 print( string.format('New Access: %s', Accessbytes))
155 print( string.rep('--',20) )
156
157 -- Set new block data
158 local EMPTY_BL = string.rep('00',16)
159 local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey)
160
161 dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL))
162 dbg( string.format('New emptyblock: %s',EMPTY_BL))
163 dbg('')
164
165 -- Ask
166 local dialogResult = utils.confirm("Do you want to erase this card")
167 if dialogResult == false then
168 return ExitMsg('Quiting it is then. Your wish is my command...')
169 end
170
171 print( string.rep('--',20) )
172
173 -- main loop
174 for block=0,numBlocks,1 do
175
176 local reminder = (block+1) % 4
177 local cmd
178 if reminder == 0 then
179 cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)
180 else
181 cmd = CmdString:format(block, OldKey , EMPTY_BL)
182 end
183
184 if block ~= 0 then
185 print(cmd)
186 --core.console(cmd)
187 end
188
189 if core.ukbhit() then
190 print("aborted by user")
191 break
192 end
193 end
194 end
195
196 main(args)
Impressum, Datenschutz