mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-11 18:33:18 +08:00
403 lines
12 KiB
Lua
403 lines
12 KiB
Lua
local cmds = require('commands')
|
|
local getopt = require('getopt')
|
|
local bin = require('bin')
|
|
local utils = require('utils')
|
|
local ansicolors = require('ansicolors')
|
|
|
|
local format = string.format
|
|
local floor = math.floor
|
|
|
|
copyright = ''
|
|
author = "Iceman"
|
|
version = 'v1.0.4'
|
|
desc =[[
|
|
This script will program a T55x7 TAG with a configuration and four blocks of data.
|
|
It will then try to detect and read back those block data and compare if read data matches the expected data.
|
|
|
|
|
|
lf t55xx wipe
|
|
lf t55xx detect
|
|
lf t55xx write -b 1 -d 00000000
|
|
lf t55xx write -b 2 -d ffffffff
|
|
lf t55xx write -b 3 -d 80000000
|
|
lf t55xx write -b 4 -d 00000001
|
|
|
|
Loop:
|
|
|
|
try write different configuration blocks, and read block1-4 and comparing the read values with the values used to write.
|
|
|
|
testsuit for T55XX commands demodulation
|
|
|
|
]]
|
|
example = [[
|
|
1. script run lf_t55xx_writetest
|
|
2. script run lf_t55xx_writetest -t FSK2A
|
|
3. script run lf_t55xx_writetest -t PSK1
|
|
]]
|
|
usage = [[
|
|
script run lf_t55xx_writetest [-h] [-t <modulation type>
|
|
]]
|
|
arguments = [[
|
|
-h this help
|
|
-t (optional, defaults to ASK) 'PSK1', 'PSK2', 'PSK3',
|
|
'FSK1', 'FSK2', 'FSK1A', 'FSK2A',
|
|
'ASK', 'BI'
|
|
]]
|
|
|
|
local DEBUG = true -- the debug flag
|
|
local TIMEOUT = 1500
|
|
local total_tests = 0
|
|
local total_pass = 0
|
|
|
|
local data_blocks_cmds = {
|
|
[1] = '00000000',
|
|
[2] = 'ffffffff',
|
|
[3] = '80000000',
|
|
[4] = '00000001',
|
|
}
|
|
|
|
---
|
|
-- A debug printout-function
|
|
local function dbg(args)
|
|
if not DEBUG then return end
|
|
if type(args) == 'table' then
|
|
local i = 1
|
|
while args[i] do
|
|
dbg(args[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(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
|
|
---
|
|
-- Exit message
|
|
local function exitMsg(msg)
|
|
print( string.rep('--',20) )
|
|
print( string.rep('--',20) )
|
|
print(msg)
|
|
print()
|
|
end
|
|
---
|
|
-- ask/fsk/psk configuration blocks to test
|
|
local function GetConfigs( modulation )
|
|
|
|
local t = {}
|
|
|
|
t['PSK1'] = {
|
|
-- Rf2
|
|
[1] = '00001040', -- 8
|
|
[2] = '00041040', -- 16
|
|
[3] = '00081040', -- 32
|
|
[4] = '000c1040', -- 40
|
|
[5] = '00101040', -- 50
|
|
[6] = '00141040', -- 64
|
|
[7] = '00181040', -- 100
|
|
[8] = '001c1040', -- 128
|
|
-- Rf4
|
|
[9] = '00001440', -- 8
|
|
[10] = '00041440', -- 16
|
|
[11] = '00081440', -- 32
|
|
[12] = '000c1440', -- 40
|
|
-- [] = '00101440', -- 50 50/4 == 12.5 invalid
|
|
[13] = '00141440', -- 64
|
|
[14] = '00181440', -- 100
|
|
[15] = '001c1440', -- 128
|
|
-- Rf8
|
|
[16] = '00001840', -- 8
|
|
[17] = '00041840', -- 16
|
|
[18] = '00081840', -- 32
|
|
[19] = '000c1840', -- 40
|
|
-- [] = '00101840', -- 50 50/8 = 6.25 invalid
|
|
[20] = '00141840', -- 64
|
|
-- [] = '00181840', -- 100 100/8 == 12.5 invalid
|
|
[21] = '001c1840', -- 128
|
|
}
|
|
|
|
t['PSK2'] = {
|
|
-- Rf2
|
|
[1] = '00002040', -- 8
|
|
[2] = '00042040', -- 16
|
|
[3] = '00082040', -- 32
|
|
[4] = '000c2040', -- 40
|
|
[5] = '00102040', -- 50
|
|
[6] = '00142040', -- 64
|
|
[7] = '00182040', -- 100
|
|
[8] = '001c2040', -- 128
|
|
-- Rf4
|
|
[9] = '00002440', -- 8
|
|
[10] = '00042440', -- 16
|
|
[11] = '00082440', -- 32
|
|
[12] = '000c2440', -- 40
|
|
-- [] = '00102440', -- 50 50/4 == 12.5 invalid
|
|
[13] = '00142440', -- 64
|
|
[14] = '00182440', -- 100
|
|
[15] = '001c2440', -- 128
|
|
-- Rf8
|
|
[16] = '00002840', -- 8
|
|
[17] = '00042840', -- 16
|
|
[18] = '00082840', -- 32
|
|
[19] = '000c2840', -- 40
|
|
-- [] = '00102840', -- 50 50/8 == 6.25 invalid
|
|
[20] = '00142840', -- 64
|
|
-- [] = '00182840', -- 100 100/8 == 12.5 invalid
|
|
[21] = '001c2840', -- 128
|
|
}
|
|
|
|
t['PSK3'] = {
|
|
-- Rf2
|
|
[1] = '00003040', -- 8
|
|
[2] = '00043040', -- 16
|
|
[3] = '00083040', -- 32
|
|
[4] = '000c3040', -- 40
|
|
[5] = '00103040', -- 50
|
|
[6] = '00143040', -- 64
|
|
[7] = '00183040', -- 100
|
|
[8] = '001c3040', -- 128
|
|
-- Rf4
|
|
[9] = '00003440', -- 8
|
|
[10] = '00043440', -- 16
|
|
[11] = '00083440', -- 32
|
|
[12] = '000c3440', -- 40
|
|
-- [] = '00103440', -- 50 50/4 == 12.5 invalid
|
|
[13] = '00143440', -- 64
|
|
[14] = '00183440', -- 100
|
|
[15] = '001c3440', -- 128
|
|
-- Rf2
|
|
[16] = '00003840', -- 8
|
|
[17] = '00043840', -- 16
|
|
[18] = '00083840', -- 32
|
|
[19] = '000c3840', -- 40
|
|
-- [] = '00103840', -- 50 50/8 == 6.25 invalid
|
|
[20] = '00143840', -- 64
|
|
-- [] = '00183840', -- 100 100/8 == 12.5 invalid
|
|
[21] = '001c3840', -- 128
|
|
}
|
|
|
|
t['FSK1'] = {
|
|
[1] = '00004040',
|
|
[2] = '00004040',
|
|
[3] = '00044040',
|
|
[4] = '00084040',
|
|
[5] = '000c4040',
|
|
[6] = '00104040',
|
|
[7] = '00144040',
|
|
[8] = '00184040',
|
|
[9] = '001c4040',
|
|
}
|
|
|
|
t['FSK2'] = {
|
|
[1] = '00005040',
|
|
[2] = '00045040',
|
|
[3] = '00085040',
|
|
[4] = '000c5040',
|
|
[5] = '00105040',
|
|
[6] = '00145040',
|
|
[7] = '00185040',
|
|
[8] = '001c5040',
|
|
}
|
|
|
|
t['FSK1A'] = {
|
|
[1] = '00006040',
|
|
[2] = '00046040',
|
|
[3] = '00086040',
|
|
[4] = '000c6040',
|
|
[5] = '00106040',
|
|
[6] = '00146040',
|
|
[7] = '00186040',
|
|
[8] = '001c6040',
|
|
}
|
|
|
|
t['FSK2A'] = {
|
|
[1] = '00007040',
|
|
[2] = '00047040',
|
|
[3] = '00087040',
|
|
[4] = '000c7040',
|
|
[5] = '00107040',
|
|
[6] = '00147040',
|
|
[7] = '00187040',
|
|
[8] = '001c7040',
|
|
}
|
|
|
|
t['ASK'] = {
|
|
[1] = '00008040',
|
|
[2] = '00048040',
|
|
[3] = '00088040',
|
|
[4] = '000c8040',
|
|
[5] = '00108040',
|
|
[6] = '00148040',
|
|
[7] = '00188040',
|
|
[8] = '001c8040',
|
|
}
|
|
|
|
t['BI'] = {
|
|
[1] = '00010040',
|
|
[2] = '00050040',
|
|
[3] = '00090040',
|
|
[4] = '000d0040',
|
|
[5] = '00110040',
|
|
[6] = '00150040',
|
|
[7] = '00190040',
|
|
[8] = '001d0040',
|
|
}
|
|
|
|
return t[modulation:upper()]
|
|
end
|
|
---
|
|
-- lf t55xx wipe
|
|
local function WipeCard()
|
|
|
|
print('Wiping card')
|
|
core.console('lf t55xx wipe')
|
|
|
|
print('Detecting card')
|
|
local res, msg = core.t55xx_detect()
|
|
if not res then
|
|
oops("Can't detect modulation. Test failed.")
|
|
core.console('rem [ERR:DETECT:WIPED] Failed to detect after wipe')
|
|
return false
|
|
else
|
|
local wipe_data_cmd = 'lf t55xx write -b %s -d %s'
|
|
for _ = 1, #data_blocks_cmds do
|
|
local val = data_blocks_cmds[_]
|
|
local c = string.format(wipe_data_cmd, _, val)
|
|
core.console(c)
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
---
|
|
-- lf t55xx read
|
|
local function CheckReadBlock(block)
|
|
local data, msg
|
|
-- blockno, page1, override, pwd
|
|
data, msg = core.t55xx_readblock(block, '0', '0', '')
|
|
if not data then
|
|
return ''
|
|
end
|
|
return ('%08X'):format(data)
|
|
end
|
|
|
|
local function test(modulation)
|
|
|
|
local process_block0_cmds = {}
|
|
local y
|
|
local password = '00000000'
|
|
local block = '00' -- configuration block 0
|
|
local flags = '00' -- page 0, no pwd, no testmode
|
|
|
|
local s = ('Start test of %s'):format(modulation)
|
|
print(s)
|
|
|
|
process_block0_cmds = GetConfigs(modulation)
|
|
|
|
if process_block0_cmds == nil then return oops('Cant find modulation '..modulation) end
|
|
|
|
for _ = 1, #process_block0_cmds do
|
|
|
|
local p_config_cmd = process_block0_cmds[_]
|
|
local errors = 0
|
|
core.clearCommandBuffer()
|
|
|
|
-- Write Config block
|
|
dbg(('lf t55xx write -b 0 -d %s'):format(p_config_cmd))
|
|
|
|
local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(p_config_cmd, 32), password, block, flags)
|
|
|
|
local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data}
|
|
local response, err = wc:sendNG(false, TIMEOUT)
|
|
if not response then return oops(err) end
|
|
|
|
-- Detect
|
|
local res, msg = core.t55xx_detect()
|
|
if not res then
|
|
print("can't detect modulation, skip to next config")
|
|
core.console(format('rem [ERR:DETECT:%s] Failed to detect modulation', p_config_cmd))
|
|
core.console(format('rem [SUMMARY:%s] FAIL detection', p_config_cmd))
|
|
total_tests = total_tests + #data_blocks_cmds
|
|
else
|
|
-- Loop block1-2
|
|
for _ = 1, #data_blocks_cmds do
|
|
total_tests = total_tests + 1
|
|
local val = data_blocks_cmds[_]
|
|
local blockdata, msg = CheckReadBlock(_)
|
|
if blockdata:lower() ~= val:lower() then
|
|
print( ('Test %s == %s Failed'):format(val, blockdata))
|
|
core.console( format('rem [ERR:READ:%s:%d] block %d: read %s instead of %s', p_config_cmd, _, _, blockdata, val))
|
|
errors = errors+1
|
|
else
|
|
print( ('Test %s == %s OK'):format(val, blockdata))
|
|
total_pass = total_pass + 1
|
|
end
|
|
end
|
|
if errors >0 then
|
|
core.console( format('rem [SUMMARY:%s] FAIL %d test%s', p_config_cmd, errors, errors > 1 and "s" or ""))
|
|
else
|
|
core.console( format('rem [SUMMARY:%s] PASS all tests', p_config_cmd))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function main(args)
|
|
|
|
print( string.rep('--',20) )
|
|
print( string.rep('--',20) )
|
|
|
|
local modulation_type = 'ASK'
|
|
-- Arguments for the script
|
|
for o, arg in getopt.getopt(args, 'ht:') do
|
|
if o == 'h' then return help() end
|
|
if o == 't' then modulation_type = arg end
|
|
end
|
|
|
|
core.clearCommandBuffer()
|
|
local res
|
|
|
|
-- Adjust this table to set which configurations should be tested
|
|
-- local test_modes = { 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2', 'FSK1A', 'FSK2A', 'ASK', 'BI' }
|
|
--local test_modes = { 'PSK1' }
|
|
local test_modes = { modulation_type }
|
|
|
|
for _ = 1, #test_modes do
|
|
res = WipeCard()
|
|
if res then
|
|
print (test_modes[_])
|
|
test(test_modes[_])
|
|
else
|
|
exitMsg('Abort!')
|
|
return
|
|
end
|
|
end
|
|
|
|
exitMsg('Tests finished')
|
|
core.console(
|
|
format('rem [SUMMARY] Success rate: %d/%d tests passed%s'
|
|
, total_pass
|
|
, total_tests
|
|
, total_pass < total_tests and ', help me improving that number!' or ' \\o/'
|
|
)
|
|
)
|
|
end
|
|
main(args)
|