proxmark3/client/luascripts/lf_em_tearoff.lua

177 lines
4.7 KiB
Lua
Raw Normal View History

2020-10-10 13:59:17 +08:00
local getopt = require('getopt')
local ansicolors = require('ansicolors')
copyright = 'Iceman'
author = 'Iceman'
version = 'v0.9.9'
desc = [[
This is scripts loops though a tear attack and reads expected value.
]]
example = [[
1. script run tearoff -n 2 -s 200 -e 400 -a 5
]]
usage = [[
2020-10-10 15:24:47 +08:00
script run tearoff [-h] [-n <steps us>] [-a <addr>] [-p <pwd>] [-s <start us>] [-e <end us>] [-r <read>] [-w <write>]
2020-10-10 13:59:17 +08:00
]]
arguments = [[
-h This help
2020-10-10 16:00:38 +08:00
-n <steps us> steps in milliseconds for each tearoff
2020-10-10 13:59:17 +08:00
-a <addr> address to target on card
-p <pwd> (optional) use a password
2020-10-10 16:00:38 +08:00
-s <delay us> initial start delay
2020-10-10 13:59:17 +08:00
-e <delay us> end delay, must be larger than start delay
2020-10-10 15:24:47 +08:00
-r <read value> 4 hex bytes value to be read
-w <write value> 4 hex bytes value to be written
2020-10-10 13:59:17 +08:00
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
local function main(args)
--[[
Basically do the following,
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
1. hw tear
2020-10-12 04:40:05 +08:00
2. lf em 4x05_write
2020-10-10 13:59:17 +08:00
3. lf em 4x05_read
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
The first two commands doesn't need a feedback from the system, so going with core.console commands.
Since the read needs demodulation of signal I opted to add that function from cmdlfem4x.c to the core lua scripting
core.em4x05_read(addr, password)
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
--]]
2020-10-10 15:24:47 +08:00
local n, addr, password, sd, ed, wr_value, rd_value
2020-10-12 04:40:05 +08:00
2020-10-10 15:24:47 +08:00
for o, a in getopt.getopt(args, 'he:s:a:p:n:r:w:') do
2020-10-10 13:59:17 +08:00
if o == 'h' then return help() end
if o == 'n' then n = a end
if o == 'a' then addr = a end
if o == 'p' then password = a end
if o == 'e' then ed = tonumber(a) end
if o == 's' then sd = tonumber(a) end
2020-10-10 15:24:47 +08:00
if o == 'w' then wr_value = a end
if o == 'r' then rd_value = a end
2020-10-10 13:59:17 +08:00
end
2020-10-10 15:24:47 +08:00
rd_value = rd_value or 'FFFFFFFF'
wr_value = wr_value or 'FFFFFFFF'
2020-10-10 13:59:17 +08:00
addr = addr or 5
password = password or ''
n = n or 2
sd = sd or 2000
ed = ed or 2100
if #password ~= 8 then
password = ''
end
2020-10-12 04:40:05 +08:00
2020-10-10 15:24:47 +08:00
if #wr_value ~= 8 then
wr_value = 'FFFFFFFF'
end
if #rd_value ~= 8 then
rd_value = 'FFFFFFFF'
end
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
if sd > ed then
2020-10-10 16:00:38 +08:00
return oops('start delay can\'t be larger than end delay', sd, ed)
2020-10-10 13:59:17 +08:00
end
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
print('Starting EM4x05 tear off')
print('target addr', addr)
if password then
print('target pwd', password)
end
print('target stepping', n)
2020-10-10 15:24:47 +08:00
print('target delay', sd ,ed)
print('read value', rd_value)
print('write value', wr_value)
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
local res_tear = 0
local res_nowrite = 0
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
local set_tearoff_delay = 'hw tearoff --delay %d'
local enable_tearoff = 'hw tearoff --on'
2020-10-12 04:40:05 +08:00
2020-10-10 15:24:47 +08:00
local wr_template = 'lf em 4x05_write %s %s %s'
2020-10-12 04:40:05 +08:00
-- init addr to value
core.console(wr_template:format(addr, wr_value, password))
2020-10-12 04:40:05 +08:00
if sd == ed then
ed = n
n = 0
end
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
for step = sd, ed, n do
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
io.flush()
if core.kbd_enter_pressed() then
print("aborted by user")
break
end
core.clearCommandBuffer()
-- reset addr to known value, if not locked into.
if n ~= 0 then
2020-10-10 15:24:47 +08:00
c = wr_template:format(addr, wr_value, password)
core.console(c)
end
2020-10-12 04:40:05 +08:00
2020-10-10 13:59:17 +08:00
local c = set_tearoff_delay:format(step)
core.console(c);
core.console(enable_tearoff)
2020-10-12 04:40:05 +08:00
2020-10-10 15:24:47 +08:00
c = wr_template:format(addr, wr_value, password)
2020-10-10 13:59:17 +08:00
core.console(c)
2020-10-10 15:24:47 +08:00
2020-10-10 13:59:17 +08:00
local word, err = core.em4x05_read(addr, password)
if err then
return oops(err)
end
2020-10-12 04:40:05 +08:00
2020-10-10 15:24:47 +08:00
local wordstr = ('%08X'):format(word)
if wordstr ~= wr_value then
if wordstr ~= rd_value then
2020-10-10 16:00:38 +08:00
print((ansicolors.red..'TEAR OFF occurred:'..ansicolors.reset..' %08X'):format(word))
2020-10-10 13:59:17 +08:00
res_tear = res_tear + 1
else
2020-10-10 16:00:38 +08:00
print((ansicolors.cyan..'TEAR OFF occurred:'..ansicolors.reset..' %08X'):format(word))
2020-10-10 13:59:17 +08:00
res_nowrite = res_nowrite + 1
end
else
2020-10-10 16:00:38 +08:00
print((ansicolors.green..'Good write occurred:'..ansicolors.reset..' %08X'):format(word))
2020-10-10 13:59:17 +08:00
end
end
end
--[[
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)