proxmark3/client/luascripts/hf_mf_format.lua

221 lines
6.3 KiB
Lua
Raw Normal View History

2019-03-09 17:34:43 +08:00
local cmds = require('commands')
local getopt = require('getopt')
local bin = require('bin')
local lib14a = require('read14a')
local utils = require('utils')
2020-04-05 18:28:49 +08:00
local ansicolors = require('ansicolors')
2019-03-09 17:34:43 +08:00
copyright = ''
author = 'Iceman'
2021-04-16 07:08:25 +08:00
version = 'v1.0.3'
2019-03-09 17:34:43 +08:00
desc = [[
2021-04-16 07:08:25 +08:00
This script will generate 'hf mf wrbl' commands for each block to format a Mifare Classic card.
2019-03-09 17:34:43 +08:00
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
2019-03-09 17:34:43 +08:00
The script will skip the manufactoring block 0.
2019-05-08 05:04:29 +08:00
]]
example = [[
-- generate commands
1. script run hf_mf_format
2019-05-08 05:04:29 +08:00
-- generate command, replacing key with new key.
2. script run hf_mf_format -k aabbccddeeff -n 112233445566 -a FF0780
2019-03-09 17:34:43 +08:00
2019-05-08 05:04:29 +08:00
-- generate commands and execute them against card.
3. script run hf_mf_format -x
2019-05-08 05:04:29 +08:00
]]
usage = [[
script run hf_mf_format -k <key> -n <key> -a <access> -x
2020-04-05 18:28:49 +08:00
]]
arguments = [[
2019-03-09 17:34:43 +08:00
-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
2020-10-23 07:24:54 +08:00
-x - execute the commands as well.
2019-03-09 17:34:43 +08:00
]]
2019-05-08 05:04:29 +08:00
2019-03-09 17:34:43 +08:00
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
2021-04-16 07:08:25 +08:00
local CmdString = 'hf mf wrbl --blk %d -b -k %s -d %s'
2019-03-09 17:34:43 +08:00
local numBlocks = 64
local numSectors = 16
---
-- A debug printout-function
2019-05-08 05:04:29 +08:00
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
2019-03-09 17:34:43 +08:00
local i = 1
2019-05-08 05:04:29 +08:00
while args[i] do
dbg(args[i])
2019-03-09 17:34:43 +08:00
i = i+1
end
else
2019-05-08 05:04:29 +08:00
print('###', args)
2019-03-09 17:34:43 +08:00
end
end
---
-- This is only meant to be used when errors occur
2019-05-08 05:04:29 +08:00
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
return nil, err
2019-03-09 17:34:43 +08:00
end
---
-- Usage help
2019-05-08 05:04:29 +08:00
local function help()
2019-03-09 17:34:43 +08:00
print(copyright)
print(author)
print(version)
print(desc)
2020-04-05 18:28:49 +08:00
print(ansicolors.cyan..'Usage'..ansicolors.reset)
2019-05-08 05:04:29 +08:00
print(usage)
2020-04-05 18:28:49 +08:00
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
print(arguments)
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
print(example)
2019-03-09 17:34:43 +08:00
end
--
-- Exit message
2019-05-08 05:04:29 +08:00
local function ExitMsg(msg)
2019-03-09 17:34:43 +08:00
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
--
-- Read information from a card
2021-04-16 07:08:25 +08:00
local function GetCardInfo()
2019-03-09 17:34:43 +08:00
result, err = lib14a.read(false, true)
if not result then
print(err)
return
end
2019-05-08 05:04:29 +08:00
print(('Found: %s'):format(result.name))
2019-03-09 17:34:43 +08:00
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
2019-05-08 05:04:29 +08:00
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
2019-03-09 17:34:43 +08:00
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))
2019-03-09 17:34:43 +08:00
print( string.format('Old key: %s', OldKey))
print( string.format('New key: %s', NewKey))
print( string.format('New Access: %s', Accessbytes))
2019-05-08 05:04:29 +08:00
print( string.rep('--', 20) )
2019-03-09 17:34:43 +08:00
2019-05-08 05:04:29 +08:00
-- Set new block data
local EMPTY_BL = string.rep('00', 16)
local EMPTY_SECTORTRAIL = string.format('%s%s%s%s', NewKey, Accessbytes, '00', NewKey)
2019-03-09 17:34:43 +08:00
2019-05-08 05:04:29 +08:00
dbg( string.format('New sector-trailer : %s', EMPTY_SECTORTRAIL))
dbg( string.format('New emptyblock: %s', EMPTY_BL))
2019-03-09 17:34:43 +08:00
dbg('')
if x then
print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.')
end
-- Ask
2019-05-08 05:04:29 +08:00
local dialogResult = utils.confirm('Do you want to erase this card')
2019-03-09 17:34:43 +08:00
if dialogResult == false then
return ExitMsg('Quiting it is then. Your wish is my command...')
end
2019-05-08 05:04:29 +08:00
print( string.rep('--', 20) )
2019-03-09 17:34:43 +08:00
-- main loop
2019-05-08 05:04:29 +08:00
for block = 0, numBlocks, 1 do
2019-03-09 17:34:43 +08:00
local reminder = (block+1) % 4
local cmd
if reminder == 0 then
2021-04-16 07:08:25 +08:00
cmd = CmdString:format(block, OldKey, EMPTY_SECTORTRAIL)
2019-03-09 17:34:43 +08:00
else
2021-04-16 07:08:25 +08:00
cmd = CmdString:format(block, OldKey, EMPTY_BL)
2019-03-09 17:34:43 +08:00
end
if block ~= 0 then
print(cmd)
if x then core.console(cmd) end
end
if core.kbd_enter_pressed() then
2019-05-08 05:04:29 +08:00
print('aborted by user')
2019-03-09 17:34:43 +08:00
break
end
end
end
2019-03-12 07:12:26 +08:00
main(args)