Moved script libraries into lualibs/folder, and added a patch to include the folder in the LUA_PATH (a.k.a package.path). See http://proxmark.org/forum/viewtopic.php?id=1750 for more details

This commit is contained in:
martin.holst@gmail.com 2013-09-28 20:07:28 +00:00
commit 686f0a1794
5 changed files with 30 additions and 0 deletions

188
client/lualibs/commands.lua Normal file
View file

@ -0,0 +1,188 @@
--[[
These are command definitions. This file should correspond exactly to usb_cmd.h.
--]]
--// For the bootloader
local _commands = {
CMD_DEVICE_INFO = 0x0000,
CMD_SETUP_WRITE = 0x0001,
CMD_FINISH_WRITE = 0x0003,
CMD_HARDWARE_RESET = 0x0004,
CMD_START_FLASH = 0x0005,
CMD_NACK = 0x00fe,
CMD_ACK = 0x00ff,
--// For general mucking around
CMD_DEBUG_PRINT_STRING = 0x0100,
CMD_DEBUG_PRINT_INTEGERS = 0x0101,
CMD_DEBUG_PRINT_BYTES = 0x0102,
CMD_LCD_RESET = 0x0103,
CMD_LCD = 0x0104,
CMD_BUFF_CLEAR = 0x0105,
CMD_READ_MEM = 0x0106,
CMD_VERSION = 0x0107,
--// For low-frequency tags
CMD_READ_TI_TYPE = 0x0202,
CMD_WRITE_TI_TYPE = 0x0203,
CMD_DOWNLOADED_RAW_BITS_TI_TYPE = 0x0204,
CMD_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0205,
CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0206,
CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K = 0x0207,
CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K = 0x0208,
CMD_DOWNLOADED_SIM_SAMPLES_125K = 0x0209,
CMD_SIMULATE_TAG_125K = 0x020A,
CMD_HID_DEMOD_FSK = 0x020B,
CMD_HID_SIM_TAG = 0x020C,
CMD_SET_LF_DIVISOR = 0x020D,
CMD_LF_SIMULATE_BIDIR = 0x020E,
CMD_SET_ADC_MUX = 0x020F,
CMD_HID_CLONE_TAG = 0x0210,
CMD_EM410X_WRITE_TAG = 0x0211,
CMD_INDALA_CLONE_TAG = 0x0212,
--// for 224 bits UID
CMD_INDALA_CLONE_TAG_L = 0x0213,
CMD_T55XX_READ_BLOCK = 0x0214,
CMD_T55XX_WRITE_BLOCK = 0x0215,
CMD_T55XX_READ_TRACE = 0x0216,
CMD_PCF7931_READ = 0x0217,
CMD_EM4X_READ_WORD = 0x0218,
CMD_EM4X_WRITE_WORD = 0x0219,
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300,
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 = 0x0301,
CMD_READ_SRI512_TAG = 0x0303,
CMD_READ_SRIX4K_TAG = 0x0304,
CMD_READER_ISO_15693 = 0x0310,
CMD_SIMTAG_ISO_15693 = 0x0311,
CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 = 0x0312,
CMD_ISO_15693_COMMAND = 0x0313,
CMD_ISO_15693_COMMAND_DONE = 0x0314,
CMD_ISO_15693_FIND_AFI = 0x0315,
CMD_ISO_15693_DEBUG = 0x0316,
--// For Hitag2 transponders
CMD_SNOOP_HITAG = 0x0370,
CMD_SIMULATE_HITAG = 0x0371,
CMD_READER_HITAG = 0x0372,
CMD_SIMULATE_TAG_HF_LISTEN = 0x0380,
CMD_SIMULATE_TAG_ISO_14443 = 0x0381,
CMD_SNOOP_ISO_14443 = 0x0382,
CMD_SNOOP_ISO_14443a = 0x0383,
CMD_SIMULATE_TAG_ISO_14443a = 0x0384,
CMD_READER_ISO_14443a = 0x0385,
CMD_SIMULATE_TAG_LEGIC_RF = 0x0387,
CMD_READER_LEGIC_RF = 0x0388,
CMD_WRITER_LEGIC_RF = 0x0389,
CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
CMD_SNOOP_ICLASS = 0x0392,
CMD_SIMULATE_TAG_ICLASS = 0x0393,
CMD_READER_ICLASS = 0x0394,
--// For measurements of the antenna tuning
CMD_MEASURE_ANTENNA_TUNING = 0x0400,
CMD_MEASURE_ANTENNA_TUNING_HF = 0x0401,
CMD_MEASURED_ANTENNA_TUNING = 0x0410,
CMD_LISTEN_READER_FIELD = 0x0420,
--// For direct FPGA control
CMD_FPGA_MAJOR_MODE_OFF = 0x0500,
--// For mifare commands
CMD_MIFARE_SET_DBGMODE = 0x0600,
CMD_MIFARE_EML_MEMCLR = 0x0601,
CMD_MIFARE_EML_MEMSET = 0x0602,
CMD_MIFARE_EML_MEMGET = 0x0603,
CMD_MIFARE_EML_CARDLOAD = 0x0604,
CMD_MIFARE_EML_CSETBLOCK = 0x0605,
CMD_MIFARE_EML_CGETBLOCK = 0x0606,
CMD_SIMULATE_MIFARE_CARD = 0x0610,
CMD_READER_MIFARE = 0x0611,
CMD_MIFARE_NESTED = 0x0612,
CMD_MIFARE_READBL = 0x0620,
CMD_MIFARE_READSC = 0x0621,
CMD_MIFARE_WRITEBL = 0x0622,
CMD_MIFARE_CHKKEYS = 0x0623,
CMD_MIFARE_SNIFFER = 0x0630,
CMD_UNKNOWN = 0xFFFF,
}
local _reverse_lookup,k,v = {}
for k, v in pairs(_commands) do
_reverse_lookup[v] = k
end
_commands.tostring = function(command)
if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end
return ("Error, numeric argument expected, got : %s"):format(tostring(command))
end
Command = {
new = function(self, o)
local o = o or {} -- create object if user does not provide one
setmetatable(o, self) -- DIY inheritance a'la javascript
self.__index = self
o.cmd = o.cmd or _commands.CMD_UNKNOWN
--o.arg1 = "test"
o.arg1 = o.arg1 or 0
o.arg2 = o.arg2 or 0
o.arg3 = o.arg3 or 0
local data = o.data or "0"
if(type(data) == 'string') then
-- We need to check if it is correct length, otherwise pad it
local len = string.len(data)
if(len < 1024) then
--Should be 1024 hex characters to represent 512 bytes of data
data = data .. string.rep("0",1024 - len )
end
if(len > 1024) then
-- OOps, a bit too much data here
print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) )
--
data = data:sub(1,1024)
end
else
print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data)))
end
o.data = data
return o
end,
parse = function (packet)
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',packet)
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
end,
}
function Command:__tostring()
local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format(
_commands.tostring(self.cmd),
tostring(self.arg1),
tostring(self.arg2),
tostring(self.arg3),
tostring(self.data))
return output
end
function Command:getBytes()
--If a hex-string has been used
local data = self.data
local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
end
return _commands

