2019-12-26 07:09:44 +08:00
|
|
|
local cmds = require('commands')
|
|
|
|
local getopt = require('getopt')
|
|
|
|
local lib14a = require('read14a')
|
|
|
|
local utils = require('utils')
|
2020-04-05 18:41:38 +08:00
|
|
|
local ansicolors = require('ansicolors')
|
2019-12-26 07:09:44 +08:00
|
|
|
|
|
|
|
-- global
|
|
|
|
local DEBUG = false -- the debug flag
|
|
|
|
local bxor = bit32.bxor
|
|
|
|
local _password = nil
|
|
|
|
local err_lock = 'use -k or change cfg0 block'
|
|
|
|
|
|
|
|
copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.'
|
|
|
|
author = 'Christian Herrmann'
|
2020-04-05 18:41:38 +08:00
|
|
|
version = 'v1.1.3'
|
2019-12-26 07:09:44 +08:00
|
|
|
desc = 'This script enables easy programming of a MAGIC NTAG 21* card'
|
2020-04-05 18:41:38 +08:00
|
|
|
example = [[
|
2020-10-07 02:44:23 +08:00
|
|
|
-- wipe tag
|
|
|
|
script run hf_mfu_magicwrite -w
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- wipe a locked down tag by giving the password
|
|
|
|
script run hf_mfu_magicwrite -k ffffffff -w
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
--read magic tag configuration
|
|
|
|
script run hf_mfu_magicwrite -c
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- set uid
|
|
|
|
script run hf_mfu_magicwrite -u 04112233445566
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- set pwd / pack
|
|
|
|
script run hf_mfu_magicwrite -p 11223344 -a 8080
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- set version to NTAG213
|
|
|
|
script run hf_mfu_magicwrite -v 0004040201000f03
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- set signature
|
|
|
|
script run hf_mfu_magicwrite -s 1122334455667788990011223344556677889900112233445566778899001122
|
2019-12-26 07:09:44 +08:00
|
|
|
]]
|
2020-04-05 18:41:38 +08:00
|
|
|
usage = [[
|
2020-08-14 01:02:30 +08:00
|
|
|
script run hf_mfu_easywrite -h -k <passwd> -c -w -u <uid> -t <type> -p <passwd> -a <pack> -s <signature> -o <otp> -v <version>
|
2020-04-05 18:41:38 +08:00
|
|
|
]]
|
|
|
|
arguments = [[
|
2020-10-07 02:44:23 +08:00
|
|
|
-h this help
|
|
|
|
-c read magic configuration
|
|
|
|
-u UID (14 hexsymbols), set UID on tag
|
|
|
|
-t tag type to impersonate
|
|
|
|
1 = UL_EV1 48k
|
|
|
|
2 = UL_EV1 128k
|
|
|
|
3 = NTAG 210
|
|
|
|
4 = NTAG 212
|
|
|
|
5 = NTAG 213 (true)
|
|
|
|
6 = NTAG 215 (true)
|
|
|
|
7 = NTAG 216 (true)
|
|
|
|
8 = NTAG I2C 1K
|
|
|
|
9 = NTAG I2C 2K
|
|
|
|
10 = NTAG I2C 1K PLUS
|
|
|
|
11 = NTAG I2C 2K PLUS
|
|
|
|
12 = NTAG 213F (true)
|
|
|
|
13 = NTAG 216F (true)
|
|
|
|
-p password (8 hexsymbols), set password on tag.
|
|
|
|
-a pack ( 4 hexsymbols), set pack on tag.
|
|
|
|
-s signature data (64 hexsymbols), set signature data on tag.
|
|
|
|
-o OTP data (8 hexsymbols), set one-time-pad data on tag.
|
|
|
|
-v version data (16 hexsymbols), set version data on tag.
|
|
|
|
-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)
|
|
|
|
-k pwd to use with the wipe option
|
2019-12-26 07:09:44 +08:00
|
|
|
]]
|
2020-01-01 04:42:53 +08:00
|
|
|
---
|
2019-12-26 07:09:44 +08:00
|
|
|
-- A debug printout-function
|
|
|
|
local function dbg(args)
|
2020-10-07 02:44:23 +08:00
|
|
|
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
|
2020-01-01 04:42:53 +08:00
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
-- This is only meant to be used when errors occur
|
|
|
|
local function oops(err)
|
2020-10-07 02:44:23 +08:00
|
|
|
print("ERROR: ",err)
|
2019-12-26 07:09:44 +08:00
|
|
|
core.clearCommandBuffer()
|
2020-10-07 02:44:23 +08:00
|
|
|
return nil, err
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
2020-01-01 04:42:53 +08:00
|
|
|
---
|
2019-12-26 07:09:44 +08:00
|
|
|
-- Usage help
|
|
|
|
local function help()
|
|
|
|
print(copyright)
|
|
|
|
print(author)
|
|
|
|
print(version)
|
|
|
|
print(desc)
|
2020-04-05 18:41:38 +08:00
|
|
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
2019-12-26 07:09:44 +08:00
|
|
|
print(usage)
|
2020-04-05 18:41:38 +08:00
|
|
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
|
|
|
print(arguments)
|
|
|
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
|
|
|
print(example)
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- set the global password variable
|
|
|
|
local function set_password(pwd)
|
2020-10-07 02:44:23 +08:00
|
|
|
if pwd == nil then _password = nil; return true, 'Ok' end
|
|
|
|
if #pwd ~= 8 then return nil, 'password wrong length. Must be 4 hex bytes' end
|
|
|
|
if #pwd == 0 then _password = nil end
|
|
|
|
_password = pwd
|
|
|
|
return true, 'Ok'
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
--- Picks out and displays the data read from a tag
|
|
|
|
-- Specifically, takes a usb packet, converts to a Command
|
2020-01-01 04:42:53 +08:00
|
|
|
-- (as in commands.lua), takes the data-array and
|
2019-12-26 07:09:44 +08:00
|
|
|
-- reads the number of bytes specified in arg1 (arg0 in c-struct)
|
|
|
|
-- @param usbpacket the data received from the device
|
|
|
|
local function getResponseData(usbpacket)
|
2020-10-07 02:44:23 +08:00
|
|
|
local resp = Command.parse(usbpacket)
|
|
|
|
local len = tonumber(resp.arg1) * 2
|
|
|
|
return string.sub(tostring(resp.data), 0, len);
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
--
|
|
|
|
local function sendRaw(rawdata, options)
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
|
|
|
+ lib14a.ISO14A_COMMAND.ISO14A_RAW
|
|
|
|
+ lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
|
|
|
arg1 = flags,
|
|
|
|
-- arg2 contains the length, which is half the length of the ASCII-string rawdata
|
|
|
|
arg2 = string.len(rawdata)/2,
|
|
|
|
data = rawdata}
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2019-12-26 07:09:44 +08:00
|
|
|
return c:sendMIX(options.ignore_response)
|
|
|
|
end
|
|
|
|
---
|
|
|
|
--
|
|
|
|
local function send(payload)
|
2020-10-07 02:44:23 +08:00
|
|
|
local usb, err = sendRaw(payload,{ignore_response = false})
|
|
|
|
if err then return oops(err) end
|
|
|
|
return getResponseData(usb)
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- select tag and if password is set, authenticate
|
|
|
|
local function connect()
|
2020-10-07 02:44:23 +08:00
|
|
|
core.clearCommandBuffer()
|
2019-12-26 07:09:44 +08:00
|
|
|
|
|
|
|
-- First of all, connect
|
|
|
|
info, err = lib14a.read(true, true)
|
|
|
|
if err then
|
|
|
|
lib14a.disconnect()
|
|
|
|
return oops(err)
|
|
|
|
end
|
|
|
|
core.clearCommandBuffer()
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
--authenticate if needed using global variable
|
|
|
|
if _password then
|
|
|
|
send('1B'.._password)
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
--
|
|
|
|
-- Read magic configuration
|
|
|
|
local function read_config()
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- read PWD
|
|
|
|
local pwd = send("30F0"):sub(1,8)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- 04 response indicates that blocks has been locked down.
|
|
|
|
if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- read PACK
|
|
|
|
local pack = send("30F1"):sub(1,4)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- read SIGNATURE
|
|
|
|
local signature1 = send('30F2'):sub(1,32)
|
|
|
|
local signature2 = send('30F6'):sub(1,32)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- read VERSION
|
|
|
|
local version = send('30FA'):sub(1,16)
|
|
|
|
-- read config
|
|
|
|
local cardtype = send('30FC'):sub(1,2)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local typestr = ''
|
|
|
|
if cardtype == '00' then typestr = 'NTAG 213'
|
|
|
|
elseif cardtype == '01' then typestr = 'NTAG 215'
|
|
|
|
elseif cardtype == '02' then typestr = 'NTAG 216'
|
|
|
|
end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Magic NTAG 21* Configuration')
|
|
|
|
print(' - Type ', typestr, '(genuine cardtype)')
|
|
|
|
print(' - Password', pwd)
|
|
|
|
print(' - Pack ', pack)
|
|
|
|
print(' - Version ', version)
|
|
|
|
print(' - Signature', signature1..signature2)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
lib14a.disconnect()
|
|
|
|
return true, 'Ok'
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- Write SIGNATURE data
|
|
|
|
local function write_signature(data)
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- uid 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
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new signature')
|
|
|
|
|
|
|
|
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 == '04' then lib14a.disconnect(); return nil, 'Failed to write signature' end
|
|
|
|
j = j + 1
|
|
|
|
end
|
|
|
|
lib14a.disconnect()
|
|
|
|
return true, 'Ok'
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- Write PWD
|
2020-01-01 04:42:53 +08:00
|
|
|
local function write_pwd(pwd)
|
2020-10-07 02:44:23 +08:00
|
|
|
-- PWD string checks
|
|
|
|
if pwd == nil then return nil, 'empty PWD string' end
|
|
|
|
if #pwd == 0 then return nil, 'empty PWD string' end
|
|
|
|
if #pwd ~= 8 then return nil, 'PWD wrong length. Should be 4 hex bytes' end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new PWD ', pwd)
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local resp = send('A2F0'..pwd)
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write password'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- Write PACK
|
2020-01-01 04:42:53 +08:00
|
|
|
local function write_pack(pack)
|
2020-10-07 02:44:23 +08:00
|
|
|
-- PACK string checks
|
|
|
|
if pack == nil then return nil, 'empty PACK string' end
|
|
|
|
if #pack == 0 then return nil, 'empty PACK string' end
|
|
|
|
if #pack ~= 4 then return nil, 'PACK wrong length. Should be 4 hex bytes' end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new PACK', pack)
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local resp = send('A2F1'..pack..'0000')
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write pack'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
--
|
|
|
|
-- Write OTP block
|
|
|
|
local function write_otp(block3)
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- 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
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new OTP ', block3)
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local resp = send('A203'..block3)
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write OTP'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
--
|
|
|
|
-- Writes a UID with bcc1, bcc2. Needs a magic tag.
|
|
|
|
local function write_uid(uid)
|
2020-10-07 02:44:23 +08:00
|
|
|
-- uid string checks
|
|
|
|
if uid == nil then return nil, 'empty uid string' end
|
|
|
|
if #uid == 0 then return nil, 'empty uid string' end
|
|
|
|
if #uid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new UID ', uid)
|
|
|
|
|
|
|
|
local uidbytes = utils.ConvertHexToBytes(uid)
|
|
|
|
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)
|
|
|
|
lib14a.disconnect()
|
|
|
|
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write new uid'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- Write VERSION data,
|
|
|
|
-- make sure you have correct version data
|
|
|
|
local function write_version(data)
|
2020-10-07 02:44:23 +08:00
|
|
|
-- 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
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new version', data)
|
|
|
|
|
|
|
|
local b1 = data:sub(1,8)
|
|
|
|
local b2 = data:sub(9,16)
|
|
|
|
local resp
|
|
|
|
resp = send('A2FA'..b1)
|
|
|
|
resp = send('A2FB'..b2)
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write version'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
2020-01-01 04:42:53 +08:00
|
|
|
-- writen TYPE which card is based on.
|
2019-12-26 07:09:44 +08:00
|
|
|
-- 00 = 213, 01 = 215, 02 = 216
|
2020-01-01 04:42:53 +08:00
|
|
|
local function write_type(data)
|
2020-10-07 02:44:23 +08:00
|
|
|
-- type string checks
|
|
|
|
if data == nil then return nil, 'empty type string' end
|
|
|
|
if #data == 0 then return nil, 'empty type string' end
|
|
|
|
if #data ~= 2 then return nil, 'type wrong length. Should be 1 hex byte' end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2019-12-26 07:09:44 +08:00
|
|
|
local info = connect()
|
|
|
|
if not info then return false, "Can't select card" end
|
2020-10-07 02:44:23 +08:00
|
|
|
print('Writing new type', data)
|
|
|
|
|
|
|
|
local resp = send('A2FC'..data..'000000')
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to write type'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- Set tag type. Predefinde version data together with magic type set.
|
|
|
|
-- Since cmd always gives 10 bytes len (data+crc) we can impersonate the following types
|
2020-01-01 04:42:53 +08:00
|
|
|
-- we only truely be three types NTAG 213,215 and 216
|
2019-12-26 07:09:44 +08:00
|
|
|
local function set_type(tagtype)
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- tagtype checks
|
|
|
|
if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end
|
|
|
|
if tagtype == nil then return nil, 'empty tagtype' end
|
|
|
|
|
|
|
|
if tagtype == 1 then
|
|
|
|
print('Setting: UL-EV1 48')
|
|
|
|
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
|
|
|
|
write_type('00') -- based on NTAG213..
|
|
|
|
|
|
|
|
-- Setting UL-Ev1 default config bl 16,17
|
|
|
|
connect()
|
|
|
|
send('a210000000FF')
|
|
|
|
send('a21100050000')
|
|
|
|
|
|
|
|
elseif tagtype == 2 then
|
|
|
|
print('Setting: UL-EV1 128')
|
|
|
|
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
|
|
|
|
write_type('01')
|
|
|
|
|
|
|
|
-- Setting UL-Ev1 default config bl 37,38
|
|
|
|
connect()
|
|
|
|
send('a225000000FF')
|
|
|
|
send('a22600050000')
|
|
|
|
elseif tagtype == 3 then
|
|
|
|
print('Setting: NTAG 210')
|
|
|
|
write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03
|
|
|
|
write_type('00')
|
|
|
|
|
|
|
|
-- Setting NTAG210 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1100600')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
-- Setting cfg1/cfg2
|
|
|
|
send('a210000000FF')
|
|
|
|
send('a21100050000')
|
|
|
|
elseif tagtype == 4 then
|
|
|
|
print('Setting: NTAG 212')
|
|
|
|
write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03
|
|
|
|
write_type('00')
|
|
|
|
|
|
|
|
-- Setting NTAG212 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1101000')
|
|
|
|
send('a2040103900a')
|
|
|
|
send('a205340300fe')
|
|
|
|
-- Setting cfg1/cfg2
|
|
|
|
send('a225000000FF')
|
|
|
|
send('a22600050000')
|
|
|
|
elseif tagtype == 5 then
|
|
|
|
print('Setting: NTAG 213')
|
|
|
|
write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03
|
|
|
|
write_type('00')
|
|
|
|
|
|
|
|
-- Setting NTAG213 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1101200')
|
|
|
|
send('a2040103a00c')
|
|
|
|
send('a205340300fe')
|
|
|
|
-- setting cfg1/cfg2
|
|
|
|
send('a229000000ff')
|
|
|
|
send('a22a00050000')
|
|
|
|
elseif tagtype == 6 then
|
|
|
|
print('Setting: NTAG 215')
|
|
|
|
write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03
|
|
|
|
write_type('01')
|
|
|
|
|
|
|
|
-- Setting NTAG215 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1103e00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
-- setting cfg1/cfg2
|
|
|
|
send('a283000000ff')
|
|
|
|
send('a28400050000')
|
|
|
|
elseif tagtype == 7 then
|
|
|
|
print('Setting: NTAG 216')
|
|
|
|
write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG216 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1106d00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
-- setting cfg1/cfg2
|
|
|
|
send('a2e3000000ff')
|
|
|
|
send('a2e400050000')
|
|
|
|
elseif tagtype == 8 then
|
|
|
|
print('Setting: NTAG I2C 1K')
|
|
|
|
write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG I2C 1K default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1106D00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
elseif tagtype == 9 then
|
|
|
|
print('Setting: NTAG I2C 2K')
|
|
|
|
write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG I2C 2K default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e110EA00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
elseif tagtype == 10 then
|
|
|
|
print('Setting: NTAG I2C plus 1K')
|
|
|
|
write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG I2C 1K default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1106D00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
elseif tagtype == 11 then
|
|
|
|
print('Setting: NTAG I2C plus 2K')
|
|
|
|
write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG I2C 2K default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1106D00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
elseif tagtype == 12 then
|
|
|
|
print('Setting: NTAG 213F')
|
|
|
|
write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03
|
|
|
|
write_type('00')
|
|
|
|
|
|
|
|
-- Setting NTAG213 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1101200')
|
|
|
|
send('a2040103a00c')
|
|
|
|
send('a205340300fe')
|
|
|
|
-- setting cfg1/cfg2
|
|
|
|
send('a229000000ff')
|
|
|
|
send('a22a00050000')
|
|
|
|
elseif tagtype == 13 then
|
|
|
|
print('Setting: NTAG 216F')
|
|
|
|
write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03
|
|
|
|
write_type('02')
|
|
|
|
|
|
|
|
-- Setting NTAG216 default CC block456
|
|
|
|
connect()
|
|
|
|
send('a203e1106d00')
|
|
|
|
send('a2040300fe00')
|
|
|
|
send('a20500000000')
|
|
|
|
-- setting cfg1/cfg2
|
|
|
|
send('a2e3000000ff')
|
|
|
|
send('a2e400050000')
|
|
|
|
end
|
|
|
|
|
|
|
|
lib14a.disconnect()
|
|
|
|
if resp == '04' then
|
|
|
|
return nil, 'Failed to set type'
|
|
|
|
else
|
|
|
|
return true, 'Ok'
|
|
|
|
end
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
---
|
|
|
|
-- wipe tag
|
|
|
|
local function wipe()
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local info = connect()
|
2019-12-26 07:09:44 +08:00
|
|
|
if not info then return false, "Can't select card" end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local err, msg, resp
|
|
|
|
local cmd_empty = 'A2%02X00000000'
|
|
|
|
local cmd_cfg1 = 'A2%02X000000FF'
|
|
|
|
local cmd_cfg2 = 'A2%02X00050000'
|
|
|
|
|
|
|
|
print('Wiping tag')
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
if err then return nil, "Tag locked down, "..err_lock end
|
|
|
|
|
|
|
|
print('setting default values...')
|
|
|
|
|
|
|
|
set_password(nil)
|
|
|
|
|
|
|
|
-- set NTAG213 default values
|
|
|
|
err, msg = set_type(5)
|
|
|
|
if err == nil then return err, msg end
|
|
|
|
|
|
|
|
--set UID
|
|
|
|
err, msg = write_uid('04112233445566')
|
|
|
|
if err == nil then return err, msg end
|
|
|
|
|
|
|
|
--set pwd
|
|
|
|
err, msg = write_pwd('FFFFFFFF')
|
|
|
|
if err == nil then return err, msg end
|
|
|
|
|
|
|
|
--set pack
|
|
|
|
err, msg = write_pack('0000')
|
|
|
|
if err == nil then return err, msg end
|
|
|
|
|
|
|
|
return true, 'Ok'
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
2020-01-01 04:42:53 +08:00
|
|
|
---
|
2019-12-26 07:09:44 +08:00
|
|
|
-- The main entry point
|
|
|
|
function main(args)
|
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
print( string.rep('--',20) )
|
|
|
|
print( string.rep('--',20) )
|
|
|
|
print()
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
local err, msg
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
if #args == 0 then return help() end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- Read the parameters
|
|
|
|
for o, a in getopt.getopt(args, 'hck:u:t:p:a:s:o:v:w') do
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- help
|
|
|
|
if o == "h" then return help() end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
--key
|
|
|
|
if o == 'k' then err, msg = set_password(a) end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- configuration
|
|
|
|
if o == "c" then err, msg = read_config() end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
--wipe tag
|
|
|
|
if o == "w" then err, msg = wipe() end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write uid
|
|
|
|
if o == "u" then err, msg = write_uid(a) end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write type/version
|
|
|
|
if o == "t" then err, msg = set_type(a) end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write pwd
|
|
|
|
if o == "p" then err, msg = write_pwd(a) end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write pack
|
|
|
|
if o == "a" then err, msg = write_pack(a) end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write signature
|
|
|
|
if o == "s" then err, msg = write_signature(a) end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write otp
|
|
|
|
if o == "o" then err, msg = write_otp(a) end
|
2019-12-26 07:09:44 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
-- write version
|
|
|
|
if o == "v" then err, msg = write_version(a) end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2020-10-07 02:44:23 +08:00
|
|
|
if err == nil then return oops(msg) end
|
|
|
|
end
|
2020-01-01 04:42:53 +08:00
|
|
|
|
2019-12-26 07:09:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
main(args)
|