From c46d22d38fad7c036a89acdb79cf0111596ae592 Mon Sep 17 00:00:00 2001 From: Winds Date: Thu, 23 Apr 2020 20:26:28 +0200 Subject: [PATCH 1/2] Moving mfc_gen3_writer.lua to a branch till it becomes useable --- client/luascripts/mfc_gen3_writer.lua | 390 ++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 client/luascripts/mfc_gen3_writer.lua diff --git a/client/luascripts/mfc_gen3_writer.lua b/client/luascripts/mfc_gen3_writer.lua new file mode 100644 index 000000000..5222c0d39 --- /dev/null +++ b/client/luascripts/mfc_gen3_writer.lua @@ -0,0 +1,390 @@ +local utils = require('utils') +local getopt = require('getopt') +local cmds = require('commands') +local read14a = require('read14a') +-- +--- +------------------------------- +-- Notes +------------------------------- +--- +-- +--[[ +---Suggestions of improvement: +--- Add support another types of dumps: BIN, JSON +--- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager. +--- Add undependence from the operation system. At the moment code not working in Linux. +--- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) +--- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% + +-- iceman notes: +-- doesn't take consideration filepaths for dump files. +-- doesn't allow A keys for authenticating when writing +-- doesn't verify that card is magic gen3. +-- doesn't take several versions of same dump ( -1, -2, -3 ) styles. +--]] +-- +--- +------------------------------- +-- Script hat +------------------------------- +--- +-- +copyright = '' +author = 'Winds' +version = 'v1.0.0' +desc = [[ + The script gives you a easy way to write your *.eml dumps onto normal MFC and magic Gen3 cards. + + Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards. + The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards. + + It supports the following functionality. + + 1. Write it to the same of current card UID. + 2. Write it to magic Gen3 card. + 3. Change uid to match dump on magic Gen3 card. + 4. Permanent lock UID on magic Gen3 card. + 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800. + + Script works in a wizard styled way. +]] +example = [[ + 1. script run mfc_gen3_writer +]] +usage = [[ + Select your *.eml dump from list to write to the card. +]] +-- +--- +------------------------------- +-- Global variables +------------------------------- +--- +-- +local DEBUG = false -- the debug flag +local files = {} -- Array for eml files +local b_keys = {} -- Array for B keys +local eml = {} -- Array for data in block 32 +local num_dumps = 0 -- num of found eml dump files +local tab = string.rep('-', 64) +local empty = string.rep('0', 32) -- Writing blocks +local default_key = 'FFFFFFFFFFFF' -- Writing blocks +local default_key_type = '01' --KeyA: 00, KeyB: 01 +local default_key_blk = 'FFFFFFFFFFFF78778800FFFFFFFFFFFF' -- Writing blocks +local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100' +local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10' +local cmd_wrbl = 'hf mf wrbl %d B %s %s' -- Writing blocks +-- +--- +------------------------------- +-- 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 +-- +--- +------------------------------- +-- This is only meant to be used when errors occur +------------------------------- +--- +-- +local function oops(err) + print('ERROR:', err) + core.clearCommandBuffer() + return nil, err +end +-- +--- +------------------------------- +-- Usage help +------------------------------- +--- +-- +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) + print(usage) +end +-- +--- +------------------------------- +-- GetUID +------------------------------- +--- +-- +local function GetUID() + return read14a.read(true, true).uid +end +-- +local function dropfield() + read14a.disconnect() + core.clearCommandBuffer() +end +-- +--- +------------------------------- +-- Wait for tag (MFC) +------------------------------- +--- +-- +local function wait() + read14a.waitFor14443a() +end +-- +--- +------------------------------- +-- Return key code 00/01 to string +------------------------------- +--- +-- +local function KeyAB() + if default_key_type == '00' then + return 'KeyA' + else + return 'KeyB' + end +end +-- +--- +------------------------------- +-- Check response from Proxmark +------------------------------- +--- +-- +local function getblockdata(response) + if response.Status == 0 then + return true + else + return false + end +end +-- +--- +------------------------------- +-- Check 0xFFFFFFFFFFFF key for tag (MFC) +------------------------------- +--- +-- +local function checkkey() + local status = 0 + for i = 1, #eml do + cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = ('%02x%02x%s'):format((i-1), default_key_type, default_key)} + if (getblockdata(cmd:sendNG(false)) == true) then + status = status + 1 + print(('%s %02s %s %s %s'):format(' ', (i-1), KeyAB(), default_key, 'OK')) + else + break + end + end + if status == #eml then + return true + end +end +-- +--- +------------------------------- +-- Check Pissword backdor +------------------------------- +--- +-- +local function checkmagic() + --Have no RAW ISO14443A command in appmain.c + cmd = Command:newNG{cmd = cmds.CMD_HF_ISO14443A_READER, data = piswords_uid_change .. GetUID()} -- sample check to pull the same UID to card and check response + if (getblockdata(cmd:sendNG(false)) == true) then + print('Magic') + else + print('Not magic') + end +end +-- +--- +------------------------------- +-- Main function +------------------------------- +--- +-- +local function main(args) + -- + --- + ------------------------------- + -- Arguments for script + ------------------------------- + --- + -- + for o, a in getopt.getopt(args, 'hd') do + if o == 'h' then return help() end + if o == 'd' then DEBUG = true end + end + -- + wait() + print(tab) + -- + --- + ------------------------------- + -- Detect 7/4 byte card + ------------------------------- + --- + -- + if string.len(GetUID()) == 14 then + eml_file_uid_start = 18 -- For windows with '---------- ' prefix + eml_file_uid_end = 31 + eml_file_lengt = 40 + else + eml_file_uid_start = 18 -- For windows with '---------- ' prefix + eml_file_uid_end = 25 + eml_file_lengt = 34 + end + dropfield() + -- + --- + ------------------------------- + -- List all EML files in /client + ------------------------------- + --- + -- + local dumpEML = 'find "." "*dump.eml"' -- Fixed for windows + local p = assert(io.popen(dumpEML)) + for _ in p:lines() do + -- The length of eml file + if string.len(_) == eml_file_lengt then + num_dumps = num_dumps + 1 + -- cut UID from eml file + files[num_dumps] = string.sub(_, eml_file_uid_start, eml_file_uid_end) -- cut numeretic UID + print(' '..num_dumps..' | '..files[num_dumps]) + end + end + -- + p.close() + -- + if num_dumps == 0 then return oops("Didn't find any dump files") end + -- + print(tab) + print(' Your card has UID '..GetUID()) + print('') + print(' Select which dump to write (1 until '..num_dumps..')') + print(tab) + io.write(' --> ') + -- + local uid_no = tonumber(io.read()) + print(tab) + print(' You have been selected card dump No ' .. uid_no .. ', with UID: ' .. files[uid_no] .. '. Your card UID: ' .. GetUID()) + -- + -- + --- + ------------------------------- + -- Load eml file + ------------------------------- + --- + -- + local dumpfile = assert(io.open('./hf-mf-' .. files[uid_no] .. '-dump.eml', 'r')) + for _ in dumpfile:lines() do table.insert(eml, _); end + dumpfile.close() + -- + --- + ------------------------------- + -- Extract B key from EML file + ------------------------------- + --- + -- + local b = 0 + for i = 1, #eml do + if (i % 4 == 0) then + repeat + b = b + 1 + -- Cut key from block + b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i]) + until b % 4 == 0 + end + end + print(tab) + dbg(b_keys) + dbg(eml) + -- + --- + ------------------------------- + -- Change UID on certain version of magic Gen3 card. + ------------------------------- + --- + -- + if (utils.confirm(' Change UID ?') == true) then + wait() + core.console(piswords_uid_change .. tostring(eml[1])) + print(tab) + print(' The new card UID : ' .. GetUID()) + end + print(tab) + --checkmagic() + -- + --- + ------------------------------- + -- Lock UID + ------------------------------- + --- + -- + if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then + wait() + core.console(piswords_uid_lock) + end + -- + print(tab) + print(' Going to check the all ' .. KeyAB() .. ' by ' .. default_key) + print(tab) + -- + if checkkey() == true then + print(tab) + if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then + for i = 1, #eml do + core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) + end + end + else + print(tab) + if (utils.confirm(' Delete ALL data and write all keys to 0x' .. default_key .. ' ?') == true) then + wait() + for i = 1, #eml do + if (i % 4 == 0) then + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) + else + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) + end + end + else + print(tab) + if (utils.confirm(' Write selected dump to card ?') == true) then + print(tab) + wait() + for i = 1, #eml do + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) + end + end + end + end + dropfield() + print(tab) + print('You are welcome') +end +-- +--- +------------------------------- +-- Start Main function +------------------------------- +--- +-- +main(args) From ea6dbec7502d15d4975e1a8d0233104ba923beb0 Mon Sep 17 00:00:00 2001 From: Winds Date: Thu, 3 Sep 2020 22:55:35 +0200 Subject: [PATCH 2/2] Now it's working both with WIN and UNX --- client/luascripts/mfc_gen3_writer.lua | 105 ++++++++++++++++++-------- 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/client/luascripts/mfc_gen3_writer.lua b/client/luascripts/mfc_gen3_writer.lua index 5222c0d39..22eae4387 100644 --- a/client/luascripts/mfc_gen3_writer.lua +++ b/client/luascripts/mfc_gen3_writer.lua @@ -14,7 +14,6 @@ local read14a = require('read14a') --- Add support another types of dumps: BIN, JSON --- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager. --- Add undependence from the operation system. At the moment code not working in Linux. ---- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) --- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% -- iceman notes: @@ -30,13 +29,13 @@ local read14a = require('read14a') ------------------------------- --- -- -copyright = '' +copyright = 'RRG Team' author = 'Winds' version = 'v1.0.0' desc = [[ - The script gives you a easy way to write your *.eml dumps onto normal MFC and magic Gen3 cards. + This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards. - Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards. + Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards. The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards. It supports the following functionality. @@ -48,12 +47,19 @@ desc = [[ 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800. Script works in a wizard styled way. + + Author Youtube channel: https://yev.ooo/ + + Many Thanks, + Best Regards ]] example = [[ 1. script run mfc_gen3_writer ]] usage = [[ + Give script to know if you uses an Windows OS Select your *.eml dump from list to write to the card. + Follow the wizard. ]] -- --- @@ -63,6 +69,7 @@ usage = [[ --- -- local DEBUG = false -- the debug flag +local dumpEML -- Find all *.EML files local files = {} -- Array for eml files local b_keys = {} -- Array for B keys local eml = {} -- Array for data in block 32 @@ -71,10 +78,11 @@ local tab = string.rep('-', 64) local empty = string.rep('0', 32) -- Writing blocks local default_key = 'FFFFFFFFFFFF' -- Writing blocks local default_key_type = '01' --KeyA: 00, KeyB: 01 -local default_key_blk = 'FFFFFFFFFFFF78778800FFFFFFFFFFFF' -- Writing blocks +local default_key_blk = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- Writing blocks local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100' local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10' -local cmd_wrbl = 'hf mf wrbl %d B %s %s' -- Writing blocks +local cmd_wrbl_a = 'hf mf wrbl %d A %s %s' -- Writing blocks by A key +local cmd_wrbl_b = 'hf mf wrbl %d B %s %s' -- Writing blocks by B key -- --- ------------------------------- @@ -155,11 +163,11 @@ end --- -- local function KeyAB() - if default_key_type == '00' then + if default_key_type == '00' then return 'KeyA' - else + else return 'KeyB' - end + end end -- --- @@ -200,17 +208,15 @@ end -- --- ------------------------------- --- Check Pissword backdor +-- Check user input A or B for blank tag (MFC) ------------------------------- --- -- -local function checkmagic() - --Have no RAW ISO14443A command in appmain.c - cmd = Command:newNG{cmd = cmds.CMD_HF_ISO14443A_READER, data = piswords_uid_change .. GetUID()} -- sample check to pull the same UID to card and check response - if (getblockdata(cmd:sendNG(false)) == true) then - print('Magic') - else - print('Not magic') +local function check_user_key(user_key_type) + if user_key_type == 'A' then + return cmd_wrbl_a + elseif user_key_type == 'B' then + return cmd_wrbl_b end end -- @@ -242,15 +248,30 @@ local function main(args) ------------------------------- --- -- - if string.len(GetUID()) == 14 then - eml_file_uid_start = 18 -- For windows with '---------- ' prefix - eml_file_uid_end = 31 - eml_file_lengt = 40 + if (utils.confirm(' Are you use a Windwos OS ?') == true) then + dumpEML = 'find "." "*dump.eml"' + if string.len(GetUID()) == 14 then + eml_file_uid_start = 18 + eml_file_uid_end = 31 + eml_file_lengt = 40 + else + eml_file_uid_start = 18 + eml_file_uid_end = 25 + eml_file_lengt = 34 + end else - eml_file_uid_start = 18 -- For windows with '---------- ' prefix - eml_file_uid_end = 25 - eml_file_lengt = 34 + dumpEML = "find '.' -iname '*dump.eml' -type f" + if string.len(GetUID()) == 14 then + eml_file_uid_start = 9 + eml_file_uid_end = 22 + eml_file_lengt = 31 + else + eml_file_uid_start = 9 + eml_file_uid_end = 16 + eml_file_lengt = 25 + end end + print(tab) dropfield() -- --- @@ -259,7 +280,6 @@ local function main(args) ------------------------------- --- -- - local dumpEML = 'find "." "*dump.eml"' -- Fixed for windows local p = assert(io.popen(dumpEML)) for _ in p:lines() do -- The length of eml file @@ -293,7 +313,7 @@ local function main(args) ------------------------------- --- -- - local dumpfile = assert(io.open('./hf-mf-' .. files[uid_no] .. '-dump.eml', 'r')) + local dumpfile = assert(io.open('hf-mf-' .. files[uid_no] .. '-dump.eml', 'r')) for _ in dumpfile:lines() do table.insert(eml, _); end dumpfile.close() -- @@ -330,7 +350,6 @@ local function main(args) print(' The new card UID : ' .. GetUID()) end print(tab) - --checkmagic() -- --- ------------------------------- @@ -351,18 +370,28 @@ local function main(args) print(tab) if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) + core.console(string.format(cmd_wrbl_b, (i-1), default_key, eml[i])) end end else print(tab) - if (utils.confirm(' Delete ALL data and write all keys to 0x' .. default_key .. ' ?') == true) then + if (utils.confirm(' It this is a new blank card ? Do you wishing to change Access Conditions to using B key ' .. default_key .. ' as main ?') == true) then + print(tab) + print(' With one key type we will use, A or B ?') + print(tab) + io.write(' --> ') + local user_key_type = tostring(io.read()) + print(tab) + print(' Enter 12 HEX chars of the key for access to card. By default ' .. default_key .. '.') + print(tab) + io.write(' --> ') + local user_key_input = tostring(io.read()) wait() for i = 1, #eml do if (i % 4 == 0) then - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) + core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, default_key_blk)) else - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) + core.console(string.format(check_user_key(user_key_type), (i-1), user_key_input, empty)) end end else @@ -371,7 +400,19 @@ local function main(args) print(tab) wait() for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) + core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], eml[i])) + end + else + print(tab) + if (utils.confirm(' Delete ALL data and write all keys to 0x' .. default_key .. ' ?') == true) then + wait() + for i = 1, #eml do + if (i % 4 == 0) then + core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], default_key_blk)) + else + core.console(string.format(cmd_wrbl_b, (i-1), b_keys[i], empty)) + end + end end end end