2 This is an example of Lua-scripting within proxmark3. This is a lua-side
3 implementation of hf mf chk
5 This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 at your option, any later version. See the LICENSE.txt file for the text of
9 Copyright (C) 2013 m h swende <martin at swende.se>
11 -- Loads the commands-library
12 local cmds = require('commands')
13 -- Load the default keys
14 local keys = require('mf_default_keys')
16 ("This script implements check keys. It utilises a large list of default keys (currently %d keys).\
17 If you want to add more, just put them inside mf_default_keys.lua. "):format(#keys)
19 local TIMEOUT = 10000 -- 10 seconds
21 local function checkCommand(command)
23 --print("Sending this command : " .. tostring(command))
24 local usbcommand = command:getBytes()
25 core.SendCommand(usbcommand)
26 local result = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
28 local count,cmd,arg0 = bin.unpack('LL',result)
30 local count,arg1,arg2,data = bin.unpack('LLH511',result,count)
34 --print("Key not found...")
38 print("Timeout while waiting for response. Increase TIMEOUT in keycheck.lua to wait longer")
39 return nil, "Timeout while waiting for device to respond"
44 function checkBlock(blockNo, keys, keyType)
45 -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
46 -- If there's more, we need to split it up
47 local start, remaining= 1, #keys
49 while remaining > 0 do
50 local n,data = remaining, nil
51 if remaining > 85 then n = 85 end
52 local data = table.concat(keys,"",start,n)
54 --print("data len", #data)
55 print(("Testing block %d, keytype %d, with %d keys"):format(blockNo, keyType, n))
56 local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
61 local status = checkCommand(command)
62 if status then return status, blockNo end
64 remaining = remaining - n
69 -- A function to display the results
70 local function displayresults(results)
71 local sector, blockNo, keyA, keyB,_
73 print("________________________________________")
74 print("|Sector|Block| A | B |")
75 print("|--------------------------------------|")
77 for sector,_ in pairs(results) do
78 blockNo, keyA, keyB = unpack(_)
80 print(("| %3d | %3d |%s|%s|"):format(sector, blockNo, keyA, keyB ))
82 print("|--------------------------------------|")
85 -- A little helper to place an item first in the list
86 local function placeFirst(akey, list)
88 if list[1] == akey then
89 -- Already at pole position
93 --print(("Putting '%s' first"):format(akey))
94 for i,v in ipairs(list) do
102 local function main()
106 core.clearCommandBuffer()
108 local keyType = 0 -- A=0, B=1
113 The mifare Classic 1k card has 16 sectors of 4 data blocks each. The
114 first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
115 8 sectors consist of 16 data blocks.
117 local blockNo = sector * 4 -1
120 blockNo = 32*4+ (sector-32)*16 -1
123 local keyA = checkBlock(blockNo, keys, 0)
124 if keyA then keys = placeFirst(keyA, keys) end
127 local keyB = checkBlock(blockNo, keys, 1)
128 if keyB then keys = placeFirst(keyB, keys) end
131 result[sector] = {blockNo, keyA, keyB }
133 -- Check if user aborted
134 if core.ukbhit() then
135 print("Aborted by user")
139 displayresults(result)