This is a library to read 14443a tags. It can be used something like this
local reader = require('read14a')
- result, err = reader.read1443a()
+ result, err = reader.read14443a()
if not result then
print(err)
return
ISO14A_NO_RATS = 0x200
}
-local ISO14443a_TYPES = {}
+local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
-local function tostring_1443a(sak)
+local function tostring_14443a(sak)
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
end
-local function parse1443a(data)
+local function parse14443a(data)
--[[
- Based on this struct :
+ Based on this struct :
typedef struct {
byte_t uid[10];
local count,uid,uidlen, atqa, sak, ats_len, ats= bin.unpack('H10CH2CC',data)
uid = uid:sub(1,2*uidlen)
--print("uid, atqa, sak: ",uid, atqa, sak)
- --print("TYPE: ", tostring_1443a(sak))
- return { uid = uid, atqa = atqa, sak = sak, name = tostring_1443a(sak)}
+ --print("TYPE: ", tostring_14443a(sak))
+ return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak)}
end
--- Sends a USBpacket to the device
-- @param command - the usb packet to send
--- @param ignoreresponse - if set to true, we don't read the device answer packet
--- which is usually recipe for fail. If not sent, the host will wait 2s for a
+-- @param ignoreresponse - if set to true, we don't read the device answer packet
+-- which is usually recipe for fail. If not sent, the host will wait 2s for a
-- response of type CMD_ACK
-- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull
local function read14443a(dont_disconnect, no_rats)
local command, result, info, err, data
- command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
+ command = Command:new{cmd = cmds.CMD_READER_ISO_14443a,
arg1 = ISO14A_COMMAND.ISO14A_CONNECT}
if dont_disconnect then
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT
local result,err = sendToDevice(command)
if result then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
- if arg0 == 0 then
+ if arg0 == 0 then
return nil, "iso14443a card select failed"
end
data = string.sub(result,count)
- info, err = parse1443a(data)
+ info, err = parse14443a(data)
else
err ="No response from card"
end
- if err then
- print(err)
+ if err then
+ print(err)
return nil, err
end
return info
end
---
--- Waits for a mifare card to be placed within the vicinity of the reader.
+-- Waits for a mifare card to be placed within the vicinity of the reader.
-- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error
local function waitFor14443a()
end
return nil, "Aborted by user"
end
+
local library = {
-
- read1443a = read14443a,
- read = read14443a,
+ read14443a = read14443a,
+ read = read14443a,
waitFor14443a = waitFor14443a,
- parse1443a = parse1443a,
+ parse14443a = parse14443a,
sendToDevice = sendToDevice,
ISO14A_COMMAND = ISO14A_COMMAND,
}
-return library
\ No newline at end of file
+return library
--[[
This is an example of Lua-scripting within proxmark3. This is a lua-side
- implementation of hf mf chk
+ implementation of hf mf chk
This code is licensed to you under the terms of the GNU GPL, version 2 or,
at your option, any later version. See the LICENSE.txt file for the text of
the license.
-
+
Copyright (C) 2013 m h swende <martin at swende.se>
--]]
-- Loads the commands-library
local keys = require('mf_default_keys')
-- Ability to read what card is there
local reader = require('read14a')
+-- Asks the user for input
+local utils = require('utils')
-local desc =
-("This script implements check keys. It utilises a large list of default keys (currently %d keys).\
+local desc = ("This script implements check keys. \
+It utilises a large list of default keys (currently %d keys).\
If you want to add more, just put them inside mf_default_keys.lua. "):format(#keys)
local TIMEOUT = 10000 -- 10 seconds
-
---[[This may be moved to a separate library at some point]]
-local utils =
-{
- ---
- -- Asks the user for Yes or No
- confirm = function(message, ...)
- local answer
- message = message .. " [y]/[n] ?"
- repeat
- io.write(message)
- io.flush()
- answer=io.read()
- if answer == 'Y' or answer == "y" then
- return true
- elseif answer == 'N' or answer == 'n' then
- return false
- end
- until false
- end,
- ---
- -- Asks the user for input
- input = function (message , default)
- local answer
- if default ~= nil then
- message = message .. " (default: ".. default.. " )"
- end
- message = message .." \n > "
- io.write(message)
- io.flush()
- answer=io.read()
- if answer == '' then answer = default end
-
- return answer
- end,
-}
local function checkCommand(command)
function checkBlock(blockNo, keys, keyType)
- -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
+ -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go.
-- If there's more, we need to split it up
local start, remaining= 1, #keys
local arg1 = bit32.bor(bit32.lshift(keyType, 8), blockNo)
--print("data",data)
--print("data len", #data)
print(("Testing block %d, keytype %d, with %d keys"):format(blockNo, keyType, n))
- local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
- arg1 = arg1,
- arg2 = 1,
- arg3 = n,
+ local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS,
+ arg1 = arg1,
+ arg2 = 1,
+ arg3 = n,
data = data}
local status = checkCommand(command)
if status then return status, blockNo end
for sector,_ in pairs(results) do
blockNo, keyA, keyB = unpack(_)
- print(("| %3d | %3d |%s|%s|"):format(sector, blockNo, keyA, keyB ))
+ print(("| %3d | %3d |%12s|%12s|"):format(sector, blockNo, keyA, keyB))
end
print("|--------------------------------------|")
end
+
-- A little helper to place an item first in the list
local function placeFirst(akey, list)
- akey = akey:lower()
- if list[1] == akey then
+ akey = akey:lower()
+ if list[1] == akey then
-- Already at pole position
return list
end
local result = {akey}
--print(("Putting '%s' first"):format(akey))
for i,v in ipairs(list) do
- if v ~= akey then
+ if v ~= akey then
result[#result+1] = v
end
end
return result
end
+
local function dumptofile(results)
local sector, blockNo, keyA, keyB,_
- if utils.confirm("Do you wish to save the keys to dumpfile?") then
+ if utils.confirm("Do you wish to save the keys to dumpfile?") then
local destination = utils.input("Select a filename to store to", "dumpkeys.bin")
local file = io.open(destination, "w")
- if file == nil then
+ if file == nil then
print("Could not write to file ", destination)
return
end
local key_a = ""
local key_b = ""
-
+
for sector,_ in pairs(results) do
blockNo, keyA, keyB = unpack(_)
key_a = key_a .. bin.pack("H",keyA);
end
-local function main( args)
+local function main(args)
print(desc);
- result, err = reader.read1443a(false, true)
+ result, err = reader.read14443a(false, true)
if not result then
print(err)
return
core.clearCommandBuffer()
local blockNo
local keyType = 0 -- A=0, B=1
- local numSectors = 16
+ local numSectors = 16
- 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.
+ 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
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"
+ elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
numSectors = 32
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
for sector=1,numSectors,1 do
--[[
- The mifare Classic 1k card has 16 sectors of 4 data blocks each.
+ 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.
+ 8 sectors consist of 16 data blocks.
--]]
- local blockNo = sector * 4 -1
-
+ local blockNo = sector * 4 - 1
+
if sector > 32 then
- blockNo = 32*4+ (sector-32)*16 -1
+ blockNo = 32*4 + (sector-32)*16 - 1
end
local keyA = checkBlock(blockNo, keys, 0)
- if keyA then keys = placeFirst(keyA, keys) end
+ if keyA then keys = placeFirst(keyA, keys) end
keyA = keyA or ""
local keyB = checkBlock(blockNo, keys, 1)
- if keyB then keys = placeFirst(keyB, keys) end
+ if keyB then keys = placeFirst(keyB, keys) end
keyB = keyB or ""
- result[sector] = {blockNo, keyA, keyB }
+ result[sector] = {blockNo, keyA, keyB}
-- Check if user aborted
if core.ukbhit() then
dumptofile(result)
end
-main( args)
-
+main(args)