Merge pull request #2799 from jareckib/patch-2

Update lf_t55xx_multiwriter.lua
This commit is contained in:
Iceman 2025-03-23 06:20:27 +01:00 committed by GitHub
commit 40830586fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -6,10 +6,14 @@ local dash = string.rep('--', 32)
local dir = os.getenv('HOME') .. '/.proxmark3/logs/' 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 logfile = (io.popen('dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:'):read("*a"):match("%C+"))
local command = core.console local command = core.console
local pm3 = require('pm3')
p = pm3.pm3()
command('clear') command('clear')
author = ' Author: jareckib - 12.03.2025' author = ' jareckib - 12.03.2025'
version = ' version v1.03' version = ' v1.06'
mod = ' 20.03.2025'
desc = [[ desc = [[
This simple script stores 1, 2 or 3 different EM4102 on a single T5577. 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. 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 The script can therefore be useful if the original EM4102 doesn't work but
@ -31,8 +35,9 @@ arguments = [[
local function help() local function help()
print() print()
print(author) print(ac.yellow..' Author:'..ac.reset..author)
print(version) print(ac.yellow..' Version:'..ac.reset..version)
print(ac.yellow..' Modification date:'..ac.reset..mod)
print(desc) print(desc)
print(ac.cyan .. ' Usage' .. ac.reset) print(ac.cyan .. ' Usage' .. ac.reset)
print(usage) print(usage)
@ -40,6 +45,25 @@ local function help()
print(arguments) print(arguments)
end end
local function sleep(n)
os.execute("sleep " ..tonumber(n))
end
function wait(msec)
local t = os.clock()
repeat
until os.clock() > t + msec * 1e-3
end
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
local function reset_log_file() local function reset_log_file()
local file = io.open(logfile, "w+") local file = io.open(logfile, "w+")
file:write("") file:write("")
@ -70,17 +94,14 @@ local function hex_to_bin(hex_value)
if not hex_value:match("^[A-Fa-f0-9]+$") or #hex_value ~= 10 then 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.") error("Invalid UID format. Must be a valid 5-byte HEX value.")
end end
local decimal_value = tonumber(hex_value, 16) local decimal_value = tonumber(hex_value, 16)
if not decimal_value then if not decimal_value then
error("Error: Invalid HEX conversion.") error("Error: Invalid HEX conversion.")
end end
local binary = "" local binary = ""
for i = 39, 0, -1 do for i = 39, 0, -1 do
binary = binary .. ((decimal_value & (1 << i)) ~= 0 and "1" or "0") binary = binary .. ((decimal_value & (1 << i)) ~= 0 and "1" or "0")
end end
if #binary ~= 40 then if #binary ~= 40 then
error("Unexpected UID length after conversion to binary.") error("Unexpected UID length after conversion to binary.")
end end
@ -95,13 +116,11 @@ local function encode_uid(uid)
local uid_bin = hex_to_bin(uid) local uid_bin = hex_to_bin(uid)
local start_bits = '1' .. string.rep('1', 8) local start_bits = '1' .. string.rep('1', 8)
local data_with_parity = '' local data_with_parity = ''
for i = 1, 40, 4 do for i = 1, 40, 4 do
local nibble = uid_bin:sub(i, i + 3) local nibble = uid_bin:sub(i, i + 3)
local parity_bit = even_parity(nibble) local parity_bit = even_parity(nibble)
data_with_parity = data_with_parity .. nibble .. parity_bit data_with_parity = data_with_parity .. nibble .. parity_bit
end end
local col_parity_bits = '' local col_parity_bits = ''
for i = 1, 4 do for i = 1, 4 do
local col_bits = '' local col_bits = ''
@ -110,10 +129,8 @@ local function encode_uid(uid)
end end
col_parity_bits = col_parity_bits .. even_parity(col_bits) col_parity_bits = col_parity_bits .. even_parity(col_bits)
end end
local stop_bit = '0' local stop_bit = '0'
local full_bin = start_bits .. data_with_parity .. col_parity_bits .. stop_bit local full_bin = start_bits .. data_with_parity .. col_parity_bits .. stop_bit
return string.format("%X", tonumber(full_bin, 2)) return string.format("%X", tonumber(full_bin, 2))
end end
@ -129,42 +146,36 @@ local function get_uid_from_user()
io.write(ac.yellow .. "Invalid choice. Please enter (1) or (2) " .. ac.reset) io.write(ac.yellow .. "Invalid choice. Please enter (1) or (2) " .. ac.reset)
end end
until choice == "1" or choice == "2" until choice == "1" or choice == "2"
if choice == "1" then if choice == "1" then
local format local format
repeat repeat
io.write("Choose format HEX or DEC (engraved ID) "..ac.cyan.."(h/d) "..ac.reset) io.write("Choose format HEX or DEC (engraved ID) "..ac.cyan.."(h/d) "..ac.reset)
format = io.read():lower() format = io.read():lower()
if format ~= "h" and format ~= "d" then if format ~= "h" and format ~= "d" then
print(ac.yellow .. "Invalid choice. Choose format HEX or DEC" .. ac.reset) print(ac.yellow .. "Invalid choice. Choose format HEX or DEC" .. ac.reset)
end end
until format == "h" or format == "d" until format == "h" or format == "d"
while true do while true do
io.write("Enter 10-character UID: "..ac.green) io.write("Enter 10-character UID: "..ac.green)
local uid = io.read():upper() local uid = io.read():upper()
if format == "h" and uid:match("^[A-F0-9]+$") and #uid == 10 then 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 return uid
elseif format == "d" and uid:match("^%d%d%d%d%d%d%d%d%d%d$") then elseif format == "d" and uid:match("^%d%d%d%d%d%d%d%d%d%d$") then
return string.format("%010X", tonumber(uid)) return string.format("%010X", tonumber(uid))
else else
print(ac.yellow .. "Invalid UID format. Please enter exactly 10 characters in selected format." .. ac.reset) print(ac.yellow .. "Invalid UID format. Enter exactly 10 characters in selected format." .. ac.reset)
end end
end end
elseif choice == "2" then elseif choice == "2" then
io.write("Place original FOB on coil for reading and press" ..ac.cyan.." Enter..." .. ac.reset) io.write("Place original FOB on coil for reading and press" ..ac.cyan.." Enter..." .. ac.reset)
io.read() io.read()
while true do while true do
reset_log_file() reset_log_file()
command('lf em 410x read') p:console('lf em 410x read')
local log_content = read_log_file(logfile) local log_content = read_log_file(logfile)
local uid = extract_uid(log_content) local uid = extract_uid(log_content)
if uid and #uid == 10 then if uid and #uid == 10 then
print("Readed EM4102 ID: " ..ac.green.. uid ..ac.reset)
return uid return uid
else else
io.write(ac.yellow .. "Error reading UID. Please adjust FOB position and press Enter..." .. ac.reset) io.write(ac.yellow .. "Error reading UID. Please adjust FOB position and press Enter..." .. ac.reset)
@ -175,33 +186,62 @@ local function get_uid_from_user()
end end
end end
local function verify_written_data(blocks, block0_value, uid_count)
reset_log_file()
p:console('lf t55 detect')
for i = 0, #blocks do
p:console('lf t55 read -b ' .. i)
end
local log_content = read_log_file(logfile)
local verified = true
local pattern_block0 = "%[%s*%+%]%s*00%s*|%s*([A-F0-9]+)"
local found_block0 = log_content:match(pattern_block0)
if not found_block0 or found_block0:upper() ~= block0_value:upper() then
print("Error in block 0 ...expected: " .. ac.green .. block0_value .. ac.reset .. " ...found: " .. ac.green .. (found_block0 or "N/A") .. ac.reset)
verified = false
end
for i = 1, #blocks do
local expected_block = blocks[i]
local pattern = "%[%s*%+%]%s*" .. string.format("%02X", i) .. " |%s*([A-F0-9]+)"
local found_block = log_content:match(pattern)
if not found_block or found_block:upper() ~= expected_block:upper() then
print("Error in block " .. i .. " ...expected: " .. ac.green .. expected_block .. ac.reset .. " ...found: " .. ac.green .. (found_block or "N/A") .. ac.reset)
verified = false
end
end
return verified
end
local function write(blocks, block0_value)
p:console('lf t55xx write -b 0 -d ' .. block0_value)
for i = 1, #blocks do
p:console('lf t55xx write -b ' .. i .. ' -d ' .. blocks[i])
end
end
local function main(args) local function main(args)
for o, a in getopt.getopt(args, 'h') do for o, a in getopt.getopt(args, 'h') do
if o == 'h' then return help() end if o == 'h' then
return help()
end
end end
local blocks = {} local blocks = {}
local uid_count = 0 local uid_count = 0
for i = 1, 3 do for i = 1, 3 do
local uid = get_uid_from_user() local uid = get_uid_from_user()
local encoded_hex = encode_uid(uid) local encoded_hex = encode_uid(uid)
blocks[#blocks + 1] = encoded_hex:sub(1, 8) blocks[#blocks + 1] = encoded_hex:sub(1, 8)
blocks[#blocks + 1] = encoded_hex:sub(9, 16) blocks[#blocks + 1] = encoded_hex:sub(9, 16)
uid_count = uid_count + 1 uid_count = uid_count + 1
if i < 3 then if i < 3 then
local next_choice local next_choice
repeat repeat
io.write(ac.reset.."Do you want to add another UID? "..ac.cyan.."(y/n) "..ac.reset) io.write(ac.reset.."Do you want to add another UID? "..ac.cyan.."(y/n) "..ac.reset)
next_choice = io.read():lower() next_choice = io.read():lower()
if next_choice ~= "y" and next_choice ~= "n" then 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) print(ac.yellow .. "Invalid choice. Please enter (y) for yes or (n) for no." .. ac.reset)
end end
until next_choice == "y" or next_choice == "n" until next_choice == "y" or next_choice == "n"
if next_choice == "y" then if next_choice == "y" then
print(dash) print(dash)
print(ac.yellow .. (i == 1 and "::: Second UID :::" or "::: Third UID :::") .. ac.reset) print(ac.yellow .. (i == 1 and "::: Second UID :::" or "::: Third UID :::") .. ac.reset)
@ -210,18 +250,22 @@ local function main(args)
end end
end end
end end
local block0_value = (uid_count == 1) and "00148040" or (uid_count == 2) and "00148080" or "001480C0" local block0_value = (uid_count == 1) and "00148040" or (uid_count == 2) and "00148080" or "001480C0"
io.write("Place the " .. ac.cyan .. "T5577" .. ac.reset .. " tag on the coil for writing and press " .. ac.cyan .. "Enter..." .. ac.reset)
io.write("Place "..ac.cyan.."T5577"..ac.reset.." tag on coil for writing and press"..ac.cyan.." Enter..."..ac.reset)
io.read() io.read()
write(blocks, block0_value)
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(dash)
print(ac.green .. "Successfully written " .. uid_count .. " EM4102 UID(s) to T5577" .. ac.reset) timer(3)
local verified = verify_written_data(blocks, block0_value, uid_count)
while not verified do
print("Verification failed." .. ac.reset .. " Please adjust the " .. ac.cyan .. "T5577" .. ac.reset .. " position and try again.")
io.write("Press " .. ac.cyan .. "Enter" .. ac.reset .. " to retry...")
io.read()
write(blocks, block0_value)
timer(3)
verified = verify_written_data(blocks, block0_value, uid_count)
end
print(ac.green .. "Successfully written " .. ac.reset .. uid_count .. ac.green .. " EM4102 UID(s) to T5577" .. ac.reset)
end end
main(args) main(args)