maur keys
[RRG-proxmark3.git] / client / luascripts / hf_mf_gen3_writer.lua
blobe3ec4351ddc1c2aab66770d0bd77f7e89eef2d96
1 local utils = require('utils')
2 local getopt = require('getopt')
3 local cmds = require('commands')
4 local read14a = require('read14a')
5 --
6 ---
7 -------------------------------
8 -- Notes
9 -------------------------------
10 ---
12 --[[
13 ---Suggestions of improvement:
14 --- Add support another types of dumps: BIN, JSON
15 --- Maybe it will be not only as `hf_mf_gen3_writer`, like a universal dump manager.
16 --- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40%
18 -- iceman notes:
19 -- doesn't take consideration filepaths for dump files.
20 -- doesn't allow A keys for authenticating when writing
21 -- doesn't verify that card is magic gen3.
22 -- doesn't take several versions of same dump ( -1, -2, -3 ) styles.
23 --]]
25 ---
26 -------------------------------
27 -- Script hat
28 -------------------------------
29 ---
31 copyright = 'RRG Team'
32 author = 'Winds'
33 version = 'v1.0.1'
34 desc = [[
35 This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards.
37 Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards.
38 The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards.
40 It supports the following functionality.
42 1. Write it to the same of current card UID.
43 2. Write it to magic Gen3 card.
44 3. Change uid to match dump on magic Gen3 card.
45 4. Permanent lock UID on magic Gen3 card.
46 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800.
48 Script works in a wizard styled way.
50 example = [[
51 1. script run mfc_gen3_writer
53 usage = [[
54 Give script to know if you uses an Windows OS
55 Select your *.eml dump from list to write to the card.
56 Follow the wizard.
59 ---
60 -------------------------------
61 -- Global variables
62 -------------------------------
63 ---
65 local DEBUG = false -- the debug flag
66 local dumpEML -- Find all *.EML files
67 local files = {} -- Array for eml files
68 local b_keys = {} -- Array for B keys
69 local eml = {} -- Array for data in block 32
70 local num_dumps = 0 -- num of found eml dump files
71 local tab = string.rep('-', 64)
72 local empty = string.rep('0', 32) -- Writing blocks
73 local default_key = 'FFFFFFFFFFFF' -- Writing blocks
74 local default_key_type = '01' --KeyA: 00, KeyB: 01
75 local default_key_blk = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- Writing blocks
76 local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100'
77 local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10'
78 local cmd_wrbl_a = 'hf mf wrbl --blk %d -a -k %s -d %s' -- Writing blocks by A key
79 local cmd_wrbl_b = 'hf mf wrbl --blk %d -b -k %s -d %s' -- Writing blocks by B key
81 ---
82 -------------------------------
83 -- A debug printout-function
84 -------------------------------
85 ---
87 local function dbg(args)
88 if not DEBUG then return end
89 if type(args) == 'table' then
90 local i = 1
91 while args[i] do
92 dbg(args[i])
93 i = i+1
94 end
95 else
96 print('###', args)
97 end
98 end
101 -------------------------------
102 -- This is only meant to be used when errors occur
103 -------------------------------
106 local function oops(err)
107 print('ERROR:', err)
108 core.clearCommandBuffer()
109 return nil, err
113 -------------------------------
114 -- Usage help
115 -------------------------------
118 local function help()
119 print(copyright)
120 print(author)
121 print(version)
122 print(desc)
123 print('Example usage')
124 print(example)
125 print(usage)
129 -------------------------------
130 -- GetUID
131 -------------------------------
134 local function GetUID()
135 return read14a.read(true, true).uid
138 local function dropfield()
139 read14a.disconnect()
140 core.clearCommandBuffer()
144 -------------------------------
145 -- Wait for tag (MFC)
146 -------------------------------
149 local function wait()
150 read14a.waitFor14443a()
154 -------------------------------
155 -- Return key code 00/01 to string
156 -------------------------------
159 local function KeyAB()
160 if default_key_type == '00' then
161 return 'KeyA'
162 else
163 return 'KeyB'
168 -------------------------------
169 -- Check response from Proxmark
170 -------------------------------
173 local function getblockdata(response)
174 if response.Status == 0 then
175 return true
176 else
177 return false
182 -------------------------------
183 -- Check 0xFFFFFFFFFFFF key for tag (MFC)
184 -------------------------------
187 local function checkkey()
188 local status = 0
189 for i = 1, #eml do
190 cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = ('%02x%02x%s'):format((i-1), default_key_type, default_key)}
191 if (getblockdata(cmd:sendNG(false)) == true) then
192 status = status + 1
193 print(('%s %02s %s %s %s'):format(' ', (i-1), KeyAB(), default_key, 'OK'))
194 else
195 break
198 if status == #eml then
199 return true
204 -------------------------------
205 -- Check user input A or B for blank tag (MFC)
206 -------------------------------
209 local function check_user_key(user_key_type)
210 if user_key_type == 'A' then
211 return cmd_wrbl_a
212 elseif user_key_type == 'B' then
213 return cmd_wrbl_b
218 -------------------------------
219 -- Main function
220 -------------------------------
223 local function main(args)
226 -------------------------------
227 -- Arguments for script
228 -------------------------------
231 for o, a in getopt.getopt(args, 'hd') do
232 if o == 'h' then return help() end
233 if o == 'd' then DEBUG = true end
236 wait()
237 print(tab)
240 -------------------------------
241 -- Detect 7/4 byte card
242 -------------------------------
245 if (utils.confirm(' Are you use a Windwos OS ?') == true) then
246 dumpEML = 'find "." "*dump.eml"'
247 if string.len(GetUID()) == 14 then
248 eml_file_uid_start = 18
249 eml_file_uid_end = 31
250 eml_file_lengt = 40
251 else
252 eml_file_uid_start = 18
253 eml_file_uid_end = 25
254 eml_file_lengt = 34
256 else
257 dumpEML = "find '.' -iname '*dump.eml' -type f"
258 if string.len(GetUID()) == 14 then
259 eml_file_uid_start = 9
260 eml_file_uid_end = 22
261 eml_file_lengt = 31
262 else
263 eml_file_uid_start = 9
264 eml_file_uid_end = 16
265 eml_file_lengt = 25
268 print(tab)
269 dropfield()
272 -------------------------------
273 -- List all EML files in /client
274 -------------------------------
277 local p = assert(io.popen(dumpEML))
278 for _ in p:lines() do
279 -- The length of eml file
280 if string.len(_) == eml_file_lengt then
281 num_dumps = num_dumps + 1
282 -- cut UID from eml file
283 files[num_dumps] = string.sub(_, eml_file_uid_start, eml_file_uid_end) -- cut numeretic UID
284 print(' '..num_dumps..' | '..files[num_dumps])
288 p.close()
290 if num_dumps == 0 then return oops("Didn't find any dump files") end
292 print(tab)
293 print(' Your card has UID '..GetUID())
294 print('')
295 print(' Select which dump to write (1 until '..num_dumps..')')
296 print(tab)
297 io.write(' --> ')
299 local uid_no = tonumber(io.read())
300 print(tab)
301 print(' You have been selected card dump No ' .. uid_no .. ', with UID: ' .. files[uid_no] .. '. Your card UID: ' .. GetUID())
305 -------------------------------
306 -- Load eml file
307 -------------------------------
310 local dumpfile = assert(io.open('hf-mf-' .. files[uid_no] .. '-dump.eml', 'r'))
311 for _ in dumpfile:lines() do table.insert(eml, _); end
312 dumpfile.close()
315 -------------------------------
316 -- Extract B key from EML file
317 -------------------------------
320 local b = 0
321 for i = 1, #eml do
322 if (i % 4 == 0) then
323 repeat
324 b = b + 1
325 -- Cut key from block
326 b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i])
327 until b % 4 == 0
330 print(tab)
331 dbg(b_keys)
332 dbg(eml)
335 -------------------------------
336 -- Change UID on certain version of magic Gen3 card.
337 -------------------------------
340 if (utils.confirm(' Change UID ?') == true) then
341 wait()
342 core.console(piswords_uid_change .. tostring(eml[1]))
343 print(tab)
344 print(' The new card UID : ' .. GetUID())
346 print(tab)
349 -------------------------------
350 -- Lock UID
351 -------------------------------
354 if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then
355 wait()
356 core.console(piswords_uid_lock)
359 print(tab)
360 print(' Going to check the all ' .. KeyAB() .. ' by ' .. default_key)
361 print(tab)
363 if checkkey() == true then
364 print(tab)
365 if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then
366 for i = 1, #eml do
367 core.console(string.format(cmd_wrbl_b, (i-1), default_key, eml[i]))
370 else
371 print(tab)
372 if (utils.confirm(' It this is a new blank card ? Do you wishing to change Access Conditions to using B key ' .. default_key .. ' as main ?') == true) then
373 print(tab)
374 print(' With one key type we will use, A or B ?')
375 print(tab)
376 io.write(' --> ')
377 local user_key_type = tostring(io.read())
378 print(tab)
379 print(' Enter 12 HEX chars of the key for access to card. By default ' .. default_key .. '.')
380 print(tab)
381 io.write(' --> ')
382 local user_key_input = tostring(io.read())
383 wait()
384 for i = 1, #eml do
385 if (i % 4 == 0) then
386 core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, default_key_blk))
387 else
388 core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, empty))
391 else
392 print(tab)
393 if (utils.confirm(' Write selected dump to card ?') == true) then
394 print(tab)
395 wait()
396 for i = 1, #eml do
397 core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], eml[i]))
399 else
400 print(tab)
401 if (utils.confirm(' Delete ALL data and write all keys to 0x' .. default_key .. ' ?') == true) then
402 wait()
403 for i = 1, #eml do
404 if (i % 4 == 0) then
405 core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], default_key_blk))
406 else
407 core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], empty))
414 dropfield()
415 print(tab)
416 print('You are welcome')
420 -------------------------------
421 -- Start Main function
422 -------------------------------
425 main(args)