text
[RRG-proxmark3.git] / client / luascripts / hf_mfu_magicwrite.lua
blob1fed9b93424f69004e66230212b57a3fdeaf6d86
1 local cmds = require('commands')
2 local getopt = require('getopt')
3 local lib14a = require('read14a')
4 local utils = require('utils')
5 local ansicolors = require('ansicolors')
7 -- global
8 local DEBUG = false -- the debug flag
9 local bxor = bit32.bxor
10 local _password = nil
11 local err_lock = 'use -k or change cfg0 block'
13 copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.'
14 author = 'Christian Herrmann'
15 version = 'v1.1.4'
16 desc = 'This script enables easy programming of a MAGIC NTAG 21* card'
17 example = [[
18 -- read magic tag configuration
19 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -c ]]..ansicolors.reset..[[
21 -- set uid
22 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -u 04112233445566 ]]..ansicolors.reset..[[
24 -- set pwd / pack
25 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -p 11223344 -a 8080 ]]..ansicolors.reset..[[
27 -- set version to NTAG213
28 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -v 0004040201000f03 ]]..ansicolors.reset..[[
30 -- set signature
31 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122 ]]..ansicolors.reset..[[
33 -- wipe tag
34 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -w ]]..ansicolors.reset..[[
36 -- wipe a locked down tag by giving the password
37 ]]..ansicolors.yellow..[[script run hf_mfu_magicwrite -k ffffffff -w ]]..ansicolors.reset..[[
40 usage = [[
41 script run hf_mfu_magicwrite -h -k <passwd> -c -w -u <uid> -t <type> -p <passwd> -a <pack> -s <signature> -o <otp> -v <version>
43 arguments = [[
44 -h this help
45 -c read magic configuration
46 -u UID (14 hexsymbols), set UID on tag
47 -t tag type to impersonate
48 1 = UL EV1 48b
49 2 = UL EV1 128b
50 3 = NTAG 210
51 4 = NTAG 212
52 5 = NTAG 213 (true)
53 6 = NTAG 215 (true)
54 7 = NTAG 216 (true)
55 8 = NTAG I2C 1K
56 9 = NTAG I2C 2K
57 10 = NTAG I2C 1K PLUS
58 11 = NTAG I2C 2K PLUS
59 12 = NTAG 213F (true)
60 13 = NTAG 216F (true)
61 -p password (8 hexsymbols), set password on tag.
62 -a pack ( 4 hexsymbols), set pack on tag.
63 -s signature data (64 hexsymbols), set signature data on tag.
64 -o OTP data (8 hexsymbols), set `One-Time Programmable` data on tag.
65 -v version data (16 hexsymbols), set version data on tag.
66 -w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5)
67 -k pwd to use with the wipe option
69 ---
70 -- A debug printout-function
71 local function dbg(args)
72 if not DEBUG then return end
73 if type(args) == 'table' then
74 local i = 1
75 while result[i] do
76 dbg(result[i])
77 i = i+1
78 end
79 else
80 print('###', args)
81 end
82 end
83 -- This is only meant to be used when errors occur
84 local function oops(err)
85 print("ERROR: ",err)
86 core.clearCommandBuffer()
87 return nil, err
88 end
89 ---
90 -- Usage help
91 local function help()
92 print(copyright)
93 print(author)
94 print(version)
95 print(desc)
96 print(ansicolors.cyan..'Usage'..ansicolors.reset)
97 print(usage)
98 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
99 print(arguments)
100 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
101 print(example)
104 -- set the global password variable
105 local function set_password(pwd)
106 if pwd == nil then _password = nil; return true, 'Ok' end
107 if #pwd ~= 8 then return nil, 'password wrong length. Must be 4 hex bytes' end
108 if #pwd == 0 then _password = nil end
109 _password = pwd
110 return true, 'Ok'
112 --- Picks out and displays the data read from a tag
113 -- Specifically, takes a usb packet, converts to a Command
114 -- (as in commands.lua), takes the data-array and
115 -- reads the number of bytes specified in arg1 (arg0 in c-struct)
116 -- @param usbpacket the data received from the device
117 local function getResponseData(usbpacket)
118 local resp = Command.parse(usbpacket)
119 local len = tonumber(resp.arg1) * 2
120 return string.sub(tostring(resp.data), 0, len);
124 local function sendRaw(rawdata, options)
126 local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
127 + lib14a.ISO14A_COMMAND.ISO14A_RAW
128 + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
130 local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
131 arg1 = flags,
132 -- arg2 contains the length, which is half the length of the ASCII-string rawdata
133 arg2 = string.len(rawdata)/2,
134 data = rawdata}
136 return c:sendMIX(options.ignore_response)
140 local function send(payload)
141 local usb, err = sendRaw(payload,{ignore_response = false})
142 if err then return oops(err) end
143 return getResponseData(usb)
146 -- select tag and if password is set, authenticate
147 local function connect()
148 core.clearCommandBuffer()
150 -- First of all, connect
151 info, err = lib14a.read(true, true)
152 if err then
153 lib14a.disconnect()
154 return oops(err)
156 core.clearCommandBuffer()
158 --authenticate if needed using global variable
159 if _password then
160 send('1B'.._password)
162 return true
165 -- Read magic configuration
166 local function read_config()
167 local info = connect()
168 if not info then return false, "Can't select card" end
170 -- read PWD
171 local pwd = send("30F0"):sub(1,8)
173 -- 04 response indicates that blocks has been locked down.
174 if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
176 -- read PACK
177 local pack = send("30F1"):sub(1,4)
179 -- read SIGNATURE
180 local signature1 = send('30F2'):sub(1,32)
181 local signature2 = send('30F6'):sub(1,32)
183 -- read VERSION
184 local version = send('30FA'):sub(1,16)
185 -- read config
186 local cardtype = send('30FC'):sub(1,2)
188 local typestr = ''
189 if cardtype == '00' then typestr = 'NTAG 213'
190 elseif cardtype == '01' then typestr = 'NTAG 215'
191 elseif cardtype == '02' then typestr = 'NTAG 216'
194 local versionstr = 'unknown'
195 if version == '0004030101000B03' then versionstr = 'UL EV1 48b'
196 elseif version == '0004030101000E03' then versionstr = 'UL EV1 128b'
197 elseif version == '0004040101000B03' then versionstr = 'NTAG 210'
198 elseif version == '0004040101000E03' then versionstr = 'NTAG 212'
199 elseif version == '0004040201000F03' then versionstr = 'NTAG 213'
200 elseif version == '0004040201001103' then versionstr = 'NTAG 215'
201 elseif version == '0004040201001303' then versionstr = 'NTAG 216'
202 elseif version == '0004040502011303' then versionstr = 'NTAG I2C 1K'
203 elseif version == '0004040502011503' then versionstr = 'NTAG I2C 2K'
204 elseif version == '0004040502021303' then versionstr = 'NTAG I2C 1K PLUS'
205 elseif version == '0004040502021503' then versionstr = 'NTAG I2C 2K PLUS'
206 elseif version == '0004040401000F03' then versionstr = 'NTAG 213F'
207 elseif version == '0004040401001303' then versionstr = 'NTAG 216F'
210 print('Magic NTAG 21* Configuration')
211 print(' - Type ', typestr, '(genuine cardtype)')
212 print(' - Password', pwd)
213 print(' - Pack ', pack)
214 print(' - Version ', version, '(' .. versionstr .. ')')
215 print(' - Signature', signature1..signature2)
217 lib14a.disconnect()
218 return true, 'Ok'
221 -- Write SIGNATURE data
222 local function write_signature(data)
224 -- uid string checks
225 if data == nil then return nil, 'empty data string' end
226 if #data == 0 then return nil, 'empty data string' end
227 if #data ~= 64 then return nil, 'data wrong length. Should be 32 hex bytes' end
229 local info = connect()
230 if not info then return false, "Can't select card" end
232 print('Writing new signature')
234 local b,c
235 local cmd = 'A2F%d%s'
236 local j = 2
237 for i = 1, #data, 8 do
238 b = data:sub(i,i+7)
239 c = cmd:format(j,b)
240 local resp = send(c)
241 if resp == '04' then lib14a.disconnect(); return nil, 'Failed to write signature' end
242 j = j + 1
244 lib14a.disconnect()
245 return true, 'Ok'
248 -- Write PWD
249 local function write_pwd(pwd)
250 -- PWD string checks
251 if pwd == nil then return nil, 'empty PWD string' end
252 if #pwd == 0 then return nil, 'empty PWD string' end
253 if #pwd ~= 8 then return nil, 'PWD wrong length. Should be 4 hex bytes' end
255 local info = connect()
256 if not info then return false, "Can't select card" end
258 print('Writing new PWD ', pwd)
260 local resp = send('A2F0'..pwd)
261 lib14a.disconnect()
262 if resp == '04' then
263 return nil, 'Failed to write password'
264 else
265 return true, 'Ok'
269 -- Write PACK
270 local function write_pack(pack)
271 -- PACK string checks
272 if pack == nil then return nil, 'empty PACK string' end
273 if #pack == 0 then return nil, 'empty PACK string' end
274 if #pack ~= 4 then return nil, 'PACK wrong length. Should be 4 hex bytes' end
276 local info = connect()
277 if not info then return false, "Can't select card" end
279 print('Writing new PACK', pack)
281 local resp = send('A2F1'..pack..'0000')
282 lib14a.disconnect()
283 if resp == '04' then
284 return nil, 'Failed to write pack'
285 else
286 return true, 'Ok'
290 -- Write OTP block
291 local function write_otp(block3)
293 -- OTP string checks
294 if block3 == nil then return nil, 'empty OTP string' end
295 if #block3 == 0 then return nil, 'empty OTP string' end
296 if #block3 ~= 8 then return nil, 'OTP wrong length. Should be 4 hex bytes' end
298 local info = connect()
299 if not info then return false, "Can't select card" end
301 print('Writing new OTP ', block3)
303 local resp = send('A203'..block3)
304 lib14a.disconnect()
305 if resp == '04' then
306 return nil, 'Failed to write OTP'
307 else
308 return true, 'Ok'
312 -- Writes a UID with bcc1, bcc2. Needs a magic tag.
313 local function write_uid(uid)
314 -- uid string checks
315 if uid == nil then return nil, 'empty uid string' end
316 if #uid == 0 then return nil, 'empty uid string' end
317 if #uid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end
319 local info = connect()
320 if not info then return false, "Can't select card" end
322 print('Writing new UID ', uid)
324 local uidbytes = utils.ConvertHexToBytes(uid)
325 local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88)
326 local bcc2 = bxor(bxor(bxor(uidbytes[4], uidbytes[5]), uidbytes[6]), uidbytes[7])
327 local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
328 local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
329 local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
330 local resp
332 resp = send('A200'..block0)
333 resp = send('A201'..block1)
334 resp = send('A202'..block2)
335 lib14a.disconnect()
337 if resp == '04' then
338 return nil, 'Failed to write new uid'
339 else
340 return true, 'Ok'
344 -- Write VERSION data,
345 -- make sure you have correct version data
346 local function write_version(data)
347 -- version string checks
348 if data == nil then return nil, 'empty version string' end
349 if #data == 0 then return nil, 'empty version string' end
350 if #data ~= 16 then return nil, 'version wrong length. Should be 8 hex bytes' end
352 local info = connect()
353 if not info then return false, "Can't select card" end
355 print('Writing new version', data)
357 local b1 = data:sub(1,8)
358 local b2 = data:sub(9,16)
359 local resp
360 resp = send('A2FA'..b1)
361 resp = send('A2FB'..b2)
362 lib14a.disconnect()
363 if resp == '04' then
364 return nil, 'Failed to write version'
365 else
366 return true, 'Ok'
370 -- write TYPE which card is based on.
371 -- 00 = 213, 01 = 215, 02 = 216
372 local function write_type(data)
373 -- type string checks
374 if data == nil then return nil, 'empty type string' end
375 if #data == 0 then return nil, 'empty type string' end
376 if #data ~= 2 then return nil, 'type wrong length. Should be 1 hex byte' end
378 local info = connect()
379 if not info then return false, "Can't select card" end
380 print('Writing new type', data)
382 local resp = send('A2FC'..data..'000000')
383 lib14a.disconnect()
384 if resp == '04' then
385 return nil, 'Failed to write type'
386 else
387 return true, 'Ok'
391 -- Set tag type. Predefinde version data together with magic type set.
392 -- Since cmd always gives 10 bytes len (data+crc) we can impersonate the following types
393 -- we only truly be three types NTAG 213,215 and 216
394 local function set_type(tagtype)
396 -- tagtype checks
397 if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end
398 if tagtype == nil then return nil, 'empty tagtype' end
400 if tagtype == 1 then
401 print('Setting: UL-EV1 48')
402 write_otp('00000000') -- Setting OTP to default 00 00 00 00
403 write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03
404 write_type('00') -- based on NTAG213..
406 -- Setting UL-Ev1 default config bl 16,17
407 connect()
408 send('a210000000FF')
409 send('a21100050000')
411 elseif tagtype == 2 then
412 print('Setting: UL-EV1 128')
413 write_otp('00000000') -- Setting OTP to default 00 00 00 00
414 write_version('0004030101000e03') -- UL-EV1 (128) 00 04 03 01 01 00 0e 03
415 write_type('01')
417 -- Setting UL-Ev1 default config bl 37,38
418 connect()
419 send('a225000000FF')
420 send('a22600050000')
421 elseif tagtype == 3 then
422 print('Setting: NTAG 210')
423 write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03
424 write_type('00')
426 -- Setting NTAG210 default CC block456
427 connect()
428 send('a203e1100600')
429 send('a2040300fe00')
430 send('a20500000000')
431 -- Setting cfg1/cfg2
432 send('a210000000FF')
433 send('a21100050000')
434 elseif tagtype == 4 then
435 print('Setting: NTAG 212')
436 write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03
437 write_type('00')
439 -- Setting NTAG212 default CC block456
440 connect()
441 send('a203e1101000')
442 send('a2040103900a')
443 send('a205340300fe')
444 -- Setting cfg1/cfg2
445 send('a225000000FF')
446 send('a22600050000')
447 elseif tagtype == 5 then
448 print('Setting: NTAG 213')
449 write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03
450 write_type('00')
452 -- Setting NTAG213 default CC block456
453 connect()
454 send('a203e1101200')
455 send('a2040103a00c')
456 send('a205340300fe')
457 -- setting cfg1/cfg2
458 send('a229000000ff')
459 send('a22a00050000')
460 elseif tagtype == 6 then
461 print('Setting: NTAG 215')
462 write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03
463 write_type('01')
465 -- Setting NTAG215 default CC block456
466 connect()
467 send('a203e1103e00')
468 send('a2040300fe00')
469 send('a20500000000')
470 -- setting cfg1/cfg2
471 send('a283000000ff')
472 send('a28400050000')
473 elseif tagtype == 7 then
474 print('Setting: NTAG 216')
475 write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03
476 write_type('02')
478 -- Setting NTAG216 default CC block456
479 connect()
480 send('a203e1106d00')
481 send('a2040300fe00')
482 send('a20500000000')
483 -- setting cfg1/cfg2
484 send('a2e3000000ff')
485 send('a2e400050000')
486 elseif tagtype == 8 then
487 print('Setting: NTAG I2C 1K')
488 write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03
489 write_type('02')
491 -- Setting NTAG I2C 1K default CC block456
492 connect()
493 send('a203e1106D00')
494 send('a2040300fe00')
495 send('a20500000000')
496 elseif tagtype == 9 then
497 print('Setting: NTAG I2C 2K')
498 write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03
499 write_type('02')
501 -- Setting NTAG I2C 2K default CC block456
502 connect()
503 send('a203e110EA00')
504 send('a2040300fe00')
505 send('a20500000000')
506 elseif tagtype == 10 then
507 print('Setting: NTAG I2C plus 1K')
508 write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03
509 write_type('02')
511 -- Setting NTAG I2C 1K default CC block456
512 connect()
513 send('a203e1106D00')
514 send('a2040300fe00')
515 send('a20500000000')
516 elseif tagtype == 11 then
517 print('Setting: NTAG I2C plus 2K')
518 write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03
519 write_type('02')
521 -- Setting NTAG I2C 2K default CC block456
522 connect()
523 send('a203e1106D00')
524 send('a2040300fe00')
525 send('a20500000000')
526 elseif tagtype == 12 then
527 print('Setting: NTAG 213F')
528 write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03
529 write_type('00')
531 -- Setting NTAG213 default CC block456
532 connect()
533 send('a203e1101200')
534 send('a2040103a00c')
535 send('a205340300fe')
536 -- setting cfg1/cfg2
537 send('a229000000ff')
538 send('a22a00050000')
539 elseif tagtype == 13 then
540 print('Setting: NTAG 216F')
541 write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03
542 write_type('02')
544 -- Setting NTAG216 default CC block456
545 connect()
546 send('a203e1106d00')
547 send('a2040300fe00')
548 send('a20500000000')
549 -- setting cfg1/cfg2
550 send('a2e3000000ff')
551 send('a2e400050000')
554 lib14a.disconnect()
555 if resp == '04' then
556 return nil, 'Failed to set type'
557 else
558 return true, 'Ok'
562 -- wipe tag
563 local function wipe()
565 local info = connect()
566 if not info then return false, "Can't select card" end
568 local err, msg, resp
569 local cmd_empty = 'A2%02X00000000'
570 local cmd_cfg1 = 'A2%02X000000FF'
571 local cmd_cfg2 = 'A2%02X00050000'
573 print('Wiping tag')
575 for b = 3, 0xFB do
576 --configuration block 0
577 if b == 0x29 or b == 0x83 or b == 0xe3 then
578 local cmd = (cmd_cfg1):format(b)
579 resp = send(cmd)
580 --configuration block 1
581 elseif b == 0x2a or b == 0x84 or b == 0xe4 then
582 local cmd = (cmd_cfg2):format(b)
583 resp = send(cmd)
584 else
585 resp = send(cmd_empty:format(b))
587 if resp == '04' or #resp == 0 then
588 io.write('\nwrote block '..b, ' failed\n')
589 err = true
590 else
591 io.write('.')
593 io.flush()
595 io.write('\r\n')
597 lib14a.disconnect()
599 if err then return nil, "Tag locked down, "..err_lock end
601 print('setting default values...')
603 set_password(nil)
605 -- set NTAG213 default values
606 err, msg = set_type(5)
607 if err == nil then return err, msg end
609 --set UID
610 err, msg = write_uid('04112233445566')
611 if err == nil then return err, msg end
613 --set pwd
614 err, msg = write_pwd('FFFFFFFF')
615 if err == nil then return err, msg end
617 --set pack
618 err, msg = write_pack('0000')
619 if err == nil then return err, msg end
621 return true, 'Ok'
624 -- The main entry point
625 function main(args)
627 print( string.rep('--',20) )
628 print( string.rep('--',20) )
629 print()
631 local err, msg
633 if #args == 0 then return help() end
635 -- Read the parameters
636 for o, a in getopt.getopt(args, 'hck:u:t:p:a:s:o:v:w') do
638 -- help
639 if o == "h" then return help() end
641 --key
642 if o == 'k' then err, msg = set_password(a) end
644 -- configuration
645 if o == "c" then err, msg = read_config() end
647 --wipe tag
648 if o == "w" then err, msg = wipe() end
650 -- write uid
651 if o == "u" then err, msg = write_uid(a) end
653 -- write type/version
654 if o == "t" then err, msg = set_type(a) end
656 -- write pwd
657 if o == "p" then err, msg = write_pwd(a) end
659 -- write pack
660 if o == "a" then err, msg = write_pack(a) end
662 -- write signature
663 if o == "s" then err, msg = write_signature(a) end
665 -- write otp
666 if o == "o" then err, msg = write_otp(a) end
668 -- write version
669 if o == "v" then err, msg = write_version(a) end
671 if err == nil then return oops(msg) end
676 main(args)