107
client/lualibs/getopt.lua Normal file
View file

@ -0,0 +1,107 @@
--[[This file is an adaptation from the following source:
https://github.com/attractivechaos/klib/blob/master/lua/klib.lua
]]
--[[
The MIT License
Copyright (c) 2011, Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
local function split(txt)
local retval = {};
for i in string.gmatch(txt, "%S+") do
table.insert(retval,i)
end
return retval
end
-- Description: getopt() translated from the BSD getopt(); compatible with the default Unix getopt()
--[[ Example:
for o, a in os.getopt(arg, 'a:b') do
print(o, a)
end
]]--
local function getopt(args, ostr)
-- Modification to handle strings instead of tables:
if type(args) == 'string' then
args = split(args)
end
local arg, place = nil, 0;
return function ()
if place == 0 then -- update scanning pointer
place = 1
if #args == 0
or args[1]:sub(1, 1) ~= '-' then
place = 0; return nil end
if #args[1] >= 2 then
place = place + 1
if args[1]:sub(2, 2) == '-' then -- found "--"
place = 0
table.remove(args, 1);
return nil;
end
end
end
local optopt = args[1]:sub(place, place);
place = place + 1;
local oli = ostr:find(optopt);
if optopt == ':' or oli == nil then -- unknown option
if optopt == '-' then return nil end
if place > #args[1] then
table.remove(args, 1);
place = 0;
end
return '?';
end
oli = oli + 1;
if ostr:sub(oli, oli) ~= ':' then -- do not need argument
arg = nil;
if place > #args[1] then
table.remove(args, 1);
place = 0;
end
else -- need an argument
if place <= #args[1] then -- no white space
arg = args[1]:sub(place);
else
table.remove(args, 1);
if #args == 0 then -- an option requiring argument is the last one
place = 0;
if ostr:sub(1, 1) == ':' then return ':' end
return '?';
else arg = args[1] end
end
table.remove(args, 1);
place = 0;
end
return optopt, arg;
end
end
return { getopt = getopt }

View file

@ -0,0 +1,151 @@
local _keys = {
--[[
These keys are from the pm3 c-codebase.
--]]
'ffffffffffff', -- Default key (first key used by program if no user defined key)
'000000000000', -- Blank key
'a0a1a2a3a4a5', -- NFCForum MAD key
'b0b1b2b3b4b5',
'aabbccddeeff',
'4d3a99c351dd',
'1a982c7e459a',
'd3f7d3f7d3f7',
'714c5c886e97',
'587ee5f9350f',
'a0478cc39091',
'533cb6c723f6',
'8fd0a4f256e9',
--[[
The data below is taken form the Slurp project,
https://github.com/4ZM/slurp/blob/master/res/xml/mifare_default_keys.xml
released as GPLV3.
--]]
'000000000000', -- Default key
'ffffffffffff', -- Default key
'b0b1b2b3b4b5', -- Key from mfoc
'4d3a99c351dd', -- Key from mfoc
'1a982c7e459a', -- Key from mfoc
'aabbccddeeff', -- Key from mfoc
'714c5c886e97', -- Key from mfoc
'587ee5f9350f', -- Key from mfoc
'a0478cc39091', -- Key from mfoc
'533cb6c723f6', -- Key from mfoc
'8fd0a4f256e9', -- Key from mfoc
-- Data from: http://pastebin.com/wcTHXLZZ
'a64598a77478', -- RKF SL Key A
'26940b21ff5d', -- RKF SL Key A
'fc00018778f7', -- RKF SL Key A
'00000ffe2488', -- RKF SL Key B
'5c598c9c58b5', -- RKF SL Key B
'e4d2770a89be', -- RKF SL Key B
-- Data from: http://pastebin.com/svGjN30Q
'434f4d4d4f41', -- RKF JOJO GROUP Key A
'434f4d4d4f42', -- RKF JOJO GROUP Key B
'47524f555041', -- RKF JOJO GROUP Key A
'47524f555042', -- RKF JOJO GROUP Key B
'505249564141', -- RKF JOJO PRIVA Key A
'505249564142', -- RKF JOJO PRIVA Key B
-- Data from: http://pastebin.com/d7sSetef
'fc00018778f7', -- RKF Rejskort Danmark Key A
'00000ffe2488', -- RKF Rejskort Danmark Key B
'0297927c0f77', -- RKF Rejskort Danmark Key A
'ee0042f88840', -- RKF Rejskort Danmark Key B
'722bfcc5375f', -- RKF Rejskort Danmark Key A
'f1d83f964314', -- RKF Rejskort Danmark Key B
-- Data from: http://pastebin.com/pvJX0xVS
'54726176656C', -- Transport Key A
'776974687573', -- Transport Key B
'4AF9D7ADEBE4', -- Directory and event log Key A
'2BA9621E0A36', -- Directory and event log Key B
-- Data from: http://pastebin.com/Dnnc5dFC
-- New cards are not encrypted (MF Ultralight)
'fc00018778f7', -- Västtrafiken Key A
'00000ffe2488', -- Västtrafiken Key B
'0297927c0f77', -- Västtrafiken Key A
'ee0042f88840', -- Västtrafiken Key B
'54726176656c', -- Västtrafiken Key A
'776974687573', -- Västtrafiken Key B
-- Data from: http://pastebin.com/y3PDBWR1
'000000000001',
'a0a1a2a3a4a5',
'123456789abc',
'b127c6f41436',
'12f2ee3478c1',
'34d1df9934c5',
'55f5a5dd38c9',
'f1a97341a9fc',
'33f974b42769',
'14d446e33363',
'c934fe34d934',
'1999a3554a55',
'27dd91f1fcf1',
'a94133013401',
'99c636334433',
'43ab19ef5c31',
'a053a292a4af',
'434f4d4d4f41',
'434f4d4d4f42',
'505249565441',
'505249565442',
-- Data from,:, http://pastebin.com/TUXj17K3
'fc0001877bf7', -- RKF ÖstgötaTrafiken Key A
'00000ffe2488', -- RKF ÖstgötaTrafiken Key B
'0297927c0f77', -- RKF ÖstgötaTrafiken Key A
'ee0042f88840', -- RKF ÖstgötaTrafiken Key B
'54726176656c', -- RKF ÖstgötaTrafiken Key A
'776974687573', -- RKF ÖstgötaTrafiken Key B
--[[
The keys below are taken from from https://code.google.com/p/mifare-key-cracker/downloads/list
--]]
'bd493a3962b6',
'010203040506',
'111111111111',
'222222222222',
'333333333333',
'444444444444',
'555555555555',
'666666666666',
'777777777777',
'888888888888',
'999999999999',
'aaaaaaaaaaaa',
'bbbbbbbbbbbb',
'cccccccccccc',
'dddddddddddd',
'eeeeeeeeeeee',
'0123456789ab',
'123456789abc',
}
---
-- The keys above have just been pasted in, for completeness sake. They contain duplicates.
-- We need to weed the duplicates out before we expose the list to someone who actually wants to use them
-- @param list a list to do 'uniq' on
local function uniq(list)
local foobar = {}
--print("list length ", #list)
for _, value in pairs(list) do
value = value:lower()
if not foobar[value] then
foobar[value] = true
table.insert(foobar, value);
end
end
--print("final list length length ", #foobar)
return foobar
end
return uniq(_keys)

127
client/lualibs/read14a.lua Normal file
View file

@ -0,0 +1,127 @@
--[[
This is a library to read 14443a tags. It can be used something like this
local reader = require('read14a')
result, err = reader.read1443a()
if not result then
print(err)
return
end
print(result.name)
--]]
-- Loads the commands-library
local cmds = require('commands')
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local ISO14A_COMMAND = {
ISO14A_CONNECT = 1,
ISO14A_NO_DISCONNECT = 2,
ISO14A_APDU = 4,
ISO14A_RAW = 8,
ISO14A_REQUEST_TRIGGER = 0x10,
ISO14A_APPEND_CRC = 0x20,
ISO14A_SET_TIMEOUT = 0x40
}
local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k"
ISO14443a_TYPES[0x10] = "NXP MIFARE Plus 2k"
ISO14443a_TYPES[0x11] = "NXP MIFARE Plus 4k"
ISO14443a_TYPES[0x18] = "NXP MIFARE Classic 4k | Plus 4k"
ISO14443a_TYPES[0x20] = "NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"
ISO14443a_TYPES[0x24] = "NXP MIFARE DESFire | DESFire EV1"
ISO14443a_TYPES[0x28] = "JCOP31 or JCOP41 v2.3.1"
ISO14443a_TYPES[0x38] = "Nokia 6212 or 6131 MIFARE CLASSIC 4K"
ISO14443a_TYPES[0x88] = "Infineon MIFARE CLASSIC 1K"
ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
local function tostring_1443a(sak)
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
end
local function parse1443a(data)
--[[
Based on this struct :
typedef struct {
byte_t uid[10];
byte_t uidlen;
byte_t atqa[2];
byte_t sak;
byte_t ats_len;
byte_t ats[256];
} __attribute__((__packed__)) iso14a_card_select_t;
--]]
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)}
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
-- response of type CMD_ACK
-- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull
local function sendToDevice(command, ignoreresponse)
core.clearCommandBuffer()
local err = core.SendCommand(command:getBytes())
if err then
print(err)
return nil, err
end
if ignoreresponse then return nil,nil end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
return response,nil
end
local library = {
-- This function does a connect.
-- @param dont_disconnect - if true, does not disable the field
read1443a = function(dont_disconnect)
local command, result, info, err, data
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
end
local result,err = sendToDevice(command)
if result then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
if arg0 == 0 then
print("iso14443a card select failed");
return nil, "iso14443a card select failed"
end
data = string.sub(result,count)
info, err = parse1443a(data)
else
err ="No response from card"
end
if err then
print(err)
return nil, err
end
return info
end,
parse1443a = parse1443a,
sendToDevice = sendToDevice,
ISO14A_COMMAND = ISO14A_COMMAND,
}
return library