mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
lf_t55xx_multiwriter
This simple script stores 1, 2 or 3 different EM4102 on a single T5577. There is an option to enter the number engraved on the fob in decimal form. The script can therefore be useful if the original EM4102 doesn't work but has an engraved ID number. By entering such an ID as a single EM4102, we can create a working copy of our damaged fob. A tag T5577 created in this way works with the following USB readers: - ACM08Y - ACM26C - Sycreader R60D - Elatech Multitech TWN4 Signed-off-by: Jarek Barwinski <116510448+jareckib@users.noreply.github.com>
This commit is contained in:
parent
70ca100e29
commit
b3e5c037e5
1 changed files with 227 additions and 0 deletions
227
client/luascripts/lf_t55xx_multiwriter.lua
Normal file
227
client/luascripts/lf_t55xx_multiwriter.lua
Normal file
|
@ -0,0 +1,227 @@
|
|||
local getopt = require('getopt')
|
||||
local utils = require('utils')
|
||||
local ac = require('ansicolors')
|
||||
local os = require('os')
|
||||
local dash = string.rep('--', 32)
|
||||
local dir = os.getenv('HOME') .. '/.proxmark3/logs/'
|
||||
local logfile = (io.popen('dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:'):read("*a"):match("%C+"))
|
||||
local command = core.console
|
||||
command('clear')
|
||||
author = ' Author: jareckib - 12.03.2025'
|
||||
version = ' version v1.03'
|
||||
desc = [[
|
||||
This simple script stores 1, 2 or 3 different EM4102 on a single T5577.
|
||||
There is an option to enter the number engraved on the fob in decimal form.
|
||||
The script can therefore be useful if the original EM4102 doesn't work but
|
||||
has an engraved ID number. By entering such an ID as a single EM4102, we
|
||||
can create a working copy of our damaged fob.
|
||||
A tag T5577 created in this way works with the following USB readers:
|
||||
|
||||
- ACM08Y
|
||||
- ACM26C
|
||||
- Sycreader R60D
|
||||
- Elatech Multitech TWN4
|
||||
]]
|
||||
usage = [[
|
||||
script run lf_t55xx_multiwriter
|
||||
]]
|
||||
arguments = [[
|
||||
script run lf_t55xx_multiwriter -h : this help
|
||||
]]
|
||||
|
||||
local function help()
|
||||
print()
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ac.cyan .. ' Usage' .. ac.reset)
|
||||
print(usage)
|
||||
print(ac.cyan .. ' Arguments' .. ac.reset)
|
||||
print(arguments)
|
||||
end
|
||||
|
||||
local function reset_log_file()
|
||||
local file = io.open(logfile, "w+")
|
||||
file:write("")
|
||||
file:close()
|
||||
end
|
||||
|
||||
local function read_log_file(logfile)
|
||||
local file = io.open(logfile, "r")
|
||||
if not file then
|
||||
return nil
|
||||
end
|
||||
local content = file:read("*all")
|
||||
file:close()
|
||||
return content
|
||||
end
|
||||
|
||||
local function extract_uid(log_content)
|
||||
for line in log_content:gmatch("[^\r\n]+") do
|
||||
local uid = line:match("%[%s*%+%]%s*EM%s*410x%s*ID%s*([A-F0-9]+)")
|
||||
if uid then
|
||||
return uid
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function hex_to_bin(hex_value)
|
||||
if not hex_value:match("^[A-Fa-f0-9]+$") or #hex_value ~= 10 then
|
||||
error("Invalid UID format. Must be a valid 5-byte HEX value.")
|
||||
end
|
||||
|
||||
local decimal_value = tonumber(hex_value, 16)
|
||||
if not decimal_value then
|
||||
error("Error: Invalid HEX conversion.")
|
||||
end
|
||||
|
||||
local binary = ""
|
||||
for i = 39, 0, -1 do
|
||||
binary = binary .. ((decimal_value & (1 << i)) ~= 0 and "1" or "0")
|
||||
end
|
||||
|
||||
if #binary ~= 40 then
|
||||
error("Unexpected UID length after conversion to binary.")
|
||||
end
|
||||
return binary
|
||||
end
|
||||
|
||||
local function even_parity(bits)
|
||||
return (bits:gsub("0", ""):len() % 2 == 0) and "0" or "1"
|
||||
end
|
||||
|
||||
local function encode_uid(uid)
|
||||
local uid_bin = hex_to_bin(uid)
|
||||
local start_bits = '1' .. string.rep('1', 8)
|
||||
local data_with_parity = ''
|
||||
|
||||
for i = 1, 40, 4 do
|
||||
local nibble = uid_bin:sub(i, i + 3)
|
||||
local parity_bit = even_parity(nibble)
|
||||
data_with_parity = data_with_parity .. nibble .. parity_bit
|
||||
end
|
||||
|
||||
local col_parity_bits = ''
|
||||
for i = 1, 4 do
|
||||
local col_bits = ''
|
||||
for j = i, #data_with_parity, 5 do
|
||||
col_bits = col_bits .. data_with_parity:sub(j, j)
|
||||
end
|
||||
col_parity_bits = col_parity_bits .. even_parity(col_bits)
|
||||
end
|
||||
|
||||
local stop_bit = '0'
|
||||
local full_bin = start_bits .. data_with_parity .. col_parity_bits .. stop_bit
|
||||
|
||||
return string.format("%X", tonumber(full_bin, 2))
|
||||
end
|
||||
|
||||
local function get_uid_from_user()
|
||||
while true do
|
||||
print(dash)
|
||||
io.write(ac.cyan .. '(1)' .. ac.reset .. ' Manual entry UID |' .. ac.cyan .. ' (2)' .. ac.reset .. ' Read via Proxmark3 ')
|
||||
|
||||
local choice
|
||||
repeat
|
||||
choice = io.read()
|
||||
if choice ~= "1" and choice ~= "2" then
|
||||
io.write(ac.yellow .. "Invalid choice. Please enter (1) or (2) " .. ac.reset)
|
||||
end
|
||||
until choice == "1" or choice == "2"
|
||||
|
||||
if choice == "1" then
|
||||
local format
|
||||
repeat
|
||||
io.write("Choose format HEX or DEC (engraved ID) "..ac.cyan.."(h/d) "..ac.reset)
|
||||
format = io.read():lower()
|
||||
|
||||
if format ~= "h" and format ~= "d" then
|
||||
print(ac.yellow .. "Invalid choice. Choose format HEX or DEC" .. ac.reset)
|
||||
end
|
||||
until format == "h" or format == "d"
|
||||
|
||||
while true do
|
||||
io.write("Enter 10-character UID: "..ac.green)
|
||||
local uid = io.read():upper()
|
||||
|
||||
if format == "h" and uid:match("^[A-F0-9]+$") and #uid == 10 then
|
||||
print(ac.reset.."Entered UID: " ..ac.green.. uid .. ac.reset)
|
||||
return uid
|
||||
elseif format == "d" and uid:match("^%d%d%d%d%d%d%d%d%d%d$") then
|
||||
return string.format("%010X", tonumber(uid))
|
||||
else
|
||||
print(ac.yellow .. "Invalid UID format. Please enter exactly 10 characters in selected format." .. ac.reset)
|
||||
end
|
||||
end
|
||||
elseif choice == "2" then
|
||||
io.write("Place original FOB on coil for reading and press" ..ac.cyan.." Enter..." .. ac.reset)
|
||||
io.read()
|
||||
|
||||
while true do
|
||||
reset_log_file()
|
||||
command('lf em 410x read')
|
||||
local log_content = read_log_file(logfile)
|
||||
local uid = extract_uid(log_content)
|
||||
|
||||
if uid and #uid == 10 then
|
||||
return uid
|
||||
else
|
||||
io.write(ac.yellow .. "Error reading UID. Please adjust FOB position and press Enter..." .. ac.reset)
|
||||
io.read()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
for o, a in getopt.getopt(args, 'h') do
|
||||
if o == 'h' then return help() end
|
||||
end
|
||||
local blocks = {}
|
||||
local uid_count = 0
|
||||
|
||||
for i = 1, 3 do
|
||||
local uid = get_uid_from_user()
|
||||
local encoded_hex = encode_uid(uid)
|
||||
|
||||
blocks[#blocks + 1] = encoded_hex:sub(1, 8)
|
||||
blocks[#blocks + 1] = encoded_hex:sub(9, 16)
|
||||
|
||||
uid_count = uid_count + 1
|
||||
|
||||
if i < 3 then
|
||||
local next_choice
|
||||
repeat
|
||||
io.write(ac.reset.."Do you want to add another UID? "..ac.cyan.."(y/n) "..ac.reset)
|
||||
next_choice = io.read():lower()
|
||||
|
||||
if next_choice ~= "y" and next_choice ~= "n" then
|
||||
print(ac.yellow .. "Invalid choice. Please enter (y) for yes or (n) for no." .. ac.reset)
|
||||
end
|
||||
until next_choice == "y" or next_choice == "n"
|
||||
|
||||
if next_choice == "y" then
|
||||
print(dash)
|
||||
print(ac.yellow .. (i == 1 and "::: Second UID :::" or "::: Third UID :::") .. ac.reset)
|
||||
elseif next_choice == "n" then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local block0_value = (uid_count == 1) and "00148040" or (uid_count == 2) and "00148080" or "001480C0"
|
||||
|
||||
io.write("Place "..ac.cyan.."T5577"..ac.reset.." tag on coil for writing and press"..ac.cyan.." Enter..."..ac.reset)
|
||||
io.read()
|
||||
|
||||
command('lf t55xx write -b 0 -d ' .. block0_value)
|
||||
for i = 1, #blocks do
|
||||
command('lf t55xx write -b ' .. i .. ' -d ' .. blocks[i])
|
||||
end
|
||||
print(dash)
|
||||
print(ac.green .. "Successfully written " .. uid_count .. " EM4102 UID(s) to T5577" .. ac.reset)
|
||||
end
|
||||
|
||||
main(args)
|
Loading…
Add table
Add a link
Reference in a new issue