mirror of
				https://github.com/RfidResearchGroup/proxmark3.git
				synced 2025-10-27 06:26:39 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			220 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local cmds = require('commands')
 | |
| local getopt = require('getopt')
 | |
| local bin = require('bin')
 | |
| local lib14a = require('read14a')
 | |
| local utils = require('utils')
 | |
| local ansicolors  = require('ansicolors')
 | |
| 
 | |
| copyright = ''
 | |
| author = 'Iceman'
 | |
| version = 'v1.0.3'
 | |
| desc = [[
 | |
| This script will generate 'hf mf wrbl' commands for each block to format a Mifare Classic 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 GPB will become 0x00
 | |
| 
 | |
| The script will skip the manufactoring block 0.
 | |
| ]]
 | |
| example = [[
 | |
|     -- generate commands
 | |
|     1. script run hf_mf_format
 | |
| 
 | |
|     -- generate command, replacing key with new key.
 | |
|     2. script run hf_mf_format -k aabbccddeeff -n 112233445566 -a FF0780
 | |
| 
 | |
|     -- generate commands and execute them against card.
 | |
|     3. script run hf_mf_format -x
 | |
| ]]
 | |
| usage = [[
 | |
| script run hf_mf_format -k <key> -n <key> -a <access> -x
 | |
| ]]
 | |
| arguments = [[
 | |
|     -h             - this help
 | |
|     -k <key>       - the current six byte key with write access
 | |
|     -n <key>       - the new key that will be written to the card
 | |
|     -a <access>    - the new access bytes that will be written to the card
 | |
|     -x             - execute the commands as well.
 | |
| ]]
 | |
| 
 | |
| local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
 | |
| local DEBUG = true -- the debug flag
 | |
| local CmdString = 'hf mf wrbl --blk %d -b -k %s -d %s'
 | |
| local numBlocks = 64
 | |
| local numSectors = 16
 | |
| ---
 | |
| -- 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(ansicolors.cyan..'Usage'..ansicolors.reset)
 | |
|     print(usage)
 | |
|     print(ansicolors.cyan..'Arguments'..ansicolors.reset)
 | |
|     print(arguments)
 | |
|     print(ansicolors.cyan..'Example usage'..ansicolors.reset)
 | |
|     print(example)
 | |
| end
 | |
| --
 | |
| -- Exit message
 | |
| local function ExitMsg(msg)
 | |
|     print( string.rep('--',20) )
 | |
|     print( string.rep('--',20) )
 | |
|     print(msg)
 | |
|     print()
 | |
| end
 | |
| --
 | |
| -- Read information from a card
 | |
| local function GetCardInfo()
 | |
|     result, err = lib14a.read(false, true)
 | |
|     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
 | |
|     elseif  0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K
 | |
|         numSectors = 16
 | |
|     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, NewKey, Accessbytes
 | |
|     local x = false
 | |
| 
 | |
|     -- Arguments for the script
 | |
|     for o, a in getopt.getopt(args, 'hk:n:a:x') 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
 | |
|         if o == 'x' then x = true 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 + 1))
 | |
|     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('')
 | |
| 
 | |
|     if x then
 | |
|         print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
 | |
|     end
 | |
|     -- 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)
 | |
|             if x then core.console(cmd) end
 | |
|         end
 | |
| 
 | |
|         if core.kbd_enter_pressed() then
 | |
|             print('aborted by user')
 | |
|             break
 | |
|         end
 | |
|     end
 | |
| end
 | |
| 
 | |
| main(args)
 |