2024-07-15 12:42:08 +03:00
local getopt = require ( 'getopt' )
local utils = require ( 'utils' )
local ac = require ( 'ansicolors' )
local os = require ( 'os' )
local count = 0
line = '-------------------------------------------------------------------------'
mod = " ELECTRA or EM410x fob cloning SCRIPT "
version = " v1.1.17 02/09/2023 made by jareckib "
desc = [[
2024-07-21 16:19:21 +02:00
Cloning new ELECTRA tags or EM410x to T5577 tag. This script changes
block 0. Additional data is written to block 3 and 4. The last
ELECTRA ID can be accessed through the option ---> "-c". For copy
directly from the original ELECTRA tag, ---> option "-e". For copy
from input, EM410X ID ---> option "-s". Next option for cloning simple
EM4102 ---> option "-m". If press <Enter> it, which writes an ID.
2024-07-15 12:42:08 +03:00
If press <n> ---> exit the script.
]]
example = [[
-------------------------------------------------------------------------------
--------------- cloning ELECTRA tag from input ID to T5577 tag ----------------
2024-07-21 16:19:21 +02:00
2024-07-15 12:42:08 +03:00
script run lf_electra -s 11AA22BB55
2024-07-21 16:19:21 +02:00
----------------- continue cloning from last cloned ELECTRA -------------------
2024-07-15 12:42:08 +03:00
script run lf_electra -c
2024-07-21 16:19:21 +02:00
2024-07-15 12:42:08 +03:00
---------------------- ELECTRA cloning from the original TAG -----------------
2024-07-21 16:19:21 +02:00
2024-07-15 12:42:08 +03:00
script run lf_electra -e
2024-07-21 16:19:21 +02:00
----------------------------- simple EM4102 cloning ---------------------------
2024-07-15 12:42:08 +03:00
script run lf_electra -m
2024-07-21 16:19:21 +02:00
2024-07-15 12:42:08 +03:00
-------------------------------------------------------------------------------
]]
usage = [[
script run lf_electra.lua [-e] [-h] [-c] [-m] [-s <ID HEX number>]
]]
arguments = [[
-h : this help
-c : continue cloning from last ID used
-s : ELECTRA - EM410x ID HEX number
-e : Read original ELECTRA from Proxmark3 device
-m : EM410x cloning
]]
--------------------------------------Path to logs files
local DEBUG = false
local dir = os.getenv ( 'HOME' ) .. '/.proxmark3/logs/'
local LAST_ID = os.getenv ( 'HOME' ) .. '/.proxmark3/logs/last_id.txt'
local ID_STATUS = ( io.popen ( 'dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:' ): read ( "*a" ): match "%C+" )
if not ID_STATUS then
error "No files in this directory"
end
-------------------------------------------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
------------------------------------------------- errors
local function oops ( err )
core.console ( 'clear' )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( ac.red .. ' ERROR:' .. ac.reset .. err )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
return nil , err
end
-----------------------------------------------sleep
local function sleep ( n )
os.execute ( "sleep " .. tonumber ( n ))
end
--------------------wait
function wait ( msec )
local t = os.clock ()
repeat
until os.clock () > t + msec * 1e-3
end
----------------------------------------------time wait
local function timer ( n )
while n > 0 do
io.write ( ac.cyan .. " ::::: " .. ac.yellow .. tonumber ( n ) .. ac.yellow .. " sec " .. ac.cyan .. "::::: \r " .. ac.reset )
sleep ( 1 )
io.flush ()
n = n - 1
end
end
----------------------------------------------------- help
local function help ()
core.console ( 'clear' )
print ( line )
print ( ac.cyan .. mod .. ac.reset )
print ( ac.cyan .. version .. ac.reset )
print ( ac.yellow .. desc .. ac.reset )
print ( line )
print ( ac.cyan .. ' Usage' .. ac.reset )
print ( usage )
print ( ac.cyan .. ' Arguments' .. ac.reset )
print ( arguments )
print ( line )
timer ( 30 )
core.console ( 'clear' )
print ( ac.cyan .. ' Example usage' .. ac.reset )
print ( example )
end
------------------------------------ Exit message
local function exitMsg ( msg )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( msg )
print ()
end
--------------------------------- idsearch EM ID
local function id ()
local f = assert ( io.open ( ID_STATUS , "r" ))
for line in f : lines () do
id = line : match "^%[%+%] EM 410x ID (%x+)"
if id then break end
end
f : close ()
local f = io.open ( ID_STATUS , "w+" )
f : write ( id )
f : close ()
local f = io.open ( ID_STATUS , "r" )
local t = f : read ( "*all" )
f : close ()
local hex_hi = tonumber ( t : sub ( 1 , 2 ), 16 )
local hex_low = tonumber ( t : sub ( 3 , 10 ), 16 )
return hex_hi , hex_low
end
---------------------------------------read file
local function readfile ()
local f = io.open ( ID_STATUS , "r" )
for line in f : lines () do
id = line : match "^(%x+)"
2025-07-10 11:52:39 +02:00
if id then break end
2024-07-15 12:42:08 +03:00
end
f : close ()
if not id then
return oops ( " ....No ID found in file" ) end
local f = io.open ( ID_STATUS , "r" )
local t = f : read ( "*all" )
f : close ()
local hex_hi = tonumber ( t : sub ( 1 , 2 ), 16 )
local hex_low = tonumber ( t : sub ( 3 , 10 ), 16 )
return hex_hi , hex_low
end
----------------------------------------last ID
local function IDsaved ()
local f = io.open ( LAST_ID , "r" )
for line in f : lines () do
id = line : match "^(%x+)"
2024-09-09 23:04:39 +02:00
if id then break end
2024-07-15 12:42:08 +03:00
end
f : close ()
if not id then
return oops ( " ....No ID found in file" ) end
local f = io.open ( LAST_ID , "r" )
local t = f : read ( "*all" )
f : close ()
local hex_hi = tonumber ( t : sub ( 1 , 2 ), 16 )
local hex_low = tonumber ( t : sub ( 3 , 10 ), 16 )
return hex_hi , hex_low
end
----------------------------------------write file
local function writefile ( hex_hi , hex_low )
local f = io.open ( ID_STATUS , "w+" )
2024-09-09 23:04:39 +02:00
local g = io.open ( LAST_ID , 'w+' )
2024-07-15 12:42:08 +03:00
f : write (( "%02X%08X \n " ): format ( hex_hi , hex_low ))
f : close ()
g : write (( "%02X%08X \n " ): format ( hex_hi , hex_low ))
g : close ()
print (( ' Saved EM410x ID ' .. ac.green .. '%02X%08X' .. ac.reset .. ' to TXT file:' ): format ( hex_hi , hex_low ))
print (( ac.yellow .. ' %s' .. ac.reset ): format ( LAST_ID ))
return true , 'Ok'
end
---------------replace line
local last_str = ''
function txt_change ( str )
io.write (( ' \b \b ' ): rep ( # last_str )) -- old line
io.write ( str ) -- new line
io.flush ()
last_str = str
end
---------------------------------------- main
local function main ( args )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ()
if # args == 0 then return help () end
local saved_id = false
local id_original = false
local emarine = false
local input_id = ''
2024-09-09 23:04:39 +02:00
for o , a in getopt.getopt ( args , 'hems:c' ) do
2024-07-15 12:42:08 +03:00
if o == 'h' then return help () end
if o == 'e' then id_original = true end
if o == 'm' then emarine = true end
if o == 's' then input_id = a end
if o == 'c' then saved_id = true end
end
--------------------check -id
2024-07-21 16:19:21 +02:00
if not saved_id and not id_original and not emarine then
2024-07-15 12:42:08 +03:00
if input_id == nil then return oops ( ' empty EM410x ID string' ) end
if # input_id == 0 then return oops ( ' empty EM410x ID string' ) end
if # input_id < 10 then return oops ( ' EM410x ID too short. Must be 5 hex bytes' ) end
if # input_id > 10 then return oops ( ' EM410x ID too long. Must be 5 hex bytes' ) end
end
core.console ( 'clear' )
print ( string.rep ( '--' , 39 ) )
print ( ac.green .. ' ....... OFF THE HINTS WILL BE LESS ON THE SCREEN' .. ac.reset )
print ( string.rep ( '--' , 39 ) )
core.console ( 'pref set hint --off' )
print ( string.rep ( '--' , 39 ) )
timer ( 4 )
core.console ( 'clear' )
local hi = tonumber ( input_id : sub ( 1 , 2 ), 16 )
local low = tonumber ( input_id : sub ( 3 , 10 ), 16 )
2024-09-09 23:04:39 +02:00
if saved_id then
2024-07-15 12:42:08 +03:00
hi , low = IDsaved ()
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( '' )
print ( ac.green .. ' ......Continue cloning from last saved ID' .. ac.reset )
print ( '' )
print ( string.rep ( '--' , 39 ) )
end
if id_original then
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( '' )
print ( ac.green .. ' Put the ELECTRA tag on the coil PM3 to read ' .. ac.reset )
print ( '' )
print ( string.rep ( '--' , 39 ))
print ( string.rep ( '--' , 39 ))
end
2024-09-09 23:04:39 +02:00
if emarine then
2024-07-15 12:42:08 +03:00
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( '' )
print ( ac.green .. ' Put the EM4102 tag on the coil PM3 to read ' .. ac.reset )
print ( '' )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
end
if emarine or id_original then
2024-09-09 23:04:39 +02:00
io.write ( ' Press' .. ac.yellow .. ' Enter' .. ac.reset .. ' to continue ... ' ); io.read ()
2024-07-15 12:42:08 +03:00
txt_change ( ' Readed TAG : ' )
core.console ( ' lf em 410x read' )
print ( string.rep ( '--' , 39 ) )
hi , low = id ()
timer ( 7 )
core.console ( 'clear' )
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( '' )
print ( ac.green .. ' Continuation of the cloning process....' .. ac.reset )
print ( '' )
print ( string.rep ( '--' , 39 ) )
end
if not emarine and not id_original and not saved_id then
print ( string.rep ( '--' , 39 ) )
print ( string.rep ( '--' , 39 ) )
print ( '' )
print ( ac.green .. ' ........ ELECTRA cloning from Entered EM-ELECTRA ID' .. ac.reset )
print ( '' )
print ( string.rep ( '--' , 39 ) )
end
2024-09-09 23:04:39 +02:00
if emarine then
2024-07-15 12:42:08 +03:00
d = ( 'EM4102 ID ' )
else
d = ( 'ELECTRA ID ' )
end
local template = (( d ) .. ac.green .. '%02X%08X' .. ac.reset )
for i = low , low + 100 , 1 do
local msg = ( template ): format ( hi , low )
print ( string.rep ( '--' , 39 ) )
if count > 0 then
print (( ' TAGs created: ' .. ac.green .. '%s' .. ac.reset ): format ( count ))
print ( string.rep ( '--' , 39 ) )
end
print (( ' %s >>>>>> cloning to ' .. ac.cyan .. 'T5577 -' .. ac.yellow .. ' Enter' .. ac.reset .. ' for yes or ' .. ac.yellow .. 'n' .. ac.reset .. ' for exit' ): format ( msg ))
print ( ' Before confirming the cloning operation, put a blank ' .. ac.cyan .. 'T5577' .. ac.reset .. ' tag on coil' .. ac.cyan .. ' PM3' .. ac.reset .. ' !' )
print ( string.rep ( '--' , 39 ) )
io.write ( ' Continue with this operation' .. ac.yellow .. ' (Enter/n)' .. ac.reset .. ' ? > ' )
answer = io.read ()
if answer == 'n' then
core.console ( 'clear' )
print ( string.rep ( '--' , 39 ) )
2025-06-19 20:26:07 +02:00
print ( ac.red .. ' Aborted via keyboard!' .. ac.reset )
2024-07-15 12:42:08 +03:00
print ( string.rep ( '--' , 39 ) )
break
end
core.console ( 'clear' )
print ( string.rep ( '--' , 39 ) )
if emarine then
core.console ( ( 'lf em 410x clone --id %02X%08X' ): format ( hi , low ) )
else
core.console ( ( 'lf em 410x clone --id %02X%08X' ): format ( hi , low ) )
core.console ( 'lf t55 write -b 0 -d 00148080' )
core.console ( 'lf t55 write -b 3 -d 7E1EAAAA' )
core.console ( 'lf t55 write -b 4 -d AAAAAAAA' )
end
count = count + 1
end
writefile ( hi , low )
core.console ( 'pref set hint --on' )
print ( string.rep ( '--' , 39 ) )
if count > 0 then
print (( ' TAGs created: ' .. ac.green .. '%s' .. ac.reset ): format ( count ))
print ( string.rep ( '--' , 39 ) )
end
end
main ( args )