1 local cmds = require('commands')
 
   2 local getopt = require('getopt')
 
   3 local utils = require('utils')
 
   4 local lib14a = require('read14a')
 
   6 example = "script iterates over all possible sectors for a tag and runs hardnested attack against them to collect the keys."
 
  10 This script iterates over all possible sectors for a tag and runs hardnested attack against them to collect the keys.
 
  13         -k                              Known key, 6 bytes (12 hex digits)
 
  15         script hard -b 112233445566
 
  22 -- A debug printout-function
 
  24         if not DEBUG then return end
 
  26     if type(args) == "table" then
 
  37 -- This is only meant to be used when errors occur
 
  46         print("Example usage")
 
  52         print( string.rep('--',20) )
 
  53         print( string.rep('--',20) )
 
  57 -- A little helper to place an item first in the list
 
  58 local function placeFirst(akey, list)
 
  60         if list[1] == akey then 
 
  61                 -- Already at pole position
 
  65         --print(("Putting '%s' first"):format(akey))
 
  66         for i,v in ipairs(list) do
 
  73 -- A function to display the results
 
  74 -- TODO: iceman 2016,  still screws up output when a key is not found.
 
  75 local function displayresults(results)
 
  76         local sector, blockNo, keyA, keyB, succA, succB, _
 
  78         print("|---|----------------|---|----------------|---|")
 
  79         print("|sec|key A           |res|key B           |res|")
 
  80         print("|---|----------------|---|----------------|---|")
 
  82         for sector,_ in pairs(results) do
 
  83                 succA, succB, keyA, keyB = unpack(_)
 
  84                 print(("|%03d|  %s  | %s |  %s  | %s |"):format(sector, keyA, succA, keyB, succB))
 
  86         print("|---|----------------|---|----------------|---|")
 
  90 -- a simple selftest function,
 
  91 local function selftest()
 
  96 -- The main entry point
 
 100         local keytype = 0 --A  01==B
 
 101         local key = 'fc00018778f7'
 
 103         local numSectors = 16   
 
 105         -- Read the parameters
 
 106         for o, a in getopt.getopt(args, 'hk:') do
 
 107                 if o == "h" then return help() end
 
 108                 if o == "k" then key = a end
 
 112         local cmdSetDbgOff = "hf mf dbg 0"
 
 113         core.console( cmdSetDbgOff) 
 
 115         result, err = lib14a.read1443a(false)
 
 119         core.clearCommandBuffer()
 
 122         print((' Found tag %s'):format(result.name))
 
 124         if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k
 
 125                 -- IFARE Classic 4K offers 4096 bytes split into forty sectors, 
 
 126                 -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. 
 
 128         elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
 
 129                 -- 1K offers 1024 bytes of data storage, split into 16 sector
 
 131         elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
 
 132                 -- MIFARE Classic mini offers 320 bytes split into five sectors.
 
 134         elseif  0x10 == result.sak then-- "NXP MIFARE Plus 2k"
 
 137                 print("I don't know how many sectors there are on this type of card, defaulting to 16")
 
 141         for sector=1,numSectors do
 
 144                 The mifare Classic 1k card has 16 sectors of 4 data blocks each. 
 
 145                 The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
 
 146                 8 sectors consist of 16 data blocks. 
 
 148                 local trgblockno = sector * 4 - 1 
 
 150                         trgblockno = 32 * 4 + (sector-32) * 16 -1
 
 153                 trgblockno = ("%02d"):format(trgblockno)
 
 157                 local errA, keyA = core.hardnested(blockno, keytype, key, trgblockno, '0', trgkey, 0,0,0,0)
 
 159                 if errA > 0 then succA = 0 end
 
 161                 local errB, keyB = core.hardnested(blockno, keytype, key, trgblockno, '1', trgkey, 0,0,0,0)
 
 163                 if errB > 0 then succB = 0 end
 
 164                 result[sector] = { succA, succB, utils.ConvertAsciiToHex(keyA), utils.ConvertAsciiToHex(keyB) }
 
 166                 -- Check if user aborted
 
 167                 if core.ukbhit() then
 
 168                         print("Aborted by user")
 
 172         displayresults(result)