mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-12-29 11:52:59 +08:00
ADD: 'script run ntag_3d.lua' - script to program xyz related ntag213f / magic ntag
This commit is contained in:
parent
07d51ec4a4
commit
cd1f5a58f5
1 changed files with 383 additions and 0 deletions
383
client/scripts/ntag_3d.lua
Normal file
383
client/scripts/ntag_3d.lua
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local lib14a = require('read14a')
|
||||||
|
|
||||||
|
copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.'
|
||||||
|
author = "Christian Herrmann"
|
||||||
|
version = 'v1.0.3'
|
||||||
|
desc = [[
|
||||||
|
This script writes a empty template for 3D printing system onto a empty NTAG213 or MAGIC NTAG21*
|
||||||
|
|
||||||
|
Thanks to @jack for his invaluable input on some of the configuration.
|
||||||
|
]]
|
||||||
|
example =[[
|
||||||
|
-- This will generate GOLD, PLA, TH, EU, 200m, tagbased uid.
|
||||||
|
script run ntag_3d -c 46 -m 50 -p 5448 -s 4555 -l 200
|
||||||
|
|
||||||
|
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid.
|
||||||
|
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200
|
||||||
|
|
||||||
|
-- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. and configure a MAGIC NTAG.
|
||||||
|
script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
script run calc_ntag_3d -h -t -u <uid> -c <color> -m <material> -p <region> -s <region> -l <length>
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
-h : this help
|
||||||
|
-t : selftest
|
||||||
|
-u <UID> : UID
|
||||||
|
-c <COLOR> : color of filament
|
||||||
|
-m <MATERIAL> : material of filament
|
||||||
|
-p <REGION> : Manufacturer region
|
||||||
|
-s <REGION> : Sales region
|
||||||
|
-l <LENGTH> : Spool length. Use only 100,200,300. 300 has problems on OSX
|
||||||
|
]]
|
||||||
|
|
||||||
|
local DEBUG = true
|
||||||
|
local TIMEOUT = 10000 -- 10 seconds
|
||||||
|
local bxor = bit32.bxor
|
||||||
|
local band = bit32.band
|
||||||
|
local rshift = bit32.rshift
|
||||||
|
|
||||||
|
local _regions = {
|
||||||
|
{'4742', 'GB'},
|
||||||
|
{'5457', 'TW'},
|
||||||
|
{'4555', 'EU'},
|
||||||
|
{'5553', 'US'},
|
||||||
|
{'454E', 'EN'},
|
||||||
|
{'4A50', 'JP'},
|
||||||
|
{'434E', 'CN'},
|
||||||
|
{'5448', 'TH'},
|
||||||
|
{'4153', 'AS'},
|
||||||
|
{'5246', 'RF'},
|
||||||
|
{'4746', 'GF'},
|
||||||
|
{'4341', 'CA'},
|
||||||
|
{'504D', 'PM'},
|
||||||
|
{'5044', 'PD'},
|
||||||
|
}
|
||||||
|
local _manufacturers = {
|
||||||
|
{'5457', 'TW'},
|
||||||
|
{'434E', 'CN'},
|
||||||
|
{'5448', 'TH'},
|
||||||
|
}
|
||||||
|
local _sales = {
|
||||||
|
{'4742', 'GB'},
|
||||||
|
{'4555', 'EU'},
|
||||||
|
{'5553', 'US'},
|
||||||
|
{'454E', 'EN'},
|
||||||
|
{'504D', 'PM'},
|
||||||
|
}
|
||||||
|
local _materials = {
|
||||||
|
{'20', 'Other material'},
|
||||||
|
{'41', 'ABS'},
|
||||||
|
{'46', 'Flexible TPE Tree'},
|
||||||
|
{'46', 'TPE'},
|
||||||
|
{'46', 'PVA'},
|
||||||
|
{'47', 'PETG'},
|
||||||
|
{'50', 'PLA'},
|
||||||
|
{'51', 'PLA'},
|
||||||
|
{'54', 'Tough PLA'},
|
||||||
|
{'55', 'UVCR'},
|
||||||
|
{'56', 'Water Soluble PVA'},
|
||||||
|
}
|
||||||
|
local _colors = {
|
||||||
|
{'30', 'Bronze'},
|
||||||
|
{'31', 'Silver'},
|
||||||
|
{'32', 'Clear Red'},
|
||||||
|
{'33', 'Clear'},
|
||||||
|
{'34', 'Bottle Green'},
|
||||||
|
{'35', 'Neon Magenta'},
|
||||||
|
{'36', 'SteelBlue'},
|
||||||
|
{'37', 'Sun Orange'},
|
||||||
|
{'38', 'Pearl White'},
|
||||||
|
{'39', 'Copper'},
|
||||||
|
{'41', 'Purple'},
|
||||||
|
{'42', 'Blue'},
|
||||||
|
{'43', 'Neon Tangerine'},
|
||||||
|
{'44', 'Viridity'},
|
||||||
|
{'45', 'Olivine'},
|
||||||
|
{'46', 'Gold'},
|
||||||
|
{'47', 'Green'},
|
||||||
|
{'48', 'Neon Green'},
|
||||||
|
{'49', 'Snow White'},
|
||||||
|
{'4A', 'Neon Yellow'},
|
||||||
|
{'4B', 'Black'},
|
||||||
|
{'4C', 'Violet'},
|
||||||
|
{'4D', 'Grape Purple'},
|
||||||
|
{'4E', 'Purpurine'},
|
||||||
|
{'4F', 'Clear Yellow'},
|
||||||
|
{'50', 'Clear Green'},
|
||||||
|
{'51', 'Clear Tangerine'},
|
||||||
|
{'52', 'Red'},
|
||||||
|
{'53', 'Cyber Yellow'},
|
||||||
|
{'54', 'Tangerine'},
|
||||||
|
{'55', 'Clear Blue'},
|
||||||
|
{'56', 'Clear Purple'},
|
||||||
|
{'57', 'White'},
|
||||||
|
{'58', 'Clear Magenta'},
|
||||||
|
{'59', 'Yellow'},
|
||||||
|
{'5A', 'Nature'},
|
||||||
|
}
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function find( arr, name )
|
||||||
|
if not name then return nil end
|
||||||
|
name = name:lower()
|
||||||
|
for k, v in pairs(arr) do
|
||||||
|
if ( v[2]:lower() == name or v[1]:lower() == name ) then
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function list( arr, desc )
|
||||||
|
print ('Value\t'..desc)
|
||||||
|
print (string.rep('=', 20))
|
||||||
|
for k, v in pairs(arr) do
|
||||||
|
print(("%s\t%s"):format(v[1],v[2]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- 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)
|
||||||
|
return nil,err
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
local function help()
|
||||||
|
print(copyright)
|
||||||
|
print(version)
|
||||||
|
print(desc)
|
||||||
|
print('Example usage')
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- Exit message
|
||||||
|
local function ExitMsg(msg)
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print(msg)
|
||||||
|
print()
|
||||||
|
end
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function write_tag(uid, t)
|
||||||
|
|
||||||
|
print('Writing to tag')
|
||||||
|
core.console('hf mf dbg 0')
|
||||||
|
|
||||||
|
local cmd = ''
|
||||||
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
|
for i= 8, 23 do
|
||||||
|
cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd)
|
||||||
|
core.console(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
--cfg1
|
||||||
|
core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd))
|
||||||
|
--cfg0
|
||||||
|
core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd))
|
||||||
|
--dynamic
|
||||||
|
core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd))
|
||||||
|
|
||||||
|
core.console('hf mf dbg 1')
|
||||||
|
print('Done')
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- configures a magic NTAG for NTAG213, with UID and PWD,PACK.
|
||||||
|
local function configure_magic_ntag(uid)
|
||||||
|
|
||||||
|
print('Configuring MAGIC NTAG')
|
||||||
|
-- Save the global args, those are *our* arguments
|
||||||
|
local myargs = args
|
||||||
|
|
||||||
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
|
-- Set the arguments for mfu_magic script v1.0.8
|
||||||
|
-- -t 12 == configure NTAG213F
|
||||||
|
-- -u == set UID
|
||||||
|
-- -p == set pwd
|
||||||
|
-- -a == set pack
|
||||||
|
args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack)
|
||||||
|
require('../scripts/mfu_magic')
|
||||||
|
|
||||||
|
-- Set back args. Not that it's used, just for the karma...
|
||||||
|
args = myargs
|
||||||
|
|
||||||
|
print('Done')
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- generates random hex numbers between 31-39
|
||||||
|
local function random_num_hex(length)
|
||||||
|
local str = ""
|
||||||
|
local i
|
||||||
|
for i = 1, length, 1 do
|
||||||
|
str = str..math.random(31, 39)
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function nwo( val )
|
||||||
|
local b1 = band(val, 0xFF)
|
||||||
|
local b2 = band( rshift(val, 8), 0xFF)
|
||||||
|
local b3 = band( rshift(val, 16), 0xFF)
|
||||||
|
local b4 = band( rshift(val, 24), 0xFF)
|
||||||
|
return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- NTAG213 template
|
||||||
|
local function template_NTAG213(uid, material, color, length, manufacture, sales)
|
||||||
|
local pwd, pack = core.keygen_algo_d(uid)
|
||||||
|
|
||||||
|
local m = tonumber(length, 10) * 1000
|
||||||
|
local m_str = nwo(m)
|
||||||
|
|
||||||
|
local t = {}
|
||||||
|
-- default empty file
|
||||||
|
for i = 0,42 do
|
||||||
|
t[i] = '00000000'
|
||||||
|
end
|
||||||
|
-- t[4] = '0103A00C' --
|
||||||
|
-- t[5] = '340300FE' --
|
||||||
|
-- 6,7
|
||||||
|
t[8] = '5A'..material..color..'00' -- 5A, material, color, 00
|
||||||
|
t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number
|
||||||
|
t[10] = m_str -- total capacity
|
||||||
|
t[11] = m_str -- total capacity
|
||||||
|
t[12] = 'D2002D00' -- fixed
|
||||||
|
t[13] = manufacture..sales -- regioner,
|
||||||
|
t[14] = random_num_hex(4) -- serial number
|
||||||
|
-- 15,16
|
||||||
|
t[17] = '34000000' -- fixed
|
||||||
|
-- 18,19
|
||||||
|
-- remaining capacity of spool
|
||||||
|
t[20] = m_str
|
||||||
|
t[21] = nwo( bxor( m, 0x54321248))
|
||||||
|
t[22] = nwo( bxor( (m - 3876923 ), 0x31275455))
|
||||||
|
t[23] = nwo( bxor( (m + 6923923 ), 0x76235481))
|
||||||
|
-- 24-39
|
||||||
|
t[40] = '000000BD' --dynamic
|
||||||
|
t[41] = '07000008' --cfg0
|
||||||
|
t[42] = '80050000' --cfg1
|
||||||
|
t[43] = ('%08X'):format(pwd)
|
||||||
|
t[44] = ('%04X0000'):format(pack)
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- outputs the called arguments
|
||||||
|
local function print_conf(uid, material, color, length, producer, sales )
|
||||||
|
print('Create tag as following')
|
||||||
|
print( string.rep('--',16) )
|
||||||
|
print('UID ', uid)
|
||||||
|
print('Material ', material[2])
|
||||||
|
print('Color ', color[2])
|
||||||
|
print('Spool length ', length)
|
||||||
|
print('Region')
|
||||||
|
print(' manufacturer', producer[2])
|
||||||
|
print(' sales ', sales[2])
|
||||||
|
print( string.rep('--',16) )
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- self test
|
||||||
|
local function selftest()
|
||||||
|
list(_regions, 'Regions')
|
||||||
|
list(_materials, 'Materials')
|
||||||
|
list(_colors, 'Colors')
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- The main entry point
|
||||||
|
local function main(args)
|
||||||
|
|
||||||
|
math.randomseed(os.time());
|
||||||
|
math.random();
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print()
|
||||||
|
|
||||||
|
local uid = '04C5DF4A6D5180'
|
||||||
|
local useUID = false
|
||||||
|
local useMAGIC = false
|
||||||
|
local material, color, length, producer, sales
|
||||||
|
|
||||||
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
|
-- Read the parameters
|
||||||
|
for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do
|
||||||
|
if o == "h" then return help() end
|
||||||
|
if o == "t" then return selftest() end
|
||||||
|
if o == "u" then uid = a; useUID = true end
|
||||||
|
if o == "m" then material = a end
|
||||||
|
if o == "c" then color = a end
|
||||||
|
if o == "l" then length = tonumber(a) end
|
||||||
|
if o == "p" then producer = a end
|
||||||
|
if o == "s" then sales = a end
|
||||||
|
if o == "1" then useMAGIC = true end
|
||||||
|
end
|
||||||
|
|
||||||
|
color = find(_colors, color)
|
||||||
|
if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end
|
||||||
|
|
||||||
|
material = find(_materials, material)
|
||||||
|
if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end
|
||||||
|
|
||||||
|
producer = find(_manufacturers, producer)
|
||||||
|
if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end
|
||||||
|
|
||||||
|
sales = find(_sales, sales)
|
||||||
|
if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end
|
||||||
|
|
||||||
|
if length > 300 then
|
||||||
|
return oops('\n\nNot valid spool length. Must be lesser than 300')
|
||||||
|
end
|
||||||
|
|
||||||
|
if useUID then
|
||||||
|
-- uid string checks
|
||||||
|
if uid == nil then return oops('empty uid string') end
|
||||||
|
if #uid == 0 then return oops('empty uid string') end
|
||||||
|
if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
|
||||||
|
else
|
||||||
|
-- GET TAG UID
|
||||||
|
local tag, err = lib14a.read1443a(false, true)
|
||||||
|
if not tag then return oops(err) end
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
uid = tag.uid
|
||||||
|
end
|
||||||
|
|
||||||
|
--print
|
||||||
|
print_conf(uid, material, color, length, producer, sales )
|
||||||
|
|
||||||
|
-- create template
|
||||||
|
local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1])
|
||||||
|
|
||||||
|
-- using MAGIC NTAG
|
||||||
|
if useMAGIC then
|
||||||
|
configure_magic_ntag(uid)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- write template data to tag
|
||||||
|
write_tag(uid, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
main(args)
|
Loading…
Reference in a new issue