mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-24 07:05:40 -07:00
lf_t55xx_multiwriter.lua v1.06
Fix verification block 0 Signed-off-by: Jarek Barwinski <116510448+jareckib@users.noreply.github.com>
This commit is contained in:
parent
c5dd239de5
commit
30a29f2ff3
1 changed files with 29 additions and 52 deletions
|
@ -9,10 +9,11 @@ local command = core.console
|
||||||
local pm3 = require('pm3')
|
local pm3 = require('pm3')
|
||||||
p = pm3.pm3()
|
p = pm3.pm3()
|
||||||
command('clear')
|
command('clear')
|
||||||
author = ' Author: jareckib - 12.03.2025'
|
author = ' jareckib - 12.03.2025'
|
||||||
version = ' version v1.05'
|
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
|
||||||
|
@ -34,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)
|
||||||
|
@ -92,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
|
||||||
|
@ -117,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 = ''
|
||||||
|
@ -132,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
|
||||||
|
|
||||||
|
@ -151,41 +146,34 @@ 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()
|
||||||
p:console('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)
|
print("Readed EM4102 ID: " ..ac.green.. uid ..ac.reset)
|
||||||
return uid
|
return uid
|
||||||
|
@ -198,73 +186,62 @@ local function get_uid_from_user()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function verify_written_data(blocks, block0_value)
|
local function verify_written_data(blocks, block0_value, uid_count)
|
||||||
reset_log_file()
|
reset_log_file()
|
||||||
local block0_value = (uid_count == 1) and "00148040" or (uid_count == 2) and "00148080" or "001480C0"
|
|
||||||
p:console('lf t55 detect')
|
p:console('lf t55 detect')
|
||||||
for i = 0, #blocks do
|
for i = 0, #blocks do
|
||||||
p:console('lf t55 read -b ' .. i)
|
p:console('lf t55 read -b ' .. i)
|
||||||
end
|
end
|
||||||
local log_content = read_log_file(logfile)
|
local log_content = read_log_file(logfile)
|
||||||
local verified = true
|
local verified = true
|
||||||
local pattern_block0 = "%[%s*%+%]%s*00 |%s*([A-F0-9]+)"
|
local pattern_block0 = "%[%s*%+%]%s*00%s*|%s*([A-F0-9]+)"
|
||||||
local found_block0 = log_content:match(pattern_block0)
|
local found_block0 = log_content:match(pattern_block0)
|
||||||
|
|
||||||
if not found_block0 or found_block0:upper() ~= block0_value:upper() then
|
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)
|
print("Error in block 0 ...expected: " .. ac.green .. block0_value .. ac.reset .. " ...found: " .. ac.green .. (found_block0 or "N/A") .. ac.reset)
|
||||||
verified = false
|
verified = false
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, #blocks do
|
for i = 1, #blocks do
|
||||||
local expected_block = blocks[i]
|
local expected_block = blocks[i]
|
||||||
local pattern = "%[%s*%+%]%s*" .. string.format("%02X", i) .. " |%s*([A-F0-9]+)"
|
local pattern = "%[%s*%+%]%s*" .. string.format("%02X", i) .. " |%s*([A-F0-9]+)"
|
||||||
local found_block = log_content:match(pattern)
|
local found_block = log_content:match(pattern)
|
||||||
|
|
||||||
if not found_block or found_block:upper() ~= expected_block:upper() then
|
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)
|
print("Error in block " .. i .. " ...expected: " .. ac.green .. expected_block .. ac.reset .. " ...found: " .. ac.green .. (found_block or "N/A") .. ac.reset)
|
||||||
verified = false
|
verified = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return verified
|
return verified
|
||||||
end
|
end
|
||||||
|
|
||||||
local function write(blocks)
|
local function write(blocks, block0_value)
|
||||||
local block0_value = (uid_count == 1) and "00148040" or (uid_count == 2) and "00148080" or "001480C0"
|
|
||||||
p:console('lf t55xx write -b 0 -d ' .. block0_value)
|
p:console('lf t55xx write -b 0 -d ' .. block0_value)
|
||||||
for i = 1, #blocks do
|
for i = 1, #blocks do
|
||||||
|
|
||||||
p:console('lf t55xx write -b ' .. i .. ' -d ' .. blocks[i])
|
p:console('lf t55xx write -b ' .. i .. ' -d ' .. blocks[i])
|
||||||
end
|
end
|
||||||
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)
|
||||||
|
@ -273,22 +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"
|
||||||
io.write("Place "..ac.cyan.."T5577"..ac.reset.." tag on coil for writing and press"..ac.cyan.." Enter..."..ac.reset)
|
io.write("Place the " .. ac.cyan .. "T5577" .. ac.reset .. " tag on the coil for writing and press " .. ac.cyan .. "Enter..." .. ac.reset)
|
||||||
io.read()
|
io.read()
|
||||||
write(blocks)
|
write(blocks, block0_value)
|
||||||
print(dash)
|
print(dash)
|
||||||
timer(3)
|
timer(3)
|
||||||
local verified = verify_written_data(blocks, block0_value)
|
local verified = verify_written_data(blocks, block0_value, uid_count)
|
||||||
while not verified do
|
while not verified do
|
||||||
print("Verification failed. Please correct the"..ac.cyan.." T5577"..ac.reset.." position and try again.")
|
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.write("Press " .. ac.cyan .. "Enter" .. ac.reset .. " to retry...")
|
||||||
io.read()
|
io.read()
|
||||||
write(blocks)
|
write(blocks, block0_value)
|
||||||
timer(3)
|
timer(3)
|
||||||
verified = verify_written_data(blocks)
|
verified = verify_written_data(blocks, block0_value, uid_count)
|
||||||
end
|
end
|
||||||
print(ac.green .. "Successfully written " ..ac.reset.. uid_count .. ac.green.." EM4102 UID(s) to T5577" .. ac.reset)
|
print(ac.green .. "Successfully written " .. ac.reset .. uid_count .. ac.green .. " EM4102 UID(s) to T5577" .. ac.reset)
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
Loading…
Add table
Add a link
Reference in a new issue