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