From 5b1311fba2d422b0c4549097f8e9e0c635b1d9e1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 29 Aug 2014 09:09:23 +0200 Subject: [PATCH] Various scripts from iceman --- client/lualibs/utils.lua | 57 ++++++++++ client/scripts/emul2dump.lua | 60 ++++++++++ client/scripts/formatMifare.lua | 196 ++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 client/lualibs/utils.lua create mode 100644 client/scripts/emul2dump.lua create mode 100644 client/scripts/formatMifare.lua diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua new file mode 100644 index 00000000..3d27d5b6 --- /dev/null +++ b/client/lualibs/utils.lua @@ -0,0 +1,57 @@ +--[[ + This may be moved to a separate library at some point (Holiman) +--]] +local Utils = +{ + -- Asks the user for Yes or No + confirm = function(message, ...) + local answer + message = message .. " [y/n] ?" + repeat + io.write(message) + io.flush() + answer=io.read() + if answer == 'Y' or answer == "y" then + return true + elseif answer == 'N' or answer == 'n' then + return false + end + until false + end, + --- + -- Asks the user for input + input = function (message , default) + local answer + if default ~= nil then + message = message .. " (default: ".. default.. " )" + end + message = message .." \n > " + io.write(message) + io.flush() + answer=io.read() + if answer == '' then answer = default end + + return answer + end, + -- + -- Converts DECIMAL to HEX + ConvertDec2Hex = function(IN) + local B,K,OUT,I,D=16,"0123456789ABCDEF","",0 + while IN>0 do + I=I+1 + IN,D=math.floor(IN/B),math.mod(IN,B)+1 + OUT=string.sub(K,D,D)..OUT + end + return OUT + end, + --- + -- Convert Byte array to string of hex + ConvertBytes2String = function(bytes) + s = {} + for i = 1, #(bytes) do + s[i] = string.format("%02X",bytes[i]) + end + return table.concat(s) + end, +} +return Utils \ No newline at end of file diff --git a/client/scripts/emul2dump.lua b/client/scripts/emul2dump.lua new file mode 100644 index 00000000..315ad99a --- /dev/null +++ b/client/scripts/emul2dump.lua @@ -0,0 +1,60 @@ +local getopt = require('getopt') +local bin = require('bin') +local dumplib = require('html_dumplib') + +example =[[ + 1. script run emul2dump + 2. script run emul2dump -i myfile.eml + 3. script run emul2dump -i myfile.eml -o myfile.bin +]] +author = "Iceman" +usage = "script run emul2dump [-i ] [-o ]" +desc =[[ +This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with "hf mf restore" + +Arguments: + -h This help + -i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used + -o Specifies the output file. If omitted, .bin is used. +]] + +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end + +local function main(args) + + local input = "dumpdata.eml" + local output = os.date("%Y-%m-%d_%H%M%S.bin"); + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hi:o:') do + if o == "h" then return help() end + if o == "i" then input = a end + if o == "o" then output = a end + end + + local filename, err = dumplib.convert_eml_to_bin(input,output) + if err then return oops(err) end + + ExitMsg(("Wrote a BIN dump to the file %s"):format(filename)) +end + +main(args) \ No newline at end of file diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua new file mode 100644 index 00000000..1ced0c28 --- /dev/null +++ b/client/scripts/formatMifare.lua @@ -0,0 +1,196 @@ +local cmds = require('commands') +local getopt = require('getopt') +local bin = require('bin') +local lib14a = require('read14a') +local utils = require('utils') + +example =[[ + 1. script run formatMifare + 2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780 +]] +author = "Iceman" +usage = "script run formatMifare -k " +desc =[[ +This script will generate 'hf mf wrbl' commands for each block to format a Mifare card. + +Alla datablocks gets 0x00 +As default the script sets the keys A/B to 0xFFFFFFFFFFFF +and the access bytes will become 0x78,0x77,0x88 +The GDB will become 0x00 + +The script will skip the manufactoring block 0. + +Arguments: + -h - this help + -k - the current six byte key with write access + -n - the new key that will be written to the card + -a - the new access bytes that will be written to the card +]] +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = true -- the debug flag +local CmdString = 'hf mf wrbl %d B %s %s' +local numBlocks = 64 +local numSectors = 16 +--- +-- A debug printout-function +function dbg(args) + if not DEBUG then + return + end + + if type(args) == "table" then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end +-- +-- Read information from a card +function GetCardInfo() + result, err = lib14a.read1443a(false) + if not result then + print(err) + return + end + print(("Found: %s"):format(result.name)) + + core.clearCommandBuffer() + + if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k + -- IFARE Classic 4K offers 4096 bytes split into forty sectors, + -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. + numSectors = 40 + elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k + -- 1K offers 1024 bytes of data storage, split into 16 sector + numSectors = 16 + elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k + -- MIFARE Classic mini offers 320 bytes split into five sectors. + numSectors = 5 + elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k" + numSectors = 32 + else + print("I don't know how many sectors there are on this type of card, defaulting to 16") + end + --[[ + The mifare Classic 1k card has 16 sectors of 4 data blocks each. + The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining + 8 sectors consist of 16 data blocks. + --]] + + -- Defaults to 16 * 4 = 64 - 1 = 63 + numBlocks = numSectors * 4 - 1 + + if numSectors > 32 then + numBlocks = 32*4+ (numSectors-32)*16 -1 + end + +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local OldKey + local NewKey + local Accessbytes + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hk:n:a:') do + if o == "h" then return help() end + if o == "k" then OldKey = a end + if o == "n" then NewKey = a end + if o == "a" then Accessbytes = a end + end + + -- validate input args. + OldKey = OldKey or 'FFFFFFFFFFFF' + if #(OldKey) ~= 12 then + return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey)) + end + + NewKey = NewKey or 'FFFFFFFFFFFF' + if #(NewKey) ~= 12 then + return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey)) + end + + --Accessbytes = Accessbytes or '787788' + Accessbytes = Accessbytes or 'FF0780' + if #(Accessbytes) ~= 6 then + return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes)) + end + + GetCardInfo() + + -- Show info + print( string.format('Estimating number of blocks: %d', numBlocks)) + print( string.format('Old key: %s', OldKey)) + print( string.format('New key: %s', NewKey)) + print( string.format('New Access: %s', Accessbytes)) + print( string.rep('--',20) ) + + -- Set new block data + local EMPTY_BL = string.rep('00',16) + local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey) + + dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL)) + dbg( string.format('New emptyblock: %s',EMPTY_BL)) + dbg('') + + -- Ask + local dialogResult = utils.confirm("Do you want to erase this card") + if dialogResult == false then + return ExitMsg('Quiting it is then. Your wish is my command...') + end + + print( string.rep('--',20) ) + + -- main loop + for block=0,numBlocks,1 do + + local reminder = (block+1) % 4 + local cmd + if reminder == 0 then + cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL) + else + cmd = CmdString:format(block, OldKey , EMPTY_BL) + end + + if block ~= 0 then + print(cmd) + --core.console(cmd) + end + + if core.ukbhit() then + print("aborted by user") + break + end + end +end + +main(args) \ No newline at end of file -- 2.39.5