From ca9f4341105e86619b50a516887b73ccf5c69f46 Mon Sep 17 00:00:00 2001 From: Jarek Barwinski <116510448+jareckib@users.noreply.github.com> Date: Fri, 31 Jan 2025 13:32:43 +0000 Subject: [PATCH] Delete client/luascripts/paxton_clone.lua.txt Signed-off-by: Jarek Barwinski <116510448+jareckib@users.noreply.github.com> --- client/luascripts/paxton_clone.lua.txt | 423 ------------------------- 1 file changed, 423 deletions(-) delete mode 100644 client/luascripts/paxton_clone.lua.txt diff --git a/client/luascripts/paxton_clone.lua.txt b/client/luascripts/paxton_clone.lua.txt deleted file mode 100644 index daa7df38b..000000000 --- a/client/luascripts/paxton_clone.lua.txt +++ /dev/null @@ -1,423 +0,0 @@ --------------------------------------------------------------------- --- Author - jareckib - 30.01.2025 --- Based on Equipter's tutorial - Downgrade Paxton to EM4102 --- version v 1.14 ---------------------------------------------------------------------- -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 log_file_path = dir .. "Paxton_log.txt" -local nam = "" -local command = core.console - -local function read_log_file(logfile) - local file = io.open(logfile, "r") - if not file then - error(" Could not open the file") - end - local content = file:read("*all") - file:close() - return content -end - -local function parse_blocks(result) - local blocks = {} - for line in result:gmatch("[^\r\n]+") do - local block_num, block_data = line:match("%[%=%]%s+%d/0x0([4-7])%s+%|%s+([0-9A-F ]+)") - if block_num and block_data then - block_num = tonumber(block_num) - block_data = block_data:gsub("%s+", "") - blocks[block_num] = block_data - end - end - return blocks -end - -local function hex_to_bin(hex_string) - local bin_string = "" - local hex_to_bin_map = { - ['0'] = "0000", ['1'] = "0001", ['2'] = "0010", ['3'] = "0011", - ['4'] = "0100", ['5'] = "0101", ['6'] = "0110", ['7'] = "0111", - ['8'] = "1000", ['9'] = "1001", ['A'] = "1010", ['B'] = "1011", - ['C'] = "1100", ['D'] = "1101", ['E'] = "1110", ['F'] = "1111" - } - for i = 1, #hex_string do - bin_string = bin_string .. hex_to_bin_map[hex_string:sub(i, i)] - end - return bin_string -end - -local function remove_last_two_bits(binary_str) - return binary_str:sub(1, #binary_str - 2) -end - -local function split_into_5bit_chunks(binary_str) - local chunks = {} - for i = 1, #binary_str, 5 do - table.insert(chunks, binary_str:sub(i, i + 4)) - end - return chunks -end - -local function remove_parity_bit(chunks) - local no_parity_chunks = {} - for _, chunk in ipairs(chunks) do - if #chunk == 5 then - table.insert(no_parity_chunks, chunk:sub(2)) - end - end - return no_parity_chunks -end - -local function convert_to_hex(chunks) - local hex_values = {} - for _, chunk in ipairs(chunks) do - if #chunk > 0 then - table.insert(hex_values, string.format("%X", tonumber(chunk, 2))) - end - end - return hex_values -end - -local function convert_to_decimal(chunks) - local decimal_values = {} - for _, chunk in ipairs(chunks) do - table.insert(decimal_values, tonumber(chunk, 2)) - end - return decimal_values -end - -local function find_until_before_f(hex_values) - local result = {} - for _, value in ipairs(hex_values) do - if value == 'F' then - break - end - table.insert(result, value) - end - return result -end - -local function process_block(block) - local binary_str = hex_to_bin(block) - binary_str = remove_last_two_bits(binary_str) - local chunks = split_into_5bit_chunks(binary_str) - local no_parity_chunks = remove_parity_bit(chunks) - return no_parity_chunks -end - -local function calculate_id_net(blocks) - local all_hex_values = {} - for _, block in ipairs(blocks) do - local hex_values = convert_to_hex(process_block(block)) - for _, hex in ipairs(hex_values) do - table.insert(all_hex_values, hex) - end - end - local selected_hex_values = find_until_before_f(all_hex_values) - if #selected_hex_values == 0 then - error(ac.red..' Error: '..ac.reset..'No valid data found in blocks 4 and 5') - end - local combined_hex = table.concat(selected_hex_values) - if not combined_hex:match("^%x+$") then - error(ac.red..' Error: '..ac.reset..'Invalid data in blocks 4 and 5') - end - local decimal_id = tonumber(combined_hex) - local stripped_hex_id = string.format("%X", decimal_id) - local padded_hex_id = string.format("%010X", decimal_id) - return decimal_id, padded_hex_id -end - -local function calculate_id_switch(blocks) - local all_decimal_values = {} - for _, block in ipairs(blocks) do - local decimal_values = convert_to_decimal(process_block(block)) - for _, dec in ipairs(decimal_values) do - table.insert(all_decimal_values, dec) - end - end - if #all_decimal_values < 15 then - error(ac.red..' Error:'..ac.reset..' Not enough data after processing blocks 4, 5, 6, and 7') - end - local id_positions = {9, 11, 13, 15, 2, 4, 6, 8} - local id_numbers = {} - for _, pos in ipairs(id_positions) do - table.insert(id_numbers, all_decimal_values[pos]) - end - local decimal_id = tonumber(table.concat(id_numbers)) - local padded_hex_id = string.format("%010X", decimal_id) - return decimal_id, padded_hex_id -end - -local function name_exists_in_log(name) - local file = io.open(log_file_path, "r") - if not file then - return false - end - local pattern = "^Name:%s*" .. name .. "%s*$" - for line in file:lines() do - if line:match(pattern) then - file:close() - return true - end - end - file:close() - return false -end - -local function log_result(blocks, em410_id, name) - local log_file = io.open(log_file_path, "a") - if log_file then - log_file:write("Name: " .. name .. "\n") - log_file:write("Date: ", os.date("%Y-%m-%d %H:%M:%S"), "\n") - for i = 4, 7 do - log_file:write(string.format("Block %d: %s\n", i, blocks[i] or "nil")) - end - log_file:write(string.format('EM4102 ID: %s\n', em410_id or "nil")) - log_file:write('--------------------------\n') - log_file:close() - print(' Log saved as: pm3/.proxmark3/logs/' ..ac.yellow..' Paxton_log.txt'..ac.reset) - else - print(" Failed to open log file for writing.") - end -end - -local function handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3) - while true do - print(" Create Paxton choose " .. ac.cyan .. "1" .. ac.reset .. " or EM4102 choose " .. ac.cyan .. "2" .. ac.reset) - print(dash) - io.write(" Your choice "..ac.cyan.."(1/2): "..ac.reset) - local choice = io.read() - if choice == "1" then - print(dash) - print(" Place the" .. ac.cyan .. " Paxton " .. ac.reset .. "Fob on the coil to write.." .. ac.green .. " ENTER " .. ac.reset .. "to continue..") - io.read() - print(dash) - command("lf hitag wrbl --ht2 -p 4 -d " .. blocks[4] .. " -k BDF5E846") - command("lf hitag wrbl --ht2 -p 5 -d " .. blocks[5] .. " -k BDF5E846") - command("lf hitag wrbl --ht2 -p 6 -d " .. blocks[6] .. " -k BDF5E846") - command("lf hitag wrbl --ht2 -p 7 -d " .. blocks[7] .. " -k BDF5E846") - elseif choice == "2" then - print(dash) - print(" Place the" .. ac.cyan .. " T5577 " .. ac.reset .. "tag on the coil and press" .. ac.green .. " ENTER " .. ac.reset .. "to continue..") - io.read() - print(dash) - command("lf em 410x clone --id " .. padded_hex_id) - else - print(ac.yellow .. " Invalid choice." .. ac.reset .. " Please enter " .. ac.cyan .. "1" .. ac.reset .. " or " .. ac.cyan .. "2" .. ac.reset) - goto ask_again - end - while true do - print(dash) - io.write(" Make next RFID Fob"..ac.cyan.." (y/n)"..ac.reset.." > "..ac.yellow) - local another = io.read() - io.write(ac.reset..'') - if another:lower() == "n" then - if was_option_3 then - print(" No writing to Paxton_log.txt - Name: " ..ac.green.. nam .. ac.reset.. " exist") - return - end - print() - print(ac.green .. " Saving Paxton_log file..." .. ac.reset) - while true do - io.write(" Enter a name for database (cannot be empty/duplicate): "..ac.yellow) - name = io.read() - io.write(ac.reset..'') - if name == nil or name:match("^%s*$") then - print(ac.red .. ' ERROR:'..ac.reset..' Name cannot be empty.') - else - if name_exists_in_log(name) then - print(ac.yellow .. ' Name exists!!! '..ac.reset.. 'Please choose a different name.') - else - break - end - end - end - log_result(blocks, padded_hex_id, name) - print(ac.green .. " Log saved successfully!" .. ac.reset) - local file = io.open(logfile, "w+") - file:write("") - file:close() - return - elseif another:lower() == "y" then - goto ask_again - else - print(ac.yellow.." Invalid response."..ac.reset.." Please enter"..ac.cyan.." y"..ac.reset.." or"..ac.cyan.." n"..ac.reset) - end - end - ::ask_again:: - end -end - -local function is_valid_hex(input) - return #input == 8 and input:match("^[0-9A-Fa-f]+$") -end - -local function main() - while true do - command('clear') - print() - print(dash) - local input_option - print(ac.green .. ' Select option: ' .. ac.reset) - print(ac.cyan .. ' 1' .. ac.reset .. ' - Read Paxton blocks 4-7 to make a copy') - print(ac.cyan .. ' 2' .. ac.reset .. ' - Manually input data for Paxton blocks 4-7') - print(ac.cyan .. " 3" .. ac.reset .. " - Search in Paxton_log by name and use the data") - print(dash) - while true do - io.write(' Your choice '..ac.cyan..'(1/2/3): ' .. ac.reset) - input_option = io.read() - if input_option == "1" or input_option == "2" or input_option == "3" then - break - else - print(ac.yellow .. ' Invalid choice.' .. ac.reset .. ' Please enter ' .. ac.cyan .. '1' .. ac.reset .. ' or ' .. ac.cyan .. '2' .. ac.reset..' or'..ac.cyan..' 3'..ac.reset) - end - end - local was_option_3 = false - if input_option == "1" then - local show_place_message = true - while true do - if show_place_message then - print(' Place the' .. ac.cyan .. ' Paxton' .. ac.reset .. ' Fob on the coil to read..' .. ac.green .. 'ENTER' .. ac.reset .. ' to continue..') - print(dash) - end - io.read() - command('lf hitag read --ht2 -k BDF5E846') - command('clear') - if not logfile then - error(" No files in this directory") - end - local result = read_log_file(logfile) - local blocks = parse_blocks(result) - local empty_block = false - for i = 4, 7 do - if not blocks[i] then - empty_block = true - break - end - end - if empty_block then - print(dash) - print(ac.yellow .. ' Adjust the Fob position on the coil.' .. ac.reset .. ' Press' .. ac.green .. ' ENTER' .. ac.reset .. ' to continue..') - print(dash) - show_place_message = false - else - print(dash) - for i = 4, 7 do - if blocks[i] then - print(string.format(" Block %d: %s%s%s", i, ac.yellow, blocks[i], ac.reset)) - end - end - local decimal_id, padded_hex_id - if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then - print(dash) - print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset) - decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]}) - else - print(dash) - print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset) - decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]}) - end - print(dash) - print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset)) - print(dash) - handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3) - break - end - end - elseif input_option == "2" then - local blocks = {} - for i = 4, 7 do - while true do - io.write(ac.reset..' Enter data for block ' .. i .. ': ' .. ac.yellow) - local input = io.read() - input = input:upper() - if is_valid_hex(input) then - blocks[i] = input - break - else - print(ac.yellow .. ' Invalid input.' .. ac.reset .. ' Each block must be 4 bytes (8 hex characters).') - end - end - end - local decimal_id, padded_hex_id - if blocks[5] and (blocks[5]:sub(4, 4) == 'F' or blocks[5]:sub(4, 4) == 'f') then - print(ac.reset.. dash) - print(' Identified Paxton ' .. ac.cyan .. 'Net2' .. ac.reset) - decimal_id, padded_hex_id = calculate_id_net({blocks[4], blocks[5]}) - else - print(ac.reset.. dash) - print(' Identified Paxton ' .. ac.cyan .. 'Switch2' .. ac.reset) - decimal_id, padded_hex_id = calculate_id_switch({blocks[4], blocks[5], blocks[6], blocks[7]}) - end - print(dash) - print(string.format(" ID for EM4102 is: %s", ac.green .. padded_hex_id .. ac.reset)) - print(dash) - if not padded_hex_id then - print(ac.red..' ERROR: '..ac.reset.. 'Invalid block data provided') - return - end - handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3) - break - elseif input_option == "3" then - was_option_3 = true - local retries = 0 - while retries < 3 do - io.write(" Enter the name to search (3 attempts) : "..ac.yellow) - local user_input = io.read() - io.write(ac.reset..'') - local name_clean = "^Name:%s*" .. user_input:gsub("%s", "%%s") .. "%s*$" - local file = io.open(log_file_path, "r") - if not file then - print(ac.red .. ' Error:'..ac.reset.. 'Could not open log file.') - return - end - local lines = {} - for line in file:lines() do - table.insert(lines, line) - end - file:close() - local found = false - for i = 1, #lines do - if lines[i]:match(name_clean) then - nam = user_input - local blocks = { - [4] = lines[i + 2]:match("Block 4: (.+)"), - [5] = lines[i + 3]:match("Block 5: (.+)"), - [6] = lines[i + 4]:match("Block 6: (.+)"), - [7] = lines[i + 5]:match("Block 7: (.+)") - } - local em4102_id = lines[i + 6]:match("EM4102 ID: (.+)") - print(dash) - for j = 4, 7 do - print(string.format(" Block %d: %s%s%s", j, ac.yellow, blocks[j] or "N/A", ac.reset)) - end - print(" EM4102 ID: " .. ac.green .. (em4102_id or "N/A") .. ac.reset) - print(dash) - local decimal_id, padded_hex_id = em4102_id, em4102_id - handle_cloning(decimal_id, padded_hex_id, blocks, was_option_3, nam) - found = true - break - end - end - if not found then - retries = retries + 1 - else - break - end - end - if retries == 3 then - print(ac.yellow .. " Name not found after 3 attempts." .. ac.reset) - end - end - print(dash) - print(' Exiting script Lua...') - return - end -end - -main() \ No newline at end of file