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 local ansicolors
= require('ansicolors')
12 This script will generate 'hf mf wrbl' commands for each block to format a Mifare Classic card.
14 Alla datablocks gets 0x00
15 As default the script sets the keys A/B to 0xFFFFFFFFFFFF
16 and the access bytes will become 0x78,0x77,0x88
17 The GPB will become 0x00
19 The script will skip the manufactoring block 0.
23 1. script run hf_mf_format
25 -- generate command, replacing key with new key.
26 2. script run hf_mf_format -k aabbccddeeff -n 112233445566 -a FF0780
28 -- generate commands and execute them against card.
29 3. script run hf_mf_format -x
32 script run hf_mf_format -k <key> -n <key> -a <access> -x
36 -k <key> - the current six byte key with write access
37 -n <key> - the new key that will be written to the card
38 -a <access> - the new access bytes that will be written to the card
39 -x - execute the commands as well.
42 local TIMEOUT
= 2000 -- Shouldn't take longer than 2 seconds
43 local DEBUG
= true -- the debug flag
44 local CmdString
= 'hf mf wrbl --blk %d -b -k %s -d %s'
48 -- A debug printout-function
49 local function dbg(args
)
50 if not DEBUG
then return end
51 if type(args
) == 'table' then
62 -- This is only meant to be used when errors occur
63 local function oops(err
)
65 core
.clearCommandBuffer()
75 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
77 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
79 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
84 local function ExitMsg(msg
)
85 print( string.rep('--',20) )
86 print( string.rep('--',20) )
91 -- Read information from a card
92 local function GetCardInfo()
93 result
, err
= lib14a
.read(false, true)
98 print(('Found: %s'):format(result
.name
))
100 core
.clearCommandBuffer()
102 if 0x18 == result
.sak
then -- NXP MIFARE Classic 4k | Plus 4k
103 -- IFARE Classic 4K offers 4096 bytes split into forty sectors,
104 -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
106 elseif 0x08 == result
.sak
then -- NXP MIFARE CLASSIC 1k | Plus 2k
107 -- 1K offers 1024 bytes of data storage, split into 16 sector
109 elseif 0x09 == result
.sak
then -- NXP MIFARE Mini 0.3k
110 -- MIFARE Classic mini offers 320 bytes split into five sectors.
112 elseif 0x10 == result
.sak
then -- NXP MIFARE Plus 2k
114 elseif 0x01 == result
.sak
then -- NXP MIFARE TNP3xxx 1K
117 print("I don't know how many sectors there are on this type of card, defaulting to 16")
120 The mifare Classic 1k card has 16 sectors of 4 data blocks each.
121 The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
122 8 sectors consist of 16 data blocks.
125 -- Defaults to 16 * 4 = 64 - 1 = 63
126 numBlocks
= numSectors
* 4 - 1
128 if numSectors
> 32 then
129 numBlocks
= 32*4+ (numSectors
-32)*16 -1
134 local function main(args
)
136 print( string.rep('--',20) )
137 print( string.rep('--',20) )
140 local OldKey
, NewKey
, Accessbytes
143 -- Arguments for the script
144 for o
, a
in getopt
.getopt(args
, 'hk:n:a:x') do
145 if o
== 'h' then return help() end
146 if o
== 'k' then OldKey
= a
end
147 if o
== 'n' then NewKey
= a
end
148 if o
== 'a' then Accessbytes
= a
end
149 if o
== 'x' then x
= true end
152 -- validate input args.
153 OldKey
= OldKey
or 'FFFFFFFFFFFF'
154 if #(OldKey
) ~= 12 then
155 return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey
))
158 NewKey
= NewKey
or 'FFFFFFFFFFFF'
159 if #(NewKey
) ~= 12 then
160 return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey
))
163 --Accessbytes = Accessbytes or '787788'
164 Accessbytes
= Accessbytes
or 'FF0780'
165 if #(Accessbytes
) ~= 6 then
166 return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes
))
172 print( string.format('Estimating number of blocks: %d', numBlocks
+ 1))
173 print( string.format('Old key: %s', OldKey
))
174 print( string.format('New key: %s', NewKey
))
175 print( string.format('New Access: %s', Accessbytes
))
176 print( string.rep('--', 20) )
178 -- Set new block data
179 local EMPTY_BL
= string.rep('00', 16)
180 local EMPTY_SECTORTRAIL
= string.format('%s%s%s%s', NewKey
, Accessbytes
, '00', NewKey
)
182 dbg( string.format('New sector-trailer : %s', EMPTY_SECTORTRAIL
))
183 dbg( string.format('New emptyblock: %s', EMPTY_BL
))
187 print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
190 local dialogResult
= utils
.confirm('Do you want to erase this card')
191 if dialogResult
== false then
192 return ExitMsg('Quiting it is then. Your wish is my command...')
195 print( string.rep('--', 20) )
198 for block
= 0, numBlocks
, 1 do
200 local reminder
= (block
+1) % 4
202 if reminder
== 0 then
203 cmd
= CmdString
:format(block
, OldKey
, EMPTY_SECTORTRAIL
)
205 cmd
= CmdString
:format(block
, OldKey
, EMPTY_BL
)
210 if x
then core
.console(cmd
) end
213 if core
.kbd_enter_pressed() then
214 print('aborted by user')