+local cmds = require('commands')\r
+local getopt = require('getopt')\r
+local bin = require('bin')\r
+local lib14a = require('read14a')\r
+local utils = require('utils')\r
+\r
+example =[[\r
+ 1. script run formatMifare\r
+ 2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780\r
+]]\r
+author = "Iceman"\r
+usage = "script run formatMifare -k <key>"\r
+desc =[[\r
+This script will generate 'hf mf wrbl' commands for each block to format a Mifare card.\r
+\r
+Alla datablocks gets 0x00\r
+As default the script sets the keys A/B to 0xFFFFFFFFFFFF\r
+and the access bytes will become 0x78,0x77,0x88\r
+The GDB will become 0x00\r
+\r
+The script will skip the manufactoring block 0.\r
+\r
+Arguments:\r
+ -h - this help\r
+ -k <key> - the current six byte key with write access\r
+ -n <key> - the new key that will be written to the card\r
+ -a <access> - the new access bytes that will be written to the card\r
+]]\r
+local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds\r
+local DEBUG = true -- the debug flag\r
+local CmdString = 'hf mf wrbl %d B %s %s'\r
+local numBlocks = 64\r
+local numSectors = 16\r
+--- \r
+-- A debug printout-function\r
+function dbg(args)\r
+ if not DEBUG then\r
+ return\r
+ end\r
+ \r
+ if type(args) == "table" then\r
+ local i = 1\r
+ while result[i] do\r
+ dbg(result[i])\r
+ i = i+1\r
+ end\r
+ else\r
+ print("###", args)\r
+ end \r
+end \r
+--- \r
+-- This is only meant to be used when errors occur\r
+function oops(err)\r
+ print("ERROR: ",err)\r
+end\r
+--- \r
+-- Usage help\r
+function help()\r
+ print(desc)\r
+ print("Example usage")\r
+ print(example)\r
+end\r
+--\r
+-- Exit message\r
+function ExitMsg(msg)\r
+ print( string.rep('--',20) )\r
+ print( string.rep('--',20) )\r
+ print(msg)\r
+ print()\r
+end\r
+--\r
+-- Read information from a card\r
+function GetCardInfo()\r
+ result, err = lib14a.read1443a(false)\r
+ if not result then\r
+ print(err)\r
+ return\r
+ end\r
+ print(("Found: %s"):format(result.name))\r
+\r
+ core.clearCommandBuffer()\r
+ \r
+ if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k\r
+ -- IFARE Classic 4K offers 4096 bytes split into forty sectors, \r
+ -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. \r
+ numSectors = 40\r
+ elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k\r
+ -- 1K offers 1024 bytes of data storage, split into 16 sector\r
+ numSectors = 16\r
+ elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k\r
+ -- MIFARE Classic mini offers 320 bytes split into five sectors.\r
+ numSectors = 5\r
+ elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k"\r
+ numSectors = 32\r
+ else\r
+ print("I don't know how many sectors there are on this type of card, defaulting to 16")\r
+ end \r
+ --[[\r
+ The mifare Classic 1k card has 16 sectors of 4 data blocks each. \r
+ The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining\r
+ 8 sectors consist of 16 data blocks. \r
+ --]]\r
+ \r
+ -- Defaults to 16 * 4 = 64 - 1 = 63\r
+ numBlocks = numSectors * 4 - 1 \r
+ \r
+ if numSectors > 32 then\r
+ numBlocks = 32*4+ (numSectors-32)*16 -1\r
+ end\r
+ \r
+end\r
+\r
+local function main(args)\r
+\r
+ print( string.rep('--',20) )\r
+ print( string.rep('--',20) )\r
+ print()\r
+ \r
+ local OldKey \r
+ local NewKey\r
+ local Accessbytes\r
+ \r
+ -- Arguments for the script\r
+ for o, a in getopt.getopt(args, 'hk:n:a:') do\r
+ if o == "h" then return help() end \r
+ if o == "k" then OldKey = a end\r
+ if o == "n" then NewKey = a end\r
+ if o == "a" then Accessbytes = a end\r
+ end\r
+\r
+ -- validate input args.\r
+ OldKey = OldKey or 'FFFFFFFFFFFF'\r
+ if #(OldKey) ~= 12 then\r
+ return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey))\r
+ end\r
+ \r
+ NewKey = NewKey or 'FFFFFFFFFFFF'\r
+ if #(NewKey) ~= 12 then\r
+ return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey))\r
+ end\r
+\r
+ --Accessbytes = Accessbytes or '787788'\r
+ Accessbytes = Accessbytes or 'FF0780'\r
+ if #(Accessbytes) ~= 6 then\r
+ return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes))\r
+ end\r
+\r
+ GetCardInfo()\r
+ \r
+ -- Show info\r
+ print( string.format('Estimating number of blocks: %d', numBlocks))\r
+ print( string.format('Old key: %s', OldKey))\r
+ print( string.format('New key: %s', NewKey))\r
+ print( string.format('New Access: %s', Accessbytes))\r
+ print( string.rep('--',20) )\r
+\r
+ -- Set new block data\r
+ local EMPTY_BL = string.rep('00',16)\r
+ local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey)\r
+ \r
+ dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL))\r
+ dbg( string.format('New emptyblock: %s',EMPTY_BL))\r
+ dbg('')\r
+ \r
+ -- Ask\r
+ local dialogResult = utils.confirm("Do you want to erase this card")\r
+ if dialogResult == false then \r
+ return ExitMsg('Quiting it is then. Your wish is my command...')\r
+ end \r
+\r
+ print( string.rep('--',20) )\r
+ \r
+ -- main loop\r
+ for block=0,numBlocks,1 do\r
+\r
+ local reminder = (block+1) % 4\r
+ local cmd\r
+ if reminder == 0 then\r
+ cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL)\r
+ else\r
+ cmd = CmdString:format(block, OldKey , EMPTY_BL) \r
+ end \r
+ \r
+ if block ~= 0 then\r
+ print(cmd)\r
+ --core.console(cmd)\r
+ end\r
+ \r
+ if core.ukbhit() then\r
+ print("aborted by user")\r
+ break\r
+ end\r
+ end\r
+end\r
+\r
+main(args)
\ No newline at end of file