]> git.zerfleddert.de Git - proxmark3-svn/blame - client/scripts/mfkeys.lua
mfkeys.lua: Remove the user input helpers (now in lualibs/utils.lua)
[proxmark3-svn] / client / scripts / mfkeys.lua
CommitLineData
16b04cb2 1--[[
2 This is an example of Lua-scripting within proxmark3. This is a lua-side
3 implementation of hf mf chk
4
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
7 the license.
8
9 Copyright (C) 2013 m h swende <martin at swende.se>
05ed5c49 10--]]
16b04cb2 11-- Loads the commands-library
12local cmds = require('commands')
13-- Load the default keys
14local keys = require('mf_default_keys')
a2d82b46 15-- Ability to read what card is there
16local reader = require('read14a')
392301aa
A
17-- Asks the user for input
18local utils = require('utils')
a2d82b46 19
05ed5c49 20
392301aa
A
21local desc = ("This script implements check keys. \
22It utilises a large list of default keys (currently %d keys).\
16b04cb2 23If you want to add more, just put them inside mf_default_keys.lua. "):format(#keys)
24
25local TIMEOUT = 10000 -- 10 seconds
05ed5c49 26
16b04cb2 27
28local function checkCommand(command)
29
30 --print("Sending this command : " .. tostring(command))
31 local usbcommand = command:getBytes()
32 core.SendCommand(usbcommand)
33 local result = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
34 if result then
35 local count,cmd,arg0 = bin.unpack('LL',result)
36 if(arg0==1) then
37 local count,arg1,arg2,data = bin.unpack('LLH511',result,count)
38 key = data:sub(1,12)
39 return key
40 else
41 --print("Key not found...")
42 return nil
43 end
44 else
45 print("Timeout while waiting for response. Increase TIMEOUT in keycheck.lua to wait longer")
46 return nil, "Timeout while waiting for device to respond"
47 end
48end
49
50
51function checkBlock(blockNo, keys, keyType)
52 -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
53 -- If there's more, we need to split it up
54 local start, remaining= 1, #keys
44191180 55 local arg1 = bit32.bor(bit32.lshift(keyType, 8), blockNo)
16b04cb2 56 local packets = {}
57 while remaining > 0 do
58 local n,data = remaining, nil
59 if remaining > 85 then n = 85 end
60 local data = table.concat(keys,"",start,n)
61 --print("data",data)
62 --print("data len", #data)
63 print(("Testing block %d, keytype %d, with %d keys"):format(blockNo, keyType, n))
64 local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
44191180
I
65 arg1 = arg1,
66 arg2 = 1,
16b04cb2 67 arg3 = n,
68 data = data}
69 local status = checkCommand(command)
70 if status then return status, blockNo end
71 start = start+n+1
72 remaining = remaining - n
73 end
74 return nil
75end
76
77-- A function to display the results
78local function displayresults(results)
79 local sector, blockNo, keyA, keyB,_
80
81 print("________________________________________")
82 print("|Sector|Block| A | B |")
83 print("|--------------------------------------|")
84
85 for sector,_ in pairs(results) do
86 blockNo, keyA, keyB = unpack(_)
87
88 print(("| %3d | %3d |%s|%s|"):format(sector, blockNo, keyA, keyB ))
89 end
90 print("|--------------------------------------|")
91
92end
93-- A little helper to place an item first in the list
94local function placeFirst(akey, list)
95 akey = akey:lower()
96 if list[1] == akey then
97 -- Already at pole position
98 return list
99 end
100 local result = {akey}
101 --print(("Putting '%s' first"):format(akey))
102 for i,v in ipairs(list) do
103 if v ~= akey then
104 result[#result+1] = v
105 end
106 end
107 return result
108end
05ed5c49 109local function dumptofile(results)
110 local sector, blockNo, keyA, keyB,_
16b04cb2 111
05ed5c49 112 if utils.confirm("Do you wish to save the keys to dumpfile?") then
113 local destination = utils.input("Select a filename to store to", "dumpkeys.bin")
114 local file = io.open(destination, "w")
115 if file == nil then
116 print("Could not write to file ", destination)
117 return
118 end
119
120 local key_a = ""
121 local key_b = ""
122
123 for sector,_ in pairs(results) do
124 blockNo, keyA, keyB = unpack(_)
125 key_a = key_a .. bin.pack("H",keyA);
126 key_b = key_b .. bin.pack("H",keyB);
127 end
128 file:write(key_a)
129 file:write(key_b)
130 file:close()
131 end
132end
133
134
135local function main( args)
16b04cb2 136
137 print(desc);
138
e98389b3 139 result, err = reader.read14443a(false, true)
a2d82b46 140 if not result then
141 print(err)
142 return
143 end
144 print(("Found a %s tag"):format(result.name))
145
146
16b04cb2 147 core.clearCommandBuffer()
148 local blockNo
149 local keyType = 0 -- A=0, B=1
05ed5c49 150 local numSectors = 16
151
152 if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k
153 -- IFARE Classic 4K offers 4096 bytes split into forty sectors,
154 -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
155 numSectors = 40
156 elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
157 -- 1K offers 1024 bytes of data storage, split into 16 sector
158 numSectors = 16
159 elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
160 -- MIFARE Classic mini offers 320 bytes split into five sectors.
161 numSectors = 5
162 elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k"
163 numSectors = 32
164 else
165 print("I don't know how many sectors there are on this type of card, defaulting to 16")
166 end
167
168 result = {}
169 for sector=1,numSectors,1 do
16b04cb2 170
171 --[[
05ed5c49 172 The mifare Classic 1k card has 16 sectors of 4 data blocks each.
173 The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining
16b04cb2 174 8 sectors consist of 16 data blocks.
175 --]]
176 local blockNo = sector * 4 -1
177
178 if sector > 32 then
179 blockNo = 32*4+ (sector-32)*16 -1
180 end
181
182 local keyA = checkBlock(blockNo, keys, 0)
183 if keyA then keys = placeFirst(keyA, keys) end
184 keyA = keyA or ""
185
186 local keyB = checkBlock(blockNo, keys, 1)
187 if keyB then keys = placeFirst(keyB, keys) end
188 keyB = keyB or ""
189
190 result[sector] = {blockNo, keyA, keyB }
191
192 -- Check if user aborted
193 if core.ukbhit() then
194 print("Aborted by user")
195 break
196 end
197 end
198 displayresults(result)
05ed5c49 199 dumptofile(result)
16b04cb2 200end
201
05ed5c49 202main( args)
16b04cb2 203
Impressum, Datenschutz