mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-18 03:00:58 +08:00
Merge pull request #1571 from startrk1995/ultimate_magic_card
Ultimate magic card (Gen4)
This commit is contained in:
commit
e83dfcc2cb
3 changed files with 1103 additions and 7 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added luascript `hf_mf_ultimatecard.lua` - Script for Ultimate Magic Card (GEN4) (@startrk1995)
|
||||
- Added new tool `brute_key` - MIFARE DESFire Telenot access AES recovery (@x41sec)
|
||||
- Fixed `hf mfu dump -k` - insert PWD in dump (@doegox)
|
||||
- Changed `hf mfu pwdgen` - now generate xiaomi air purifier pwd/pack (@doegox)
|
||||
|
|
|
@ -1008,7 +1008,71 @@ If the card is an Ultimate Magic Card, it returns 30 bytes.
|
|||
### Magic commands
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
Special commands summary:
|
||||
There are two ways to program this card.
|
||||
|
||||
1. Use the raw commands designated by the `hf 14a` examples.
|
||||
|
||||
***OR***
|
||||
|
||||
2. Use the hf_mf_ultimatecard.lua script commands designated but the `script run hf_mf_ulimatecard` examples.
|
||||
|
||||
|
||||
script run hf_mf_ultimatecard.lua -h
|
||||
```
|
||||
This script enables easy programming of an Ultimate Mifare Magic card
|
||||
Usage
|
||||
script run hf_mf_ultimatecard -h -k <passwd> -c -w <type> -u <uid> -t <type> -p <passwd> -a <pack> -s <signature> -o <otp> -v <version> -q <atqa/sak> -g <gtu> -z <ats> -m <ul-mode> -n <ul-protocol>
|
||||
|
||||
Arguments
|
||||
-h this help
|
||||
-c read magic configuration
|
||||
-u UID (8-14 hexsymbols), set UID on tag
|
||||
-t tag type to impersonate
|
||||
1 = Mifare Mini S20 4-byte 12 = NTAG 210
|
||||
2 = Mifare Mini S20 7-byte 13 = NTAG 212
|
||||
3 = Mifare 1k S50 4-byte 14 = NTAG 213
|
||||
4 = Mifare 1k S50 7-byte 15 = NTAG 215
|
||||
5 = Mifare 4k S70 4-byte 16 = NTAG 216
|
||||
6 = Mifare 4k S70 7-byte 17 = NTAG I2C 1K
|
||||
*** 7 = UL - NOT WORKING FULLY 18 = NTAG I2C 2K
|
||||
*** 8 = UL-C - NOT WORKING FULLY 19 = NTAG I2C 1K PLUS
|
||||
9 = UL EV1 48b 20 = NTAG I2C 2K PLUS
|
||||
10 = UL EV1 128b 21 = NTAG 213F
|
||||
*** 11 = UL Plus - NOT WORKING YET 22 = NTAG 216F
|
||||
|
||||
-p NTAG password (8 hexsymbols), set NTAG password on tag.
|
||||
-a NTAG pack ( 4 hexsymbols), set NTAG pack on tag.
|
||||
-s Signature data (64 hexsymbols), set signature data on tag.
|
||||
-o OTP data (8 hexsymbols), set `One-Time Programmable` data on tag.
|
||||
-v Version data (16 hexsymbols), set version data on tag.
|
||||
-q ATQA/SAK (<2b ATQA><1b SAK> hexsymbols), set ATQA/SAK on tag.
|
||||
-g GTU Mode (1 hexsymbol), set GTU shadow mode.
|
||||
-z ATS (<1b length><0-16 ATS> hexsymbols), Configure ATS. Length set to 00 will disable ATS.
|
||||
-w Wipe tag. 0 for Mifare or 1 for UL. Fills tag with zeros and put default values for type selected.
|
||||
-m Ultralight mode (00 UL EV1, 01 NTAG, 02 UL-C, 03 UL) Set type of UL.
|
||||
-n Ultralight protocol (00 MFC, 01 UL), switches between UL and MFC mode
|
||||
-k Ultimate Magic Card Key (IF DIFFERENT THAN DEFAULT 00000000)
|
||||
|
||||
Example usage
|
||||
-- read magic tag configuration
|
||||
script run hf_mf_ultimatecard -c
|
||||
-- set uid
|
||||
script run hf_mf_ultimatecard -u 04112233445566
|
||||
-- set NTAG pwd / pack
|
||||
script run hf_mf_ultimatecard -p 11223344 -a 8080
|
||||
-- set version to NTAG213
|
||||
script run hf_mf_ultimatecard -v 0004040201000f03
|
||||
-- set ATQA/SAK to [00 44] [08]
|
||||
script run hf_mf_ultimatecard -q 004408
|
||||
-- wipe tag with a NTAG213 or Mifare 1k S50 4 byte
|
||||
script run hf_mf_ultimatecard -w 1
|
||||
-- use a non default UMC key. Only use this if the default key for the MAGIC CARD was changed.
|
||||
script run hf_mf_ultimatecard -k ffffffff -w 1
|
||||
-- Wipe tag, turn into NTAG215, set sig, version, NTAG pwd/pak, and OTP.
|
||||
script run hf_mf_ultimatecard -w 1 -t 15 -u 04112233445566 -s 112233445566778899001122334455667788990011223344556677 -p FFFFFFFF -a 8080 -o 11111111
|
||||
```
|
||||
|
||||
Special raw commands summary:
|
||||
|
||||
```
|
||||
CF <passwd> 32 <00-03> // Configure GTU shadow mode
|
||||
|
@ -1063,6 +1127,7 @@ hf 14a raw -s -c -t 1000 CF00000000CE02
|
|||
hf 14a raw -s -c -t 1000 CF<passwd>35<2b ATQA><1b SAK>
|
||||
```
|
||||
* ⚠ ATQA bytes are swapped in the command
|
||||
* ⚠ ATQA bytes that result in `iso14443a card select failed` (I.E. ATQA=0040 in raw form) can be corrected with `hf 14a config --atqa force`
|
||||
* ⚠ when SAK bit 6 is set (e.g. SAK=20 or 28), ATS must be turned on, otherwise the card may not be recognized by some readers!
|
||||
* ⚠ never set SAK bit 3 (e.g. SAK=04), it indicates an extra cascade level is required (see `hf 14a config --cl2 skip` or `hf 14a config --cl3 skip` to recover a misconfigured card)
|
||||
|
||||
|
@ -1070,6 +1135,10 @@ Example: ATQA 0044 SAK 28, default pwd
|
|||
```
|
||||
hf 14a raw -s -c -t 1000 CF0000000035440028
|
||||
```
|
||||
OR (Note the script will correct the ATQA correctly)
|
||||
```
|
||||
script run hf_mf_ultimatecard -q 004428
|
||||
```
|
||||
### Change ATS
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1086,6 +1155,12 @@ Example: ATS to 0606757781028002F0, default pwd
|
|||
hf 14a raw -s -c -t 1000 CF000000003406067577810280
|
||||
```
|
||||
|
||||
Or
|
||||
|
||||
```
|
||||
script run hf_mf_ultimatecard -z 06067577810280`
|
||||
```
|
||||
|
||||
### Set UID length (4, 7, 10)
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1104,29 +1179,43 @@ hf 14a raw -s -c -t 1000 CF000000006801
|
|||
### Set 14443A UID
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
UID is configured according to block0 with a backdoor write.
|
||||
UID is configured according to block0 with a backdoor write. (Script commands are below the UID length examples)
|
||||
|
||||
Example: preparing first two blocks:
|
||||
Example: preparing first two blocks: (Note the UMC has to be in MFC mode and the correct UID byte length set)
|
||||
```
|
||||
hf 14a raw -s -c -t 1000 CF00000000CD00000102030405060708090A0B0C0D0E0F
|
||||
hf 14a raw -s -c -t 1000 CF00000000CD01101112131415161718191A1B1C1D1E1F
|
||||
hf 14a reader
|
||||
```
|
||||
MFC mode, 4b UID
|
||||
MFC mode 4b UID
|
||||
|
||||
=> UID `00010203`
|
||||
|
||||
MFC mode, 7b UID
|
||||
`script run hf_mf_ultimatecard -t 3 -u 00010203`
|
||||
|
||||
MFC mode 7b UID
|
||||
|
||||
=> UID `00010203040506`
|
||||
|
||||
MFC mode, 10b UID
|
||||
`script run hf_mf_ultimatecard -t 3 -u 00010203040506`
|
||||
|
||||
MFC mode, 10b UID
|
||||
|
||||
=> UID `00010203040506070809`
|
||||
|
||||
Ultralight mode, 4b UID
|
||||
Ultralight mode, 4b UID
|
||||
|
||||
=> UID `00010203`
|
||||
|
||||
Ultralight mode, 7b UID
|
||||
|
||||
=> UID `00010210111213`
|
||||
|
||||
👉 the UID is composed of first two blocks as in regular Ultralights
|
||||
* Examples
|
||||
* UL-EV1 48b = `script run hf_mf_ultimatecard -t 9 -u 00010203040506`
|
||||
* UL EV1 128b = `script run hf_mf_ultimatecard -t 10 -u 00010203040506`
|
||||
* NTAG 215 = `script run hf_mf_ultimatecard -t 15 -u 00010203040506`
|
||||
|
||||
Ultralight mode, 10b UID
|
||||
=> UID `00010203040506070809`
|
||||
|
@ -1158,10 +1247,17 @@ hf 14a raw -s -c -t 1000 CF<passwd>69<1b param>
|
|||
* `01`: MIFARE Ultralight/NTAG mode
|
||||
|
||||
Example: activate Ultralight protocol, default pwd
|
||||
|
||||
```
|
||||
hf 14a raw -s -c -t 1000 CF000000006901
|
||||
```
|
||||
|
||||
Or
|
||||
|
||||
```
|
||||
script run hf_mf_ultimatecard -n 01
|
||||
```
|
||||
|
||||
In this mode, if SAK=`00` and ATQA=`0044`, it acts as an Ultralight card
|
||||
|
||||
⚠ only the first four bytes of each block will be mapped in the Ultralight memory map (so the Ultralight block numbers follow backdoor R/W block numbers).
|
||||
|
@ -1182,9 +1278,16 @@ hf 14a raw -s -c -t 1000 CF<passwd>6A<1b param>
|
|||
⚠ it supposes Ultralight mode was activated (cf command `69`)
|
||||
|
||||
Example: set Ultralight mode to Ultralight-C, default pwd
|
||||
|
||||
```
|
||||
hf 14a raw -s -c -t 1000 CF000000006A02
|
||||
```
|
||||
Or
|
||||
|
||||
```
|
||||
script run hf_mf_ultimatecard -m 02
|
||||
```
|
||||
|
||||
Now the card supports the 3DES UL-C authentication.
|
||||
### Set shadow mode (GTU)
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
@ -1193,6 +1296,24 @@ This mode is divided into four states: off (pre-write), on (on restore), don’t
|
|||
If you use it, please enter the pre-write mode first. At this time, write the full card data.
|
||||
After writing, set it to on. At this time, after writing the data, the first time you read the data just written, the next time you read It is the pre-written data. All modes support this operation. It should be noted that using any block to read and write in this mode may give wrong results.
|
||||
|
||||
Example:
|
||||
`script run hf_mf_ultimatecard -w 1 -g 00 -t 15 -u 04112233445566 -s 112233445566778899001122334455667788990011223344556677 -p FFFFFFFF -a 8080 -o 11111111 -g 01`
|
||||
* -w 1 = wipe the card in Ultralight Mode
|
||||
* -g 00 = turn on pre-write mode
|
||||
* -t 15 = change the type of card to NTAG 215
|
||||
* -u = set the uid
|
||||
* -s = set the signature
|
||||
* -p = set the NTAG password
|
||||
* -a = set the PACK
|
||||
* -o = set the OTP
|
||||
* -g 01 = turn on restore mode
|
||||
|
||||
At this point the card is set to a unwritten NTAG 215. Now any data written to the card will only last for 1 read. Write a popular game toy to it, read it, now it is back to the unwritten NTAG 215.
|
||||
|
||||
👉 Remember to disable GTU mode to get the card back to a normal state.
|
||||
|
||||
`script run hf_mf_ultimatecard -g 03`
|
||||
|
||||
```
|
||||
hf 14a raw -s -c -t 1000 CF<passwd>32<1b param>
|
||||
```
|
||||
|
|
974
hf_mf_ultimatecard.lua
Normal file
974
hf_mf_ultimatecard.lua
Normal file
|
@ -0,0 +1,974 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local lib14a = require('read14a')
|
||||
local utils = require('utils')
|
||||
local ansicolors = require('ansicolors')
|
||||
|
||||
-- global
|
||||
local DEBUG = false -- the debug flag
|
||||
local bxor = bit32.bxor
|
||||
local _ntagpassword = nil
|
||||
local _key = '00000000' -- default UMC key
|
||||
local err_lock = 'use -k or change cfg0 block'
|
||||
local _print = 0
|
||||
copyright = ''
|
||||
author = 'Nathan Glaser'
|
||||
version = 'v1.0.4'
|
||||
date = 'Created - Jan 2022'
|
||||
desc = 'This script enables easy programming of an Ultimate Mifare Magic card'
|
||||
example = [[
|
||||
-- read magic tag configuration
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -c ]]..ansicolors.reset..[[
|
||||
|
||||
-- set uid
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -u 04112233445566 ]]..ansicolors.reset..[[
|
||||
|
||||
-- set NTAG pwd / pack
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -p 11223344 -a 8080 ]]..ansicolors.reset..[[
|
||||
|
||||
-- set version to NTAG213
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -v 0004040201000f03 ]]..ansicolors.reset..[[
|
||||
|
||||
-- set ATQA/SAK to [00 44] [08]
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -q 004408 ]]..ansicolors.reset..[[
|
||||
|
||||
-- wipe tag with a NTAG213 or Mifare 1k S50 4 byte
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -w 1]]..ansicolors.reset..[[
|
||||
|
||||
-- use a non default UMC key. Only use this if the default key for the MAGIC CARD was changed.
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -k ffffffff -w 1]]..ansicolors.reset..[[
|
||||
|
||||
-- Wipe tag, turn into NTAG215, set sig, version, NTAG pwd/pak, and OTP.
|
||||
]]..ansicolors.yellow..[[script run hf_mf_ultimatecard -w 1 -t 15 -u 04112233445566 -s 112233445566778899001122334455667788990011223344556677 -p FFFFFFFF -a 8080 -o 11111111]]..ansicolors.reset..[[
|
||||
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mf_ultimatecard -h -k <passwd> -c -w <type> -u <uid> -t <type> -p <passwd> -a <pack> -s <signature> -o <otp> -v <version> -q <atqa/sak> -g <gtu> -z <ats> -m <ul-mode> -n <ul-protocol>
|
||||
]]
|
||||
arguments = [[
|
||||
-h this help
|
||||
-c read magic configuration
|
||||
-u UID (8-14 hexsymbols), set UID on tag
|
||||
-t tag type to impersonate
|
||||
1 = Mifare Mini S20 4-byte 12 = NTAG 210
|
||||
2 = Mifare Mini S20 7-byte 13 = NTAG 212
|
||||
3 = Mifare 1k S50 4-byte 14 = NTAG 213
|
||||
4 = Mifare 1k S50 7-byte 15 = NTAG 215
|
||||
5 = Mifare 4k S70 4-byte 16 = NTAG 216
|
||||
6 = Mifare 4k S70 7-byte 17 = NTAG I2C 1K
|
||||
*** 7 = UL - NOT WORKING FULLY 18 = NTAG I2C 2K
|
||||
*** 8 = UL-C - NOT WORKING FULLY 19 = NTAG I2C 1K PLUS
|
||||
9 = UL EV1 48b 20 = NTAG I2C 2K PLUS
|
||||
10 = UL EV1 128b 21 = NTAG 213F
|
||||
*** 11 = UL Plus - NOT WORKING YET 22 = NTAG 216F
|
||||
|
||||
-p NTAG password (8 hexsymbols), set NTAG password on tag.
|
||||
-a NTAG pack ( 4 hexsymbols), set NTAG pack on tag.
|
||||
-s Signature data (64 hexsymbols), set signature data on tag.
|
||||
-o OTP data (8 hexsymbols), set `One-Time Programmable` data on tag.
|
||||
-v Version data (16 hexsymbols), set version data on tag.
|
||||
-q ATQA/SAK (<2b ATQA><1b SAK> hexsymbols), set ATQA/SAK on tag.
|
||||
-g GTU Mode (1 hexsymbol), set GTU shadow mode.
|
||||
-z ATS (<1b length><0-16 ATS> hexsymbols), Configure ATS. Length set to 00 will disable ATS.
|
||||
-w Wipe tag. 0 for Mifare or 1 for UL. Fills tag with zeros and put default values for type selected.
|
||||
-m Ultralight mode (00 UL EV1, 01 NTAG, 02 UL-C, 03 UL) Set type of UL.
|
||||
-n Ultralight protocol (00 MFC, 01 UL), switches between UL and MFC mode
|
||||
-k Ultimate Magic Card Key (IF DIFFERENT THAN DEFAULT 00000000)
|
||||
]]
|
||||
---
|
||||
-- A debug printout-function
|
||||
local function dbg(args)
|
||||
if not DEBUG then return end
|
||||
if type(args) == 'table' then
|
||||
local i = 1
|
||||
while result[i] do
|
||||
dbg(result[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print('###', args)
|
||||
end
|
||||
end
|
||||
-- This is only meant to be used when errors occur
|
||||
local function oops(err)
|
||||
print("ERROR: ",err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, err
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(date)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
---
|
||||
-- set the global password variable
|
||||
local function set_ntagpassword(pwd)
|
||||
if pwd == nil then _ntagpassword = nil; return true, 'Ok' end
|
||||
if #pwd ~= 8 then return nil, 'password wrong length. Must be 4 hex bytes' end
|
||||
if #pwd == 0 then _ntagpassword = nil end
|
||||
_ntagpassword = pwd
|
||||
return true, 'Ok'
|
||||
end
|
||||
-- set the global UMC key variable
|
||||
local function set_key(key)
|
||||
print('Key:'..key)
|
||||
if key == nil then _key = '00000000'; return true, 'Ok' end
|
||||
if #key ~= 8 then return nil, 'UMC key is wrong the length. Must be 4 hex bytes' end
|
||||
if #key == 0 then _key = nil end
|
||||
_key = key
|
||||
return true, 'Ok'
|
||||
end
|
||||
--- Picks out and displays the data read from a tag
|
||||
-- Specifically, takes a usb packet, converts to a Command
|
||||
-- (as in commands.lua), takes the data-array and
|
||||
-- reads the number of bytes specified in arg1 (arg0 in c-struct)
|
||||
-- @param usbpacket the data received from the device
|
||||
local function getResponseData(usbpacket)
|
||||
local resp = Command.parse(usbpacket)
|
||||
local len = tonumber(resp.arg1) * 2
|
||||
return string.sub(tostring(resp.data), 0, len);
|
||||
end
|
||||
---
|
||||
local function sendRaw(rawdata, options)
|
||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||
+ lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||
+ lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||
local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
||||
arg1 = flags,
|
||||
arg2 = string.len(rawdata)/2,
|
||||
data = rawdata}
|
||||
return c:sendMIX(options.ignore_response)
|
||||
end
|
||||
---
|
||||
local function send(payload)
|
||||
local usb, err = sendRaw(payload,{ignore_response = false})
|
||||
if err then return oops(err) end
|
||||
return getResponseData(usb)
|
||||
end
|
||||
---
|
||||
local function connect()
|
||||
core.clearCommandBuffer()
|
||||
-- First of all, connect
|
||||
info, err = lib14a.read(true, true)
|
||||
if err then
|
||||
lib14a.disconnect()
|
||||
return oops(err)
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
--authenticate if needed using global variable
|
||||
if _ntagpassword then
|
||||
send('1B'.._ntagpassword)
|
||||
end
|
||||
return true
|
||||
end
|
||||
---
|
||||
-- Read magic configuration
|
||||
local function read_config()
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
-- read Ultimate Magic Card CONFIG
|
||||
if magicconfig == nil then
|
||||
magicconfig = send("CF".._key.."C6")
|
||||
else print('No Config')
|
||||
end
|
||||
-- extract data from CONFIG - based on CONFIG in https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md#gen-4-gtu
|
||||
ulprotocol, uidlength, readpass, gtumode, ats, atqa1, atqa2, sak, ulmode = magicconfig:sub(1,2), magicconfig:sub(3,4), magicconfig:sub(5,12), magicconfig:sub(13,14), magicconfig:sub(15,48), magicconfig:sub(51,52), magicconfig:sub(49,50), magicconfig:sub(53,54), magicconfig:sub(55,56)
|
||||
atqaf = atqa1..' '..atqa2
|
||||
cardtype, cardprotocol, gtustr, atsstr = 'unknown', 'unknown', 'unknown', 'unknown'
|
||||
if magicconfig == nil then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
if #magicconfig ~= 64 then lib14a.disconnect(); return nil, "partial read of configuration, "..err_lock end
|
||||
if gtumode == '00' then gtustr = 'Pre-write/Shadow Mode'
|
||||
elseif gtumode == '01' then gtustr = 'Restore Mode'
|
||||
elseif gtumode == '02' then gtustr = 'Disabled'
|
||||
elseif gtumode == '03' then gtustr = 'Disabled, high speed R/W mode for Ultralight'
|
||||
end
|
||||
if ats:sub(1,2) == '00' then atsstr = 'Disabled'
|
||||
else atsstr = (string.sub(ats, 3))
|
||||
end
|
||||
if ulprotocol == '00' then
|
||||
cardprotocol = 'MIFARE Classic Protocol'
|
||||
ultype = 'Disabled'
|
||||
if uidlength == '00' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,8)
|
||||
if atqaf == '00 04' and sak == '09' then cardtype = 'MIFARE Mini S20 4-byte UID'
|
||||
elseif atqaf == '00 04' and sak == '08' then cardtype = 'MIFARE 1k S50 4-byte UID'
|
||||
elseif atqaf == '00 02' and sak == '18' then cardtype = 'MIFARE 4k S70 4-byte UID'
|
||||
end
|
||||
elseif uidlength == '01' then
|
||||
uid = send("CF".._key.."CE00"):sub(1,14)
|
||||
if atqaf == '00 44' and sak == '09' then cardtype = 'MIFARE Mini S20 7-byte UID'
|
||||
elseif atqaf == '00 44' and sak == '08' then cardtype = 'MIFARE 1k S50 7-byte UID'
|
||||
elseif atqaf == '00 42' and sak == '18' then cardtype = 'MIFARE 4k S70 7-byte UID'
|
||||
end
|
||||
end
|
||||
elseif ulprotocol == '01' then
|
||||
-- Read Ultralight config only if UL protocol is enabled
|
||||
cardprotocol = 'MIFARE Ultralight/NTAG'
|
||||
block0 = send("3000")
|
||||
uid0 = block0:sub(1,6)
|
||||
uid = uid0..block0:sub(9,16)
|
||||
if ulmode == '00' then ultype = 'Ultralight EV1'
|
||||
elseif ulmode == '01' then ultype = 'NTAG21x'
|
||||
elseif ulmode == '02' then ultype = 'Ultralight-C'
|
||||
elseif ulmode == '03' then ultype = 'Ultralight'
|
||||
end
|
||||
-- read VERSION
|
||||
cversion = send('30FA'):sub(1,16)
|
||||
-- pwdblock must be set since the 30F1 and 30F2 special commands don't work on the ntag21x part of the UMC
|
||||
if ulmode == '03' then versionstr = 'Ultralight'
|
||||
elseif ulmode == '02' then versionstr = 'Ultralight-C'
|
||||
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
|
||||
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
|
||||
elseif cversion == '0004030101000E03' then versionstr = 'UL EV1 128b'
|
||||
elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210'
|
||||
elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212'
|
||||
elseif cversion == '0004040201000F03' then versionstr = 'NTAG 213'
|
||||
elseif cversion == '0004040201001103' then versionstr = 'NTAG 215'
|
||||
elseif cversion == '0004040201001303' then versionstr = 'NTAG 216'
|
||||
elseif cversion == '0004040502011303' then versionstr = 'NTAG I2C 1K'
|
||||
elseif cversion == '0004040502011503' then versionstr = 'NTAG I2C 2K'
|
||||
elseif cversion == '0004040502021303' then versionstr = 'NTAG I2C 1K PLUS'
|
||||
elseif cversion == '0004040502021503' then versionstr = 'NTAG I2C 2K PLUS'
|
||||
elseif cversion == '0004040401000F03' then versionstr = 'NTAG 213F'
|
||||
elseif cversion == '0004040401001303' then versionstr = 'NTAG 216F'
|
||||
end
|
||||
-- read PWD
|
||||
cpwd = send("30F0"):sub(1,8)
|
||||
pwd = send("30E5"):sub(1,8)
|
||||
-- 04 response indicates that blocks has been locked down.
|
||||
if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
-- read PACK
|
||||
cpack = send("30F1"):sub(1,4)
|
||||
pack = send("30E6"):sub(1,4)
|
||||
-- read SIGNATURE
|
||||
signature1 = send('30F2'):sub(1,32)
|
||||
signature2 = send('30F6'):sub(1,32)
|
||||
lib14a.disconnect()
|
||||
end
|
||||
if _print < 1 then
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tUltimate Magic Card Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - Raw Config ', string.sub(magicconfig, 1, -9))
|
||||
print(' - Card Protocol ', cardprotocol)
|
||||
print(' - Ultralight Mode ', ultype)
|
||||
print(' - ULM Backdoor Key ', readpass)
|
||||
print(' - GTU Mode ', gtustr)
|
||||
if ulprotocol == '01' then
|
||||
print(' - Card Type ', versionstr)
|
||||
else
|
||||
print(' - Card Type ', cardtype)
|
||||
end
|
||||
print(' - UID ', uid)
|
||||
print(' - ATQA ', atqaf)
|
||||
print(' - SAK ', sak)
|
||||
if ulprotocol == '01' then
|
||||
print('')
|
||||
print(string.rep('=', 88))
|
||||
print('\t\t\tMagic UL/NTAG 21* Configuration')
|
||||
print(string.rep('=', 88))
|
||||
print(' - ATS ', atsstr)
|
||||
print(' - Password ', '[0xE5] '..pwd, '[0xF0] '..cpwd)
|
||||
print(' - Pack ', '[0xE6] '..pack, '[0xF1] '..cpack)
|
||||
print(' - Version ', cversion)
|
||||
print(' - Signature ', signature1..signature2)
|
||||
end
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
--
|
||||
-- Writes a UID for MFC and MFUL/NTAG cards
|
||||
local function write_uid(useruid)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
-- Writes a MFC UID with GEN4 magic commands.
|
||||
if ulprotocol == '00' then
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if (#useruid ~= 8) and (#useruid ~= 14) then return nil, 'UID wrong length. Should be 4 or 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), uidbytes[4])
|
||||
local block0 = string.format('%02X%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], uidbytes[4], bcc1)
|
||||
local resp = send('CF'.._key..'CD00'..block0)
|
||||
-- Writes a MFUL UID with bcc1, bcc2 using NTAG21xx commands.
|
||||
elseif ulprotocol == '01' then
|
||||
-- uid string checks
|
||||
if useruid == nil then return nil, 'empty uid string' end
|
||||
if #useruid == 0 then return nil, 'empty uid string' end
|
||||
if #useruid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end
|
||||
print('Writing new UID ', useruid)
|
||||
local uidbytes = utils.ConvertHexToBytes(useruid)
|
||||
local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88)
|
||||
local bcc2 = bxor(bxor(bxor(uidbytes[4], uidbytes[5]), uidbytes[6]), uidbytes[7])
|
||||
local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1)
|
||||
local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7])
|
||||
local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00)
|
||||
local resp
|
||||
resp = send('A200'..block0)
|
||||
resp = send('A201'..block1)
|
||||
resp = send('A202'..block2)
|
||||
else
|
||||
print('Incorrect ul')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
if resp ~= nil then
|
||||
return nil, oops('Failed to write UID')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
---
|
||||
-- Write ATQA/SAK
|
||||
local function write_atqasak(atqasak)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if atqasak == nil then return nil, 'Empty ATQA/SAK string' end
|
||||
if #atqasak == 0 then return nil, 'Empty ATQA/SAK string' end
|
||||
if #atqasak ~= 6 then return nil, 'ATQA/SAK wrong length. Should be 6 hex bytes. I.E. 004408 ATQA(0044) SAK(08)' end
|
||||
local atqauser1 = atqasak:sub(1,2)
|
||||
local atqauser2 = atqasak:sub(3,4)
|
||||
local atqauserf = atqauser2..atqauser1
|
||||
local sakuser = atqasak:sub(5,6)
|
||||
if sakuser == '04' then
|
||||
print('Never set SAK bit 3 (e.g. SAK=04), it indicates an extra cascade level is required')
|
||||
return nil
|
||||
elseif (sakuser == '20' or sakuser == '28') and atslen == '00' then
|
||||
print('When SAK equals 20 or 28, ATS must be turned on')
|
||||
return nil
|
||||
elseif atqauser2 == '40' then
|
||||
print('ATQA of [00 40] will cause the card to not answer.')
|
||||
return nil
|
||||
else
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('New ATQA: '..atqauser1..' '..atqauser2..' New SAK: '..sakuser)
|
||||
local resp = send("CF".._key.."35"..atqauserf..sakuser)
|
||||
lib14a.disconnect()
|
||||
if resp == nil then
|
||||
return nil, oops('Failed to write ATQA/SAK')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
end
|
||||
---
|
||||
-- Write NTAG PWD
|
||||
local function write_ntagpwd(ntagpwd)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
-- PWD string checks
|
||||
if ntagpwd == nil then return nil, 'empty NTAG PWD string' end
|
||||
if #ntagpwd == 0 then return nil, 'empty NTAG PWD string' end
|
||||
if #ntagpwd ~= 8 then return nil, 'NTAG PWD wrong length. Should be 4 hex bytes' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing new NTAG PWD ', ntagpwd)
|
||||
local resp = send('A2E5'..ntagpwd) -- must add both for password to be read by the reader command B1
|
||||
local resp = send('A2F0'..ntagpwd)
|
||||
lib14a.disconnect()
|
||||
if resp == nil then
|
||||
return nil, 'Failed to write password'
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
---
|
||||
-- Write PACK
|
||||
local function write_pack(userpack)
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == 0 then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
-- PACK string checks
|
||||
if userpack == nil then return nil, 'empty PACK string' end
|
||||
if #userpack == 0 then return nil, 'empty PACK string' end
|
||||
if #userpack ~= 4 then return nil, 'PACK wrong length. Should be 4 hex bytes' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing new PACK', userpack)
|
||||
send('A2E6'..userpack..'0000')
|
||||
send('A2F1'..userpack..'0000')
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Write OTP block
|
||||
local function write_otp(block3)
|
||||
-- OTP string checks
|
||||
if block3 == nil then return nil, 'empty OTP string' end
|
||||
if #block3 == 0 then return nil, 'empty OTP string' end
|
||||
if #block3 ~= 8 then return nil, 'OTP wrong length. Should be 4 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing new OTP ', block3)
|
||||
local resp = send('A203'..block3)
|
||||
lib14a.disconnect()
|
||||
if resp ~= '0A' then return false, oops('Failed to write OTP')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
---
|
||||
-- Write VERSION data,
|
||||
-- make sure you have correct version data
|
||||
local function write_version(data)
|
||||
-- Version string checks
|
||||
if data == nil then return nil, 'empty version string' end
|
||||
if #data == 0 then return nil, 'empty version string' end
|
||||
if #data ~= 16 then return nil, 'version wrong length. Should be 8 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
print('Writing new version', data)
|
||||
local b1 = data:sub(1,8)
|
||||
local b2 = data:sub(9,16)
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
local resp
|
||||
resp = send('A2FA'..b1)
|
||||
resp = send('A2FB'..b2)
|
||||
lib14a.disconnect()
|
||||
if resp ~= '0A' then return nil, oops('Failed to write version')
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
|
||||
end
|
||||
---
|
||||
-- Write SIGNATURE data
|
||||
local function write_signature(data)
|
||||
-- Signature string checks
|
||||
if data == nil then return nil, 'empty data string' end
|
||||
if #data == 0 then return nil, 'empty data string' end
|
||||
if #data ~= 64 then return nil, 'data wrong length. Should be 32 hex bytes' end
|
||||
-- read CONFIG
|
||||
if not magicconfig then
|
||||
_print = 1
|
||||
read_config()
|
||||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
print('Writing new signature',data)
|
||||
local b,c
|
||||
local cmd = 'A2F%d%s'
|
||||
local j = 2
|
||||
for i = 1, #data, 8 do
|
||||
b = data:sub(i,i+7)
|
||||
c = cmd:format(j,b)
|
||||
local resp = send(c)
|
||||
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
|
||||
j = j + 1
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Enable/Disable GTU Mode
|
||||
-- 00: pre-write, 01: restore mode, 02: disabled, 03: disabled, high speed R/W mode for Ultralight
|
||||
local function write_gtu(gtu)
|
||||
if gtu == nil then return nil, 'empty GTU string' end
|
||||
if #gtu == 0 then return nil, 'empty GTU string' end
|
||||
if #gtu ~= 2 then return nil, 'type wrong length. Should be 1 hex byte' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if gtu == '00' then
|
||||
print('Enabling GTU Pre-Write')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '01' then
|
||||
print('Enabling GTU Restore Mode')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '02' then
|
||||
print('Disabled GTU')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '03' then
|
||||
print('Disabled GTU, high speed R/W mode for Ultralight')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
else
|
||||
print('Failed to set GTU mode')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Write ATS
|
||||
-- First hexbyte is length. 00 to disable ATS. 16 hexbytes for ATS
|
||||
local function write_ats(atsuser)
|
||||
if atsuser == nil then return nil, 'empty ATS string' end
|
||||
if #atsuser == 0 then return nil, 'empty ATS string' end
|
||||
if #atsuser > 34 then return nil, 'type wrong length. Should be <1b length><0-16b ATS> hex byte' end
|
||||
local atscardlen = atsuser:sub(1,2)
|
||||
local atscardlendecimal = tonumber(atscardlen, 16)
|
||||
local atsf = string.sub(atsuser, 3)
|
||||
if (#atsf / 2) ~= atscardlendecimal then
|
||||
oops('Given length of ATS ('..atscardlendecimal..') does not match the ATS_length ('..(#atsf / 2)..')')
|
||||
return true, 'Ok'
|
||||
else
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
print('Writing '..atscardlendecimal..' ATS bytes of '..atsf)
|
||||
send("CF".._key.."34"..atsuser)
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Change UL/MFC protocol
|
||||
local function write_ulp(ulp)
|
||||
if ulp == nil then return nil, 'empty ULP string' end
|
||||
if #ulp == 0 then return nil, 'empty ULP string' end
|
||||
if #ulp > 2 then return nil, 'type wrong length. Should be 1 hex byte' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulp == '00' then
|
||||
print('Changing card to Mifare Classic Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
elseif ulp == '01' then
|
||||
print('Changing card to Ultralight Protocol')
|
||||
send("CF".._key.."69"..ulp)
|
||||
else
|
||||
oops('Protocol needs to be either 00 or 01')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Change UL Mode Type
|
||||
local function write_ulm(ulm)
|
||||
if ulm == nil then return nil, 'empty ULM string' end
|
||||
if #ulm == 0 then return nil, 'empty ULM string' end
|
||||
if #ulm > 2 then return nil, 'type wrong length. Should be 1 hex byte' end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulm == '00' then
|
||||
print('Changing card UL mode to Ultralight EV1')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '01' then
|
||||
print('Changing card UL mode to NTAG')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '02' then
|
||||
print('Changing card UL mode to Ultralight-C')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
elseif ulm == '03' then
|
||||
print('Changing card UL mode to Ultralight')
|
||||
send("CF".._key.."6A"..ulm)
|
||||
else
|
||||
oops('UL mode needs to be either 00, 01, 02, 03')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
end
|
||||
---
|
||||
-- Set type for magic card presets.
|
||||
local function set_type(tagtype)
|
||||
-- tagtype checks
|
||||
if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end
|
||||
if tagtype == nil then return nil, oops('empty tagtype') end
|
||||
-- Setting Mifare mini S20 4-byte
|
||||
if tagtype == 1 then
|
||||
print('Setting: Ultimate Magic card to Mifare mini S20 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000900")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare mini S20 7-byte
|
||||
elseif tagtype == 2 then
|
||||
print('Setting: Ultimate Magic card to Mifare mini S20 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000900")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting Mifare 1k S50 4--byte
|
||||
elseif tagtype == 3 then
|
||||
print('Setting: Ultimate Magic card to Mifare 1k S50 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare 1k S50 7-byte
|
||||
elseif tagtype == 4 then
|
||||
print('Setting: Ultimate Magic card to Mifare 1k S50 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151644000800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting Mifare 4k S70 4-byte
|
||||
elseif tagtype == 5 then
|
||||
print('Setting: Ultimate Magic card to Mifare 4k S70 4-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151602001800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233')
|
||||
-- Setting Mifare 4k S70 7-byte
|
||||
elseif tagtype == 6 then
|
||||
print('Setting: Ultimate Magic card to Mifare 4k S70 7-byte')
|
||||
connect()
|
||||
send("CF".._key.."F000010000000002000978009102DABC19101011121314151642001800")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
-- Setting UL
|
||||
elseif tagtype == 7 then
|
||||
print('Setting: Ultimate Magic card to UL')
|
||||
connect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000003")
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0000000000000000') -- UL-C does not have a version
|
||||
-- Setting UL-C
|
||||
elseif tagtype == 8 then
|
||||
print('Setting: Ultimate Magic card to UL-C')
|
||||
connect()
|
||||
send("CF".._key.."F0010100000000030A0A78008102DBA0C119402AB5BA4D321A44000002")
|
||||
print('Setting default permissions and 3des key')
|
||||
send('A22A30000000') -- Auth0 page 48/0x30 and above need authentication
|
||||
send('A22B80000000') -- Auth1 read and write access restricted
|
||||
send('A22C42524541') -- Default 3des key
|
||||
send('A22D4B4D4549')
|
||||
send('A22E46594F55')
|
||||
send('A22F43414E21')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0000000000000000') -- UL-C does not have a version
|
||||
elseif tagtype == 9 then
|
||||
print('Setting: Ultimate Magic card to UL-EV1 48')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
-- Setting UL-Ev1 default config bl 16,17
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a210000000FF')
|
||||
send('a21100050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03
|
||||
elseif tagtype == 10 then
|
||||
print('Setting: Ultimate Magic card to UL-EV1 128')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000000")
|
||||
-- Setting UL-Ev1 default config bl 37,38
|
||||
send('a2E5FFFFFFFF') -- A2F0 block does not align correctly to actual pwd block
|
||||
send('a2E6FFFFFFFF') -- A2F1 block does not align correctly to actual pack block
|
||||
send('a225000000FF')
|
||||
send('a22600050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_otp('00000000') -- Setting OTP to default 00 00 00 00
|
||||
write_version('0004030101000e03') -- UL-EV1 (128) 00 04 03 01 01 00 0e 03
|
||||
elseif tagtype == 12 then
|
||||
print('Setting: Ultimate Magic card to NTAG 210')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG210 default CC block456
|
||||
send('a203e1100600')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
-- Setting cfg1/cfg2
|
||||
send('a210000000FF')
|
||||
send('a21100050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03
|
||||
elseif tagtype == 13 then
|
||||
print('Setting: Ultimate Magic card to NTAG 212')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG212 default CC block456
|
||||
send('a203e1101000')
|
||||
send('a2040103900a')
|
||||
send('a205340300fe')
|
||||
-- Setting cfg1/cfg2
|
||||
send('a225000000FF')
|
||||
send('a22600050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03
|
||||
elseif tagtype == 14 then
|
||||
print('Setting: Ultimate Magic card to NTAG 213')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG213 default CC block456
|
||||
send('a203e1101200')
|
||||
send('a2040103a00c')
|
||||
send('a205340300fe')
|
||||
-- setting cfg1/cfg2
|
||||
send('a229000000ff')
|
||||
send('a22a00050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03
|
||||
elseif tagtype == 15 then
|
||||
print('Setting: Ultimate Magic card to NTAG 215')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG215 default CC block456
|
||||
send('a203e1103e00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
-- setting cfg1/cfg2
|
||||
send('a283000000ff')
|
||||
send('a28400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03
|
||||
elseif tagtype == 16 then
|
||||
print('Setting: Ultimate Magic card to NTAG 216')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG216 default CC block456
|
||||
send('a203e1106d00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
-- setting cfg1/cfg2
|
||||
send('a2e3000000ff')
|
||||
send('a2e400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03
|
||||
elseif tagtype == 17 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C 1K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 1K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03
|
||||
elseif tagtype == 18 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C 2K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 2K default CC block456
|
||||
send('a203e110EA00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03
|
||||
elseif tagtype == 19 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C plus 1K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 1K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03
|
||||
elseif tagtype == 20 then
|
||||
print('Setting: Ultimate Magic card to NTAG I2C plus 2K')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG I2C 2K default CC block456
|
||||
send('a203e1106D00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03
|
||||
elseif tagtype == 21 then
|
||||
print('Setting: Ultimate Magic card to NTAG 213F')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG213 default CC block456
|
||||
send('a203e1101200')
|
||||
send('a2040103a00c')
|
||||
send('a205340300fe')
|
||||
-- setting cfg1/cfg2
|
||||
send('a229000000ff')
|
||||
send('a22a00050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03
|
||||
elseif tagtype == 22 then
|
||||
print('Setting: Ultimate Magic card to NTAG 216F')
|
||||
connect()
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
-- Setting NTAG216 default CC block456
|
||||
send('a203e1106d00')
|
||||
send('a2040300fe00')
|
||||
send('a20500000000')
|
||||
-- setting cfg1/cfg2
|
||||
send('a2e3000000ff')
|
||||
send('a2e400050000')
|
||||
lib14a.disconnect()
|
||||
write_uid('04112233445566')
|
||||
write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03
|
||||
else
|
||||
oops('No matching tag types')
|
||||
end
|
||||
lib14a.disconnect()
|
||||
if resp == '04' then
|
||||
return nil, 'Failed to set type'
|
||||
else
|
||||
return true, 'Ok'
|
||||
end
|
||||
end
|
||||
---
|
||||
-- wipe tag
|
||||
local function wipe(wtype)
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if wtype == '0' then
|
||||
print('Starting Mifare Wipe')
|
||||
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
|
||||
send("CF".._key.."CD000102030404080400000000000000BEAF")
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
|
||||
local cmd_cfg1 = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
|
||||
for b = 1, 0xFB do
|
||||
if b == 0x03 or b == 0x07 or b == 0x0B or b == 0x0F or b == 0x13 or b == 0x17 or b == 0x1B or b == 0x1F or b == 0x23 or b == 0x27 or b == 0x2B or b == 0x2F or b == 0x33 or b == 0x37 or b == 0x3B or b == 0x3F then
|
||||
local cmd = (cmd_cfg1):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
local cmd = (cmd_empty):format(b)
|
||||
resp = send(cmd)
|
||||
end
|
||||
if resp == nil then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
print('\n')
|
||||
err, msg = set_type(3)
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
elseif wtype == '1' then
|
||||
print('Starting Ultralight Wipe')
|
||||
local err, msg, resp
|
||||
local cmd_empty = 'A2%02X00000000'
|
||||
local cmd_cfg1 = 'A2%02X000000FF'
|
||||
local cmd_cfg2 = 'A2%02X00050000'
|
||||
print('Wiping tag')
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
|
||||
for b = 3, 0xFB do
|
||||
--configuration block 0
|
||||
if b == 0x29 or b == 0x83 or b == 0xe3 then
|
||||
local cmd = (cmd_cfg1):format(b)
|
||||
resp = send(cmd)
|
||||
--configuration block 1
|
||||
elseif b == 0x2a or b == 0x84 or b == 0xe4 then
|
||||
local cmd = (cmd_cfg2):format(b)
|
||||
resp = send(cmd)
|
||||
else
|
||||
resp = send(cmd_empty:format(b))
|
||||
end
|
||||
if resp == '04' or #resp == 0 then
|
||||
io.write('\nwrote block '..b, ' failed\n')
|
||||
err = true
|
||||
else
|
||||
io.write('.')
|
||||
end
|
||||
io.flush()
|
||||
end
|
||||
io.write('\r\n')
|
||||
lib14a.disconnect()
|
||||
print('\n')
|
||||
if err then return nil, "Tag locked down, "..err_lock end
|
||||
-- set NTAG213 default values
|
||||
err, msg = set_type(14)
|
||||
if err == nil then return err, msg end
|
||||
--set UID
|
||||
err, msg = write_uid('04112233445566')
|
||||
if err == nil then return err, msg end
|
||||
--set NTAG pwd
|
||||
err, msg = write_ntagpwd('FFFFFFFF')
|
||||
if err == nil then return err, msg end
|
||||
--set pack
|
||||
err, msg = write_pack('0000')
|
||||
if err == nil then return err, msg end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
else oops('Use 0 for Mifare wipe or 1 for Ultralight wipe')
|
||||
end
|
||||
end
|
||||
---
|
||||
-- The main entry point
|
||||
function main(args)
|
||||
print()
|
||||
local err, msg
|
||||
if #args == 0 then return help() end
|
||||
-- Read the parameters
|
||||
for o, a in getopt.getopt(args, 'hck:u:t:p:a:s:o:v:q:g:z:n:m:w:') do
|
||||
-- help
|
||||
if o == "h" then return help() end
|
||||
-- set Ultimate Magic Card Key for read write
|
||||
if o == "k" then err, msg = set_key(a) end
|
||||
-- configuration
|
||||
if o == "c" then err, msg = read_config() end
|
||||
-- wipe tag
|
||||
if o == "w" then err, msg = wipe(a) end
|
||||
-- write uid
|
||||
if o == "u" then err, msg = write_uid(a) end
|
||||
-- write type/version
|
||||
if o == "t" then err, msg = set_type(a) end
|
||||
-- write NTAG pwd
|
||||
if o == "p" then err, msg = write_ntagpwd(a) end
|
||||
-- write pack
|
||||
if o == "a" then err, msg = write_pack(a) end
|
||||
-- write signature
|
||||
if o == "s" then err, msg = write_signature(a) end
|
||||
-- write otp
|
||||
if o == "o" then err, msg = write_otp(a) end
|
||||
-- write version
|
||||
if o == "v" then err, msg = write_version(a) end
|
||||
-- write atqa/sak
|
||||
if o == "q" then err, msg = write_atqasak(a) end
|
||||
-- write gtu mode
|
||||
if o == "g" then err, msg = write_gtu(a) end
|
||||
-- write ats
|
||||
if o == "z" then err, msg = write_ats(a) end
|
||||
-- write UL mode
|
||||
if o == "m" then err, msg = write_ulm(a) end
|
||||
-- write UL protocol
|
||||
if o == "n" then err, msg = write_ulp(a) end
|
||||
if err == nil then return oops(msg) end
|
||||
end
|
||||
end
|
||||
main(args)
|
Loading…
Add table
Reference in a new issue