mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
lua: more fix mix of spaces & tabs
This commit is contained in:
parent
05ff45e550
commit
2d1a077ae4
14 changed files with 1423 additions and 1423 deletions
|
@ -1,78 +1,78 @@
|
|||
--[[
|
||||
local _errorcodes = {
|
||||
SW_NO_ERROR = 0x9000,
|
||||
SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining
|
||||
SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged =
|
||||
SW_WRONG_LENGTH = 0x6700, -- : Wrong length
|
||||
SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2)
|
||||
SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le)
|
||||
SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported
|
||||
SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported
|
||||
SW_UNKNOWN = 0x6F00, -- : No precise diagnosis
|
||||
SW_NO_ERROR = 0x9000,
|
||||
SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining
|
||||
SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged =
|
||||
SW_WRONG_LENGTH = 0x6700, -- : Wrong length
|
||||
SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2)
|
||||
SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le)
|
||||
SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported
|
||||
SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported
|
||||
SW_UNKNOWN = 0x6F00, -- : No precise diagnosis
|
||||
|
||||
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel
|
||||
SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging
|
||||
SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected
|
||||
SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported
|
||||
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel
|
||||
SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging
|
||||
SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected
|
||||
SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported
|
||||
|
||||
SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied
|
||||
SW_FILE_INVALID = 0x6983, -- : File invalid
|
||||
SW_DATA_INVALID = 0x6984, -- : Data invalid
|
||||
SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied
|
||||
SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF)
|
||||
SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed
|
||||
SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied
|
||||
SW_FILE_INVALID = 0x6983, -- : File invalid
|
||||
SW_DATA_INVALID = 0x6984, -- : Data invalid
|
||||
SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied
|
||||
SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF)
|
||||
SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed
|
||||
|
||||
SW_WRONG_DATA = 0x6A80, -- : Wrong data
|
||||
SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported
|
||||
SW_FILE_NOT_FOUND = 0x6A82, -- : File not found
|
||||
SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found
|
||||
SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file
|
||||
SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2)
|
||||
SW_WRONG_DATA = 0x6A80, -- : Wrong data
|
||||
SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported
|
||||
SW_FILE_NOT_FOUND = 0x6A82, -- : File not found
|
||||
SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found
|
||||
SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file
|
||||
SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2)
|
||||
}
|
||||
--]]
|
||||
local _errorcodes = {
|
||||
SW_NO_ERROR = '9000',
|
||||
SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining
|
||||
SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged =
|
||||
SW_WRONG_LENGTH = '6700', -- : Wrong length
|
||||
SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2)
|
||||
SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le)
|
||||
SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported
|
||||
SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported
|
||||
SW_UNKNOWN = '6F00', -- : No precise diagnosis
|
||||
SW_NO_ERROR = '9000',
|
||||
SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining
|
||||
SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged =
|
||||
SW_WRONG_LENGTH = '6700', -- : Wrong length
|
||||
SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2)
|
||||
SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le)
|
||||
SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported
|
||||
SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported
|
||||
SW_UNKNOWN = '6F00', -- : No precise diagnosis
|
||||
|
||||
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel
|
||||
SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging
|
||||
SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected
|
||||
SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported
|
||||
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel
|
||||
SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging
|
||||
SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected
|
||||
SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported
|
||||
|
||||
SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied
|
||||
SW_FILE_INVALID = '6983', -- : File invalid
|
||||
SW_DATA_INVALID = '6984', -- : Data invalid
|
||||
SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied
|
||||
SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF)
|
||||
SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed
|
||||
SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied
|
||||
SW_FILE_INVALID = '6983', -- : File invalid
|
||||
SW_DATA_INVALID = '6984', -- : Data invalid
|
||||
SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied
|
||||
SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF)
|
||||
SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed
|
||||
|
||||
SW_WRONG_DATA = '6A80', -- : Wrong data
|
||||
SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported
|
||||
SW_FILE_NOT_FOUND = '6A82', -- : File not found
|
||||
SW_RECORD_NOT_FOUND = '6A83', -- : Record not found
|
||||
SW_FILE_FULL = '6A84', -- : Not enough memory space in the file
|
||||
SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2)
|
||||
SW_WRONG_DATA = '6A80', -- : Wrong data
|
||||
SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported
|
||||
SW_FILE_NOT_FOUND = '6A82', -- : File not found
|
||||
SW_RECORD_NOT_FOUND = '6A83', -- : Record not found
|
||||
SW_FILE_FULL = '6A84', -- : Not enough memory space in the file
|
||||
SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2)
|
||||
}
|
||||
|
||||
local _reverse_lookup,k,v = {}
|
||||
for k, v in pairs(_errorcodes) do
|
||||
_reverse_lookup[v] = k
|
||||
_reverse_lookup[v] = k
|
||||
end
|
||||
|
||||
_errorcodes.tostring = function(command)
|
||||
if(type(command) == 'string') then
|
||||
return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command)
|
||||
end
|
||||
if(type(command) == 'number') then
|
||||
return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command)
|
||||
end
|
||||
return ("Error, numeric or string argument expected, got : %s"):format(tostring(command))
|
||||
if(type(command) == 'string') then
|
||||
return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command)
|
||||
end
|
||||
if(type(command) == 'number') then
|
||||
return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command)
|
||||
end
|
||||
return ("Error, numeric or string argument expected, got : %s"):format(tostring(command))
|
||||
end
|
||||
return _errorcodes
|
|
@ -1,73 +1,73 @@
|
|||
--[[
|
||||
Handle Proxmark USB Commands
|
||||
Handle Proxmark USB Commands
|
||||
--]]
|
||||
|
||||
local _commands = require('usb_cmd')
|
||||
|
||||
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))
|
||||
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)
|
||||
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
|
||||
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 = o.arg1 or 0
|
||||
o.arg2 = o.arg2 or 0
|
||||
o.arg3 = o.arg3 or 0
|
||||
local data = o.data or "0"
|
||||
o.cmd = o.cmd or _commands.CMD_UNKNOWN
|
||||
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('LLLLH511', packet)
|
||||
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
|
||||
end
|
||||
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('LLLLH511', 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
|
||||
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);
|
||||
--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
|
||||
|
|
|
@ -185,25 +185,25 @@ local _names = {
|
|||
|
||||
{"404", "9401", "0030", "earth", "legendary","Bash"},
|
||||
{"416", "a001", "0030", "magic", "legendary", "Spyro"},
|
||||
--{"", "", "0030", "magic", "legendary", "Deja Vu"},
|
||||
--{"", "", "0030", "magic", "legendary", "Deja Vu"},
|
||||
{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"},
|
||||
--{"", "", "0030", "tech", "legendary", "bouncer"},
|
||||
--{"", "", "0030", "tech", "legendary", "jawbreaker"},
|
||||
--{"", "", "0030", "tech", "legendary", "bouncer"},
|
||||
--{"", "", "0030", "tech", "legendary", "jawbreaker"},
|
||||
{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"},
|
||||
--{"", "", "0030", "undead", "legendary", "grim creeper"},
|
||||
--{"", "", "0030", "undead", "legendary", "night shift"},
|
||||
|
||||
--{"", "", "0030", "air", "legendary", "blades"},
|
||||
--{"", "", "0030", "air", "legendary", "jet vac"},
|
||||
--{"", "", "0030", "air", "legendary", "Free Ranger"},
|
||||
--{"", "", "0030", "life", "legendary", "stealth elf"},
|
||||
--{"", "", "0030", "life", "legendary", "Bushwhack"},
|
||||
--{"", "", "0030", "fire", "legendary", "ignitor"},
|
||||
--{"", "", "0030", "water", "legendary", "slam bam"},
|
||||
--{"", "", "0030", "water", "legendary", "chill"},
|
||||
--{"", "", "0030", "undead", "legendary", "grim creeper"},
|
||||
--{"", "", "0030", "undead", "legendary", "night shift"},
|
||||
|
||||
--{"", "", "0030", "air", "legendary", "blades"},
|
||||
--{"", "", "0030", "air", "legendary", "jet vac"},
|
||||
--{"", "", "0030", "air", "legendary", "Free Ranger"},
|
||||
--{"", "", "0030", "life", "legendary", "stealth elf"},
|
||||
--{"", "", "0030", "life", "legendary", "Bushwhack"},
|
||||
--{"", "", "0030", "fire", "legendary", "ignitor"},
|
||||
--{"", "", "0030", "water", "legendary", "slam bam"},
|
||||
--{"", "", "0030", "water", "legendary", "chill"},
|
||||
|
||||
--{"", "", "0030", "", "legendary", "zoo lou"},
|
||||
|
||||
--{"", "", "0030", "", "legendary", "zoo lou"},
|
||||
|
||||
{"450", "c201", "0030", "air", "trapmaster", "Gusto"},
|
||||
--{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"},
|
||||
{"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"},
|
||||
|
@ -453,23 +453,23 @@ local _names = {
|
|||
|
||||
local function find( main, sub)
|
||||
main = main:lower()
|
||||
sub = sub:lower()
|
||||
sub = sub:lower()
|
||||
for k, v in pairs(_names) do
|
||||
if ( v[2]:lower() == main and v[3]:lower() == sub) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return nil
|
||||
if ( v[2]:lower() == main and v[3]:lower() == sub) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
local function list()
|
||||
print ("Type\tSub\tElement\tGame Name")
|
||||
print (string.rep('=', 54))
|
||||
print ("Type\tSub\tElement\tGame Name")
|
||||
print (string.rep('=', 54))
|
||||
for k, v in pairs(_names) do
|
||||
print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] ))
|
||||
end
|
||||
print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] ))
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
Find = find,
|
||||
List = list,
|
||||
Find = find,
|
||||
List = list,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--[[
|
||||
decimal, di edition, model name
|
||||
--[[
|
||||
decimal, di edition, model name
|
||||
--]]
|
||||
local _names = {
|
||||
{"1000001","1","Mr. Incredible"},
|
||||
|
@ -319,8 +319,8 @@ local _names = {
|
|||
{"4000226","3","?? unknown ??"},
|
||||
{"4000227","3","?? unknown ??"},
|
||||
{"4000229","3","Quad Jumper"},
|
||||
--[[
|
||||
these below are Portals. Not to be used for tags.
|
||||
--[[
|
||||
these below are Portals. Not to be used for tags.
|
||||
--]]
|
||||
{"8032384","0","Infinity Base - 3DS"},
|
||||
{"8032385","0","Infinity Base - Xbox"},
|
||||
|
@ -332,21 +332,21 @@ local _names = {
|
|||
local function find( main )
|
||||
main = main:lower()
|
||||
for k, v in pairs(_names) do
|
||||
if ( v[1]:lower() == main ) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return nil
|
||||
if ( v[1]:lower() == main ) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
local function list()
|
||||
print ("Type\tEdition\t Model name")
|
||||
print (string.rep('=', 54))
|
||||
print ("Type\tEdition\t Model name")
|
||||
print (string.rep('=', 54))
|
||||
for k, v in pairs(_names) do
|
||||
print(("%s\t%s\t%s"):format(v[1],v[2],v[3] ))
|
||||
end
|
||||
print(("%s\t%s\t%s"):format(v[1],v[2],v[3] ))
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
Find = find,
|
||||
List = list,
|
||||
Find = find,
|
||||
List = list,
|
||||
}
|
||||
|
|
|
@ -7,19 +7,19 @@ 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
|
||||
|
@ -56,8 +56,8 @@ local function getopt(args, ostr)
|
|||
return function ()
|
||||
if place == 0 then -- update scanning pointer
|
||||
place = 1
|
||||
if #args == 0
|
||||
or args[1]:sub(1, 1) ~= '-' then
|
||||
if #args == 0
|
||||
or args[1]:sub(1, 1) ~= '-' then
|
||||
place = 0; return nil end
|
||||
if #args[1] >= 2 then
|
||||
place = place + 1
|
||||
|
@ -96,12 +96,12 @@ local function getopt(args, ostr)
|
|||
if ostr:sub(1, 1) == ':' then return ':' end
|
||||
return '?';
|
||||
else arg = args[1] end
|
||||
end
|
||||
table.remove(args, 1);
|
||||
place = 0;
|
||||
end
|
||||
end
|
||||
table.remove(args, 1);
|
||||
place = 0;
|
||||
end
|
||||
return optopt, arg;
|
||||
end
|
||||
end
|
||||
|
||||
return { getopt = getopt }
|
||||
return { getopt = getopt }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--[[
|
||||
THIS IS WORK IN PROGREESS, very much not finished.
|
||||
THIS IS WORK IN PROGREESS, very much not finished.
|
||||
|
||||
This library utilises other libraries under the hood, but can be used as a generic reader for 13.56MHz tags.
|
||||
This library utilises other libraries under the hood, but can be used as a generic reader for 13.56MHz tags.
|
||||
]]
|
||||
|
||||
local reader14443A = require('read14a')
|
||||
|
@ -10,26 +10,26 @@ local reader15693 = require('read15')
|
|||
|
||||
---
|
||||
-- This method library can be set waits or a 13.56 MHz tag, and when one is found, returns info about
|
||||
-- what tag it is.
|
||||
--
|
||||
-- what tag it is.
|
||||
--
|
||||
-- @return if successfull: an table containing card info
|
||||
-- @return if unsuccessfull : nil, error
|
||||
local function waitForTag()
|
||||
print("Waiting for card... press any key to quit")
|
||||
local readers = {reader14443A, reader14443B, reader15693}
|
||||
local i = 0;
|
||||
while not core.ukbhit() do
|
||||
i = (i % 3) +1
|
||||
r = readers[i]
|
||||
print("Reading with ",i)
|
||||
res, err = r.read()
|
||||
if res then return res end
|
||||
print(err)
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
print("Waiting for card... press any key to quit")
|
||||
local readers = {reader14443A, reader14443B, reader15693}
|
||||
local i = 0;
|
||||
while not core.ukbhit() do
|
||||
i = (i % 3) +1
|
||||
r = readers[i]
|
||||
print("Reading with ",i)
|
||||
res, err = r.read()
|
||||
if res then return res end
|
||||
print(err)
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
end
|
||||
|
||||
return {
|
||||
waitForTag = waitForTag,
|
||||
waitForTag = waitForTag,
|
||||
}
|
|
@ -2,154 +2,154 @@ bin = require('bin')
|
|||
|
||||
|
||||
-------------------------------
|
||||
-- Some utilities
|
||||
-- Some utilities
|
||||
-------------------------------
|
||||
|
||||
---
|
||||
---
|
||||
-- A debug printout-function
|
||||
local function dbg(args)
|
||||
|
||||
|
||||
if type(args) == "table" then
|
||||
local i = 1
|
||||
while args[i] do
|
||||
print("###", args[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
local i = 1
|
||||
while args[i] do
|
||||
print("###", args[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
local function oops(err)
|
||||
print("ERROR: ",err)
|
||||
return nil, err
|
||||
print("ERROR: ",err)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local function save_HTML(javascript, filename)
|
||||
|
||||
-- Read the HTML-skel file
|
||||
local skel = require("htmlskel")
|
||||
html = skel.getHTML(javascript);
|
||||
-- Read the HTML-skel file
|
||||
local skel = require("htmlskel")
|
||||
html = skel.getHTML(javascript);
|
||||
|
||||
-- Open the output file
|
||||
|
||||
local outfile = io.open(filename, "w")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
-- Write the data into it
|
||||
outfile:write(html)
|
||||
io.close(outfile)
|
||||
-- Open the output file
|
||||
|
||||
-- Done
|
||||
return filename
|
||||
local outfile = io.open(filename, "w")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
-- Write the data into it
|
||||
outfile:write(html)
|
||||
io.close(outfile)
|
||||
|
||||
-- Done
|
||||
return filename
|
||||
|
||||
end
|
||||
|
||||
local function save_TEXT(data,filename)
|
||||
-- Open the output file
|
||||
local outfile = io.open(filename, "w")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
|
||||
outfile:write(data)
|
||||
io.close(outfile)
|
||||
return filename
|
||||
-- Open the output file
|
||||
local outfile = io.open(filename, "w")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
|
||||
outfile:write(data)
|
||||
io.close(outfile)
|
||||
return filename
|
||||
end
|
||||
|
||||
local function save_BIN(data, filename)
|
||||
-- Open the output file
|
||||
|
||||
local outfile = io.open(filename, "wb")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
|
||||
-- Write the data into it
|
||||
local i = 1
|
||||
while data[i] do
|
||||
outfile:write(data[i])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
io.close(outfile)
|
||||
return filename
|
||||
-- Open the output file
|
||||
|
||||
local outfile = io.open(filename, "wb")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
|
||||
-- Write the data into it
|
||||
local i = 1
|
||||
while data[i] do
|
||||
outfile:write(data[i])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
io.close(outfile)
|
||||
return filename
|
||||
end
|
||||
|
||||
local function convert_ascii_dump_to_JS(infile)
|
||||
local t = infile:read("*all")
|
||||
local cleaned
|
||||
local output = "[";
|
||||
for line in string.gmatch(t, "[^\n]+") do
|
||||
if string.byte(line,1) ~= string.byte("+",1) then
|
||||
cleaned = (line or ''):gsub('%s+','')
|
||||
output = output .. "'"..cleaned.."',\n"
|
||||
local t = infile:read("*all")
|
||||
local cleaned
|
||||
local output = "[";
|
||||
for line in string.gmatch(t, "[^\n]+") do
|
||||
if string.byte(line,1) ~= string.byte("+",1) then
|
||||
cleaned = (line or ''):gsub('%s+','')
|
||||
output = output .. "'"..cleaned.."',\n"
|
||||
end
|
||||
end
|
||||
output = output .. "]"
|
||||
return output
|
||||
end
|
||||
output = output .. "]"
|
||||
return output
|
||||
end
|
||||
|
||||
local function convert_binary_dump_to_JS(infile, blockLen)
|
||||
local bindata = infile:read("*all")
|
||||
len = string.len(bindata)
|
||||
local bindata = infile:read("*all")
|
||||
len = string.len(bindata)
|
||||
|
||||
if len % blockLen ~= 0 then
|
||||
return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen))
|
||||
end
|
||||
if len % blockLen ~= 0 then
|
||||
return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen))
|
||||
end
|
||||
|
||||
local _,hex = bin.unpack(("H%d"):format(len),bindata)
|
||||
local _,hex = bin.unpack(("H%d"):format(len),bindata)
|
||||
|
||||
-- Now that we've converted binary data into hex, we doubled the size.
|
||||
-- One byte, like 0xDE is now
|
||||
-- the characters 'D' and 'E' : one byte each.
|
||||
-- Thus:
|
||||
blockLen = blockLen * 2
|
||||
-- Now that we've converted binary data into hex, we doubled the size.
|
||||
-- One byte, like 0xDE is now
|
||||
-- the characters 'D' and 'E' : one byte each.
|
||||
-- Thus:
|
||||
blockLen = blockLen * 2
|
||||
|
||||
local js,i = "[";
|
||||
for i = 1, string.len(hex),blockLen do
|
||||
js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n"
|
||||
end
|
||||
js = js .. "]"
|
||||
return js
|
||||
local js,i = "[";
|
||||
for i = 1, string.len(hex),blockLen do
|
||||
js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n"
|
||||
end
|
||||
js = js .. "]"
|
||||
return js
|
||||
end
|
||||
|
||||
local function convert_ascii_dump_to_BIN(infile)
|
||||
local t = infile:read("*all")
|
||||
local cleaned
|
||||
local output = {};
|
||||
for line in string.gmatch(t, "[^\n]+") do
|
||||
if string.byte(line) ~= string.byte("+") then
|
||||
cleaned = (line or ''):gsub('%s+','')
|
||||
for c in cleaned:gmatch('..') do
|
||||
output[#output+1] = string.char( tonumber(c,16) )
|
||||
end
|
||||
end
|
||||
end
|
||||
return output
|
||||
local t = infile:read("*all")
|
||||
local cleaned
|
||||
local output = {};
|
||||
for line in string.gmatch(t, "[^\n]+") do
|
||||
if string.byte(line) ~= string.byte("+") then
|
||||
cleaned = (line or ''):gsub('%s+','')
|
||||
for c in cleaned:gmatch('..') do
|
||||
output[#output+1] = string.char( tonumber(c,16) )
|
||||
end
|
||||
end
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Converts a .eml-file into a HTML/Javascript file.
|
||||
-- Converts a .eml-file into a HTML/Javascript file.
|
||||
-- @param input the file to convert
|
||||
-- @param output the file to write to
|
||||
-- @return the name of the new file.
|
||||
-- @return the name of the new file.
|
||||
local function convert_eml_to_html(input, output)
|
||||
input = input or 'dumpdata.eml'
|
||||
output = output or input .. 'html'
|
||||
input = input or 'dumpdata.eml'
|
||||
output = output or input .. 'html'
|
||||
|
||||
local infile = io.open(input, "r")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
local infile = io.open(input, "r")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
|
||||
-- Read file, get JS
|
||||
local javascript = convert_ascii_dump_to_JS(infile)
|
||||
io.close(infile)
|
||||
return save_HTML(javascript, output )
|
||||
-- Read file, get JS
|
||||
local javascript = convert_ascii_dump_to_JS(infile)
|
||||
io.close(infile)
|
||||
return save_HTML(javascript, output )
|
||||
end
|
||||
|
||||
--- Converts a binary dump into HTML/Javascript file
|
||||
|
@ -157,46 +157,46 @@ end
|
|||
-- @param output the file to write to
|
||||
-- @param blockLen, the length of each block. Defaults to 16 bytes
|
||||
local function convert_bin_to_html(input, output, blockLen)
|
||||
input = input or 'dumpdata.bin'
|
||||
blockLen = blockLen or 16
|
||||
output = output or input .. 'html'
|
||||
input = input or 'dumpdata.bin'
|
||||
blockLen = blockLen or 16
|
||||
output = output or input .. 'html'
|
||||
|
||||
local infile = io.open(input, "rb")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
-- Read file, get JS
|
||||
local javascript = convert_binary_dump_to_JS(infile, blockLen)
|
||||
io.close(infile)
|
||||
local infile = io.open(input, "rb")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
-- Read file, get JS
|
||||
local javascript = convert_binary_dump_to_JS(infile, blockLen)
|
||||
io.close(infile)
|
||||
|
||||
return save_HTML(javascript, output )
|
||||
return save_HTML(javascript, output )
|
||||
end
|
||||
|
||||
--- Converts a eml dump into a binary file
|
||||
-- @param input the file containing the eml-dump (defaults to dumpdata.eml)
|
||||
-- @param output the file to write to ( defaults to dumpdata.bin)
|
||||
local function convert_eml_to_bin(input, output)
|
||||
input = input or 'dumpdata.eml'
|
||||
output = output or 'dumpdata.bin'
|
||||
input = input or 'dumpdata.eml'
|
||||
output = output or 'dumpdata.bin'
|
||||
|
||||
local infile = io.open(input, "rb")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
-- Read file, get BIN
|
||||
local data = convert_ascii_dump_to_BIN(infile)
|
||||
io.close(infile)
|
||||
local infile = io.open(input, "rb")
|
||||
if infile == nil then
|
||||
return oops(string.format("Could not read file %s",tostring(input)))
|
||||
end
|
||||
-- Read file, get BIN
|
||||
local data = convert_ascii_dump_to_BIN(infile)
|
||||
io.close(infile)
|
||||
|
||||
return save_BIN(data, output )
|
||||
return save_BIN(data, output )
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
convert_bin_to_html = convert_bin_to_html,
|
||||
convert_eml_to_html = convert_eml_to_html,
|
||||
convert_eml_to_bin = convert_eml_to_bin,
|
||||
convert_bin_to_html = convert_bin_to_html,
|
||||
convert_eml_to_html = convert_eml_to_html,
|
||||
convert_eml_to_bin = convert_eml_to_bin,
|
||||
SaveAsBinary = save_BIN,
|
||||
SaveAsText = save_TEXT,
|
||||
SaveAsText = save_TEXT,
|
||||
SaveAsBinary = save_BIN,
|
||||
SaveAsText = save_TEXT,
|
||||
SaveAsText = save_TEXT,
|
||||
}
|
||||
|
|
|
@ -2,360 +2,360 @@ local skel_1 = [[
|
|||
<html>
|
||||
<head>
|
||||
|
||||
<script>
|
||||
var dictionary = {}
|
||||
function add(commaSeparated)
|
||||
{
|
||||
var fields = commaSeparated.split(",");
|
||||
var manufacturerCode = fields[0];
|
||||
var modelCode = fields[1];
|
||||
var modelSubCode= fields[2];
|
||||
var modelName = fields[3];
|
||||
var ATQA = fields[4];
|
||||
var SAK = fields[5];
|
||||
<script>
|
||||
var dictionary = {}
|
||||
function add(commaSeparated)
|
||||
{
|
||||
var fields = commaSeparated.split(",");
|
||||
var manufacturerCode = fields[0];
|
||||
var modelCode = fields[1];
|
||||
var modelSubCode= fields[2];
|
||||
var modelName = fields[3];
|
||||
var ATQA = fields[4];
|
||||
var SAK = fields[5];
|
||||
|
||||
//In the data below, wrong endian is used. Mifare is
|
||||
// written as "0004" instead of "0400", so we need to
|
||||
// flip it
|
||||
ATQA = ATQA.substr(2,4)+ATQA.substr(0,2)
|
||||
//In the data below, wrong endian is used. Mifare is
|
||||
// written as "0004" instead of "0400", so we need to
|
||||
// flip it
|
||||
ATQA = ATQA.substr(2,4)+ATQA.substr(0,2)
|
||||
|
||||
var info = {
|
||||
modelCode : modelCode,
|
||||
modelSubCode : modelSubCode,
|
||||
modelName : modelName,
|
||||
ATQA : ATQA,
|
||||
SAK : SAK
|
||||
}
|
||||
console.log("Adding "+modelName+" , "+SAK)
|
||||
var info = {
|
||||
modelCode : modelCode,
|
||||
modelSubCode : modelSubCode,
|
||||
modelName : modelName,
|
||||
ATQA : ATQA,
|
||||
SAK : SAK
|
||||
}
|
||||
console.log("Adding "+modelName+" , "+SAK)
|
||||
|
||||
dictionary[ATQA] = dictionary[ATQA] || [];
|
||||
dictionary[ATQA].push(info)
|
||||
}
|
||||
function lookup(atqa, sak)
|
||||
{
|
||||
if (!dictionary[atqa]) return "UNKNOWN";
|
||||
dictionary[ATQA] = dictionary[ATQA] || [];
|
||||
dictionary[ATQA].push(info)
|
||||
}
|
||||
function lookup(atqa, sak)
|
||||
{
|
||||
if (!dictionary[atqa]) return "UNKNOWN";
|
||||
|
||||
var possibleMatches = [];
|
||||
for(var i = 0 ; i < dictionary[atqa].length ; i++)
|
||||
{
|
||||
var possibleMatches = [];
|
||||
for(var i = 0 ; i < dictionary[atqa].length ; i++)
|
||||
{
|
||||
|
||||
var info = dictionary[atqa][i];
|
||||
console.log("Comparing "+sak+ " with "+ info.SAK);
|
||||
if(sak && info.SAK == sak)//exact match
|
||||
{
|
||||
return info.modelName;
|
||||
// possibleMatches.push(info.modelName);
|
||||
}else //SAK unknown
|
||||
{
|
||||
possibleMatches.push(info.modelName);
|
||||
}
|
||||
}
|
||||
if(possibleMatches.length > 0)
|
||||
return possibleMatches.join(" or ");
|
||||
return "UNKNOWN"
|
||||
}
|
||||
var info = dictionary[atqa][i];
|
||||
console.log("Comparing "+sak+ " with "+ info.SAK);
|
||||
if(sak && info.SAK == sak)//exact match
|
||||
{
|
||||
return info.modelName;
|
||||
// possibleMatches.push(info.modelName);
|
||||
}else //SAK unknown
|
||||
{
|
||||
possibleMatches.push(info.modelName);
|
||||
}
|
||||
}
|
||||
if(possibleMatches.length > 0)
|
||||
return possibleMatches.join(" or ");
|
||||
return "UNKNOWN"
|
||||
}
|
||||
|
||||
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
|
||||
add("04,,,Mifare Mini,0004,09");
|
||||
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
|
||||
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");
|
||||
add("04,,,Mifare Plus (4 byte UID) 4K SL2,0004,11");
|
||||
add("04,,,Mifare Plus (4 byte UID) 4K SL1,0004,18");
|
||||
add("04,,,Mifare Plus (4 byte UID) 2K/4K SL3,0004,20");
|
||||
add("04,,,Mifare Classic 4K,0002,18");
|
||||
add("xx,,,NDEF Tags,0044,00 ");
|
||||
add("04,,,Mifare Ultralight/UltralightC,0044,04");
|
||||
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0042,08");
|
||||
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0044,08");
|
||||
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0042,18");
|
||||
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0044,18");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,10");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,10");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,11");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,11");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,20");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,20");
|
||||
add("04,,,Mifare DesFire / DesFire EV1,0344,20067577810280");
|
||||
add("04,,,JCOP31,0304,283877B14A434F503331");
|
||||
add("04,,,JCOP31 v2.4.1,0048,207877B1024A434F5076323431");
|
||||
add("04,,,JCOP41 v2.2,0048,203833B14A434F503431563232");
|
||||
add("04,,,JCOP41 v2.3.1,0004,283833B14A434F50343156323331");
|
||||
add("05,,,Mifare Classic 1K,0004,88");
|
||||
add("40,,,MPCOS,0002,98");
|
||||
add("25,,,Topaz/Topaz512/Jewel,0C00,");
|
||||
add("1D,,,FM1208SH01,0004,53");
|
||||
add("1D,,,FM1208,0008,20");
|
||||
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6212,0002,38");
|
||||
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6131,0008,38");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0002");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0102");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0202");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0302");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0402");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0502");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0602");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0702");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0802");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0902");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0A02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0B02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0C02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0D02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0E02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0F02");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0004");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0104");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0204");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0304");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0404");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0504");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0604");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0704");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0804");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0904");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0A04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0B04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0C04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0D04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0E04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0F04");
|
||||
add("04,,,Smart MX with 7 byte UID,0048");
|
||||
add("04,,,Smart MX with 7 byte UID,0148");
|
||||
add("04,,,Smart MX with 7 byte UID,0248");
|
||||
add("04,,,Smart MX with 7 byte UID,0348");
|
||||
add("04,,,Smart MX with 7 byte UID,0448");
|
||||
add("04,,,Smart MX with 7 byte UID,0548");
|
||||
add("04,,,Smart MX with 7 byte UID,0648");
|
||||
add("04,,,Smart MX with 7 byte UID,0748");
|
||||
add("04,,,Smart MX with 7 byte UID,0848");
|
||||
add("04,,,Smart MX with 7 byte UID,0948");
|
||||
add("04,,,Smart MX with 7 byte UID,0A48");
|
||||
add("04,,,Smart MX with 7 byte UID,0B48");
|
||||
add("04,,,Smart MX with 7 byte UID,0C48");
|
||||
add("04,,,Smart MX with 7 byte UID,0D48");
|
||||
add("04,,,Smart MX with 7 byte UID,0E48");
|
||||
add("04,,,Smart MX with 7 byte UID,0F48");
|
||||
</script>
|
||||
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
|
||||
add("04,,,Mifare Mini,0004,09");
|
||||
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
|
||||
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");
|
||||
add("04,,,Mifare Plus (4 byte UID) 4K SL2,0004,11");
|
||||
add("04,,,Mifare Plus (4 byte UID) 4K SL1,0004,18");
|
||||
add("04,,,Mifare Plus (4 byte UID) 2K/4K SL3,0004,20");
|
||||
add("04,,,Mifare Classic 4K,0002,18");
|
||||
add("xx,,,NDEF Tags,0044,00 ");
|
||||
add("04,,,Mifare Ultralight/UltralightC,0044,04");
|
||||
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0042,08");
|
||||
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0044,08");
|
||||
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0042,18");
|
||||
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0044,18");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,10");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,10");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,11");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,11");
|
||||
add("04,,,Mifare Plus (7 byte UID),0042,20");
|
||||
add("04,,,Mifare Plus (7 byte UID),0044,20");
|
||||
add("04,,,Mifare DesFire / DesFire EV1,0344,20067577810280");
|
||||
add("04,,,JCOP31,0304,283877B14A434F503331");
|
||||
add("04,,,JCOP31 v2.4.1,0048,207877B1024A434F5076323431");
|
||||
add("04,,,JCOP41 v2.2,0048,203833B14A434F503431563232");
|
||||
add("04,,,JCOP41 v2.3.1,0004,283833B14A434F50343156323331");
|
||||
add("05,,,Mifare Classic 1K,0004,88");
|
||||
add("40,,,MPCOS,0002,98");
|
||||
add("25,,,Topaz/Topaz512/Jewel,0C00,");
|
||||
add("1D,,,FM1208SH01,0004,53");
|
||||
add("1D,,,FM1208,0008,20");
|
||||
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6212,0002,38");
|
||||
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6131,0008,38");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0002");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0102");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0202");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0302");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0402");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0502");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0602");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0702");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0802");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0902");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0A02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0B02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0C02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0D02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0E02");
|
||||
add("04,,,Smart MX with Mifare 4K emulation,0F02");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0004");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0104");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0204");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0304");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0404");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0504");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0604");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0704");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0804");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0904");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0A04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0B04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0C04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0D04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0E04");
|
||||
add("04,,,Smart MX with Mifare 1K emulation,0F04");
|
||||
add("04,,,Smart MX with 7 byte UID,0048");
|
||||
add("04,,,Smart MX with 7 byte UID,0148");
|
||||
add("04,,,Smart MX with 7 byte UID,0248");
|
||||
add("04,,,Smart MX with 7 byte UID,0348");
|
||||
add("04,,,Smart MX with 7 byte UID,0448");
|
||||
add("04,,,Smart MX with 7 byte UID,0548");
|
||||
add("04,,,Smart MX with 7 byte UID,0648");
|
||||
add("04,,,Smart MX with 7 byte UID,0748");
|
||||
add("04,,,Smart MX with 7 byte UID,0848");
|
||||
add("04,,,Smart MX with 7 byte UID,0948");
|
||||
add("04,,,Smart MX with 7 byte UID,0A48");
|
||||
add("04,,,Smart MX with 7 byte UID,0B48");
|
||||
add("04,,,Smart MX with 7 byte UID,0C48");
|
||||
add("04,,,Smart MX with 7 byte UID,0D48");
|
||||
add("04,,,Smart MX with 7 byte UID,0E48");
|
||||
add("04,,,Smart MX with 7 byte UID,0F48");
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
background-color: #2F3440;
|
||||
background-color:#232323;
|
||||
color : #F5E5C0;
|
||||
xtext-transform: uppercase;
|
||||
font-size: 1.05em;
|
||||
font-family: monospace,Arial;
|
||||
}
|
||||
table{
|
||||
float:left;
|
||||
border: 1px solid white;
|
||||
}
|
||||
td {
|
||||
empty-cells: show;
|
||||
}
|
||||
td.blockzero, .turqoise{
|
||||
color: rgb(140, 245, 193);
|
||||
}
|
||||
td.key_a, .yellow{
|
||||
color : #F8CA4D;
|
||||
}
|
||||
td.key_b, .blue{
|
||||
color : #3F5666;
|
||||
}
|
||||
td.accessconditions, .red{
|
||||
color : #EA6045;
|
||||
}
|
||||
|
||||
td.sectorhdr{
|
||||
border-top: 1px solid white;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
/** Jquery for the poor **/
|
||||
function dc(x){return document.createElement(x)}
|
||||
<style>
|
||||
* {
|
||||
background-color: #2F3440;
|
||||
background-color:#232323;
|
||||
color : #F5E5C0;
|
||||
xtext-transform: uppercase;
|
||||
font-size: 1.05em;
|
||||
font-family: monospace,Arial;
|
||||
}
|
||||
table{
|
||||
float:left;
|
||||
border: 1px solid white;
|
||||
}
|
||||
td {
|
||||
empty-cells: show;
|
||||
}
|
||||
td.blockzero, .turqoise{
|
||||
color: rgb(140, 245, 193);
|
||||
}
|
||||
td.key_a, .yellow{
|
||||
color : #F8CA4D;
|
||||
}
|
||||
td.key_b, .blue{
|
||||
color : #3F5666;
|
||||
}
|
||||
td.accessconditions, .red{
|
||||
color : #EA6045;
|
||||
}
|
||||
|
||||
function tr(table){
|
||||
var row = dc('tr');
|
||||
table.appendChild(row);
|
||||
return row;
|
||||
}
|
||||
function td(row, text){
|
||||
var tdata = dc('td');
|
||||
row.appendChild(tdata);
|
||||
tdata.appendChild(document.createTextNode(text))
|
||||
return tdata;
|
||||
}
|
||||
td.sectorhdr{
|
||||
border-top: 1px solid white;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
/** Jquery for the poor **/
|
||||
function dc(x){return document.createElement(x)}
|
||||
|
||||
/**
|
||||
* The identifiers that determine how to highlight data and present information
|
||||
**/
|
||||
var identifiers = [
|
||||
function(data)
|
||||
{
|
||||
// Should be 32 characters long ( 16 bytes per block)
|
||||
if(data[0].length != 32) { return false; }
|
||||
// ... add more checks if necessary ...
|
||||
function tr(table){
|
||||
var row = dc('tr');
|
||||
table.appendChild(row);
|
||||
return row;
|
||||
}
|
||||
function td(row, text){
|
||||
var tdata = dc('td');
|
||||
row.appendChild(tdata);
|
||||
tdata.appendChild(document.createTextNode(text))
|
||||
return tdata;
|
||||
}
|
||||
|
||||
var info = {Type : "Mifare"}
|
||||
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
|
||||
info['UID'] = data[0].substring(0,8);
|
||||
info['SAK'] = data[0].substring(10,12);
|
||||
info['ATQA'] = data[0].substring(12,16);
|
||||
/**
|
||||
* The identifiers that determine how to highlight data and present information
|
||||
**/
|
||||
var identifiers = [
|
||||
function(data)
|
||||
{
|
||||
// Should be 32 characters long ( 16 bytes per block)
|
||||
if(data[0].length != 32) { return false; }
|
||||
// ... add more checks if necessary ...
|
||||
|
||||
info['Name'] = lookup(info.ATQA, info.SAK);
|
||||
return {info: info, highlighter : mifareHighlighter }
|
||||
},
|
||||
function(data)
|
||||
{
|
||||
// Should be 8 characters long ( 4 bytes per block)
|
||||
if(data[0].length != 8) { return false; }
|
||||
// ... add more checks if necessary ...
|
||||
var info = {Type : "NDEF"}
|
||||
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
|
||||
var info = {Type : "Mifare"}
|
||||
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
|
||||
info['UID'] = data[0].substring(0,8);
|
||||
info['SAK'] = data[0].substring(10,12);
|
||||
info['ATQA'] = data[0].substring(12,16);
|
||||
|
||||
return {info: info, highlighter : ndefHighligheter }
|
||||
},
|
||||
info['Name'] = lookup(info.ATQA, info.SAK);
|
||||
return {info: info, highlighter : mifareHighlighter }
|
||||
},
|
||||
function(data)
|
||||
{
|
||||
// Should be 8 characters long ( 4 bytes per block)
|
||||
if(data[0].length != 8) { return false; }
|
||||
// ... add more checks if necessary ...
|
||||
var info = {Type : "NDEF"}
|
||||
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
|
||||
|
||||
function(data)
|
||||
{//This is the catch-all
|
||||
return {info: {type : "Unknown"}, highlighter : noHighlighter}
|
||||
}
|
||||
]
|
||||
|
||||
return {info: info, highlighter : ndefHighligheter }
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to convert bin-data into printable chars
|
||||
**/
|
||||
|
||||
function to_ascii(hexval)
|
||||
{
|
||||
var intval = parseInt(hexval,16);
|
||||
if(intval > 31 && intval < 127)
|
||||
{
|
||||
return String.fromCharCode(intval);
|
||||
}
|
||||
return ".";
|
||||
}
|
||||
function(data)
|
||||
{//This is the catch-all
|
||||
return {info: {type : "Unknown"}, highlighter : noHighlighter}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
function loadIntoTable(data, info, ascii)
|
||||
{
|
||||
var t = dc("table")
|
||||
for(var i = 0 ; i < data.length ; i++)
|
||||
{
|
||||
line = data[i];
|
||||
var row = tr(t);
|
||||
var bytes = line.match(/(.{1,2})/g);
|
||||
for(var b = 0 ; b < bytes.length ; b++)
|
||||
{
|
||||
var elem = td(row, ascii ? to_ascii(bytes[b]) : bytes[b]);
|
||||
info.highlighter.addClass(elem,i,b, bytes[b]);
|
||||
}
|
||||
}
|
||||
document.body.appendChild(t);
|
||||
}
|
||||
function loadGeneralInfo(data, info)
|
||||
{
|
||||
var t = dc("table");
|
||||
for (var key in info)
|
||||
{
|
||||
var row = tr(t);
|
||||
td(row,key);
|
||||
td(row,info[key]);
|
||||
}
|
||||
document.body.appendChild(t);
|
||||
}
|
||||
/**
|
||||
* Helper function to convert bin-data into printable chars
|
||||
**/
|
||||
|
||||
function handle(dump)
|
||||
{
|
||||
var data = dump.data;
|
||||
var info = null;
|
||||
for(var i = 0; i < identifiers.length && !info; i++)
|
||||
info = identifiers[i](data);
|
||||
function to_ascii(hexval)
|
||||
{
|
||||
var intval = parseInt(hexval,16);
|
||||
if(intval > 31 && intval < 127)
|
||||
{
|
||||
return String.fromCharCode(intval);
|
||||
}
|
||||
return ".";
|
||||
}
|
||||
|
||||
console.log(info);
|
||||
|
||||
loadIntoTable(data, info, false);
|
||||
loadIntoTable(data, info, true);
|
||||
loadGeneralInfo(data, info.info);
|
||||
function loadIntoTable(data, info, ascii)
|
||||
{
|
||||
var t = dc("table")
|
||||
for(var i = 0 ; i < data.length ; i++)
|
||||
{
|
||||
line = data[i];
|
||||
var row = tr(t);
|
||||
var bytes = line.match(/(.{1,2})/g);
|
||||
for(var b = 0 ; b < bytes.length ; b++)
|
||||
{
|
||||
var elem = td(row, ascii ? to_ascii(bytes[b]) : bytes[b]);
|
||||
info.highlighter.addClass(elem,i,b, bytes[b]);
|
||||
}
|
||||
}
|
||||
document.body.appendChild(t);
|
||||
}
|
||||
function loadGeneralInfo(data, info)
|
||||
{
|
||||
var t = dc("table");
|
||||
for (var key in info)
|
||||
{
|
||||
var row = tr(t);
|
||||
td(row,key);
|
||||
td(row,info[key]);
|
||||
}
|
||||
document.body.appendChild(t);
|
||||
}
|
||||
|
||||
}
|
||||
var noHighlighter = {
|
||||
addClass : function(el ,line, byte)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
var ndefHighligheter = {
|
||||
addClass : function(el ,line, byte, value)
|
||||
{
|
||||
if(line < 3)
|
||||
{
|
||||
el.className += " red";
|
||||
}
|
||||
if ( line == 3)
|
||||
{
|
||||
console.log(value);
|
||||
if( byte == 0 && "e1" == value.toLowerCase()) el.className += " turqoise";
|
||||
if( byte == 1 ) el.className += " yellow";
|
||||
if( byte == 2 ) el.className += " blue";
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
var mifareHighlighter = {
|
||||
addClass : function(el ,line, byte)
|
||||
{
|
||||
if (line == 0)
|
||||
{
|
||||
el.className += " blockzero";
|
||||
}
|
||||
|
||||
if(line < 128){
|
||||
linesPerSector = 4;
|
||||
} else {
|
||||
//Quadruple size sectors
|
||||
linesPerSector = 16;
|
||||
line = line - 128;
|
||||
}
|
||||
function handle(dump)
|
||||
{
|
||||
var data = dump.data;
|
||||
var info = null;
|
||||
for(var i = 0; i < identifiers.length && !info; i++)
|
||||
info = identifiers[i](data);
|
||||
|
||||
if(line % linesPerSector == 0)
|
||||
{
|
||||
el.className += " sectorhdr";
|
||||
}
|
||||
if(line % linesPerSector == (linesPerSector -1))
|
||||
{
|
||||
el.className += " sectortrailer";
|
||||
if(byte == undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
console.log(info);
|
||||
|
||||
if(byte < 6) el.className += " key_a";
|
||||
else if(byte < 10) el.className += " accessconditions";
|
||||
else el.className += " key_b";
|
||||
}
|
||||
loadIntoTable(data, info, false);
|
||||
loadIntoTable(data, info, true);
|
||||
loadGeneralInfo(data, info.info);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
var noHighlighter = {
|
||||
addClass : function(el ,line, byte)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
var ndefHighligheter = {
|
||||
addClass : function(el ,line, byte, value)
|
||||
{
|
||||
if(line < 3)
|
||||
{
|
||||
el.className += " red";
|
||||
}
|
||||
if ( line == 3)
|
||||
{
|
||||
console.log(value);
|
||||
if( byte == 0 && "e1" == value.toLowerCase()) el.className += " turqoise";
|
||||
if( byte == 1 ) el.className += " yellow";
|
||||
if( byte == 2 ) el.className += " blue";
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
var mifareHighlighter = {
|
||||
addClass : function(el ,line, byte)
|
||||
{
|
||||
if (line == 0)
|
||||
{
|
||||
el.className += " blockzero";
|
||||
}
|
||||
|
||||
if(line < 128){
|
||||
linesPerSector = 4;
|
||||
} else {
|
||||
//Quadruple size sectors
|
||||
linesPerSector = 16;
|
||||
line = line - 128;
|
||||
}
|
||||
|
||||
if(line % linesPerSector == 0)
|
||||
{
|
||||
el.className += " sectorhdr";
|
||||
}
|
||||
if(line % linesPerSector == (linesPerSector -1))
|
||||
{
|
||||
el.className += " sectortrailer";
|
||||
if(byte == undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(byte < 6) el.className += " key_a";
|
||||
else if(byte < 10) el.className += " accessconditions";
|
||||
else el.className += " key_b";
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body></body>
|
||||
<script>
|
||||
var x = { data :
|
||||
var x = { data :
|
||||
]]
|
||||
local skel_2 = [[
|
||||
|
||||
};
|
||||
handle(x);
|
||||
</script>
|
||||
|
||||
};
|
||||
handle(x);
|
||||
</script>
|
||||
</html>
|
||||
|
||||
]]
|
||||
local function getHTML(data)
|
||||
return skel_1 .. data .. skel_2
|
||||
return skel_1 .. data .. skel_2
|
||||
end
|
||||
|
||||
return {getHTML = getHTML}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--[[
|
||||
This is an experimental lib.
|
||||
This is an experimental lib.
|
||||
--]]
|
||||
local utils = require('utils')
|
||||
|
||||
|
@ -35,60 +35,60 @@ shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x
|
|||
shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
|
||||
|
||||
local function ApplyPermutationAndShifts( pos, value, nibble)
|
||||
local shiftbytes = shifts[pos]
|
||||
local shiftElem = shiftbytes[nibble+1] --one indexed
|
||||
local shiftOne = shiftbytes[1]
|
||||
local rs = bit32.bxor(value, shiftOne, shiftElem)
|
||||
return rs
|
||||
local shiftbytes = shifts[pos]
|
||||
local shiftElem = shiftbytes[nibble+1] --one indexed
|
||||
local shiftOne = shiftbytes[1]
|
||||
local rs = bit32.bxor(value, shiftOne, shiftElem)
|
||||
return rs
|
||||
end
|
||||
|
||||
local function GetOne( uid, block )
|
||||
|
||||
if uid == nil then return nil, 'empty uid string' end
|
||||
if #uid == 0 then return nil, 'empty uid string' end
|
||||
if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
|
||||
if type(block) ~= 'number' then return nil, 'block is not number' end
|
||||
if block > 16 or block < 0 then return nil, 'block is out-of-range' end
|
||||
|
||||
local s = ('%s%02X'):format(uid,block)
|
||||
local nibble1 = tonumber(s:sub(1,1),16) + 1
|
||||
if uid == nil then return nil, 'empty uid string' end
|
||||
if #uid == 0 then return nil, 'empty uid string' end
|
||||
if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
|
||||
if type(block) ~= 'number' then return nil, 'block is not number' end
|
||||
if block > 16 or block < 0 then return nil, 'block is out-of-range' end
|
||||
|
||||
local permuted = ''
|
||||
for i = 1, #s do
|
||||
local el_row = shifts[i]
|
||||
local el_value = el_row[nibble1]
|
||||
j = 1
|
||||
while j <= i do
|
||||
if i-j > 0 then
|
||||
local nibble = tonumber(s:sub(j+1,j+1),16)
|
||||
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
|
||||
end
|
||||
j = j+1
|
||||
end
|
||||
permuted =('%s%X'):format(permuted,el_value)
|
||||
end
|
||||
local s = ('%s%02X'):format(uid,block)
|
||||
local nibble1 = tonumber(s:sub(1,1),16) + 1
|
||||
|
||||
permuted = 'C2'..permuted
|
||||
local crc64numStr = utils.Crc64(permuted)
|
||||
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
|
||||
local key = utils.ConvertBytesToHex(keybytes)
|
||||
return key:sub(1,12)
|
||||
local permuted = ''
|
||||
for i = 1, #s do
|
||||
local el_row = shifts[i]
|
||||
local el_value = el_row[nibble1]
|
||||
j = 1
|
||||
while j <= i do
|
||||
if i-j > 0 then
|
||||
local nibble = tonumber(s:sub(j+1,j+1),16)
|
||||
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
|
||||
end
|
||||
j = j+1
|
||||
end
|
||||
permuted =('%s%X'):format(permuted,el_value)
|
||||
end
|
||||
|
||||
permuted = 'C2'..permuted
|
||||
local crc64numStr = utils.Crc64(permuted)
|
||||
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
|
||||
local key = utils.ConvertBytesToHex(keybytes)
|
||||
return key:sub(1,12)
|
||||
end
|
||||
|
||||
local PreCalc =
|
||||
local PreCalc =
|
||||
{
|
||||
GetAll = function(id)
|
||||
if id == nil then return nil, 'empty string' end
|
||||
if #id == 0 then return nil, 'empty string' end
|
||||
if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
|
||||
|
||||
local list = '4b0b20107ccb'
|
||||
for i = 1,15 do
|
||||
local key, err = GetOne(id,i)
|
||||
if not key then return oops(err) end
|
||||
list = list..key
|
||||
end
|
||||
return list
|
||||
end,
|
||||
GetAll = function(id)
|
||||
if id == nil then return nil, 'empty string' end
|
||||
if #id == 0 then return nil, 'empty string' end
|
||||
if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
|
||||
|
||||
local list = '4b0b20107ccb'
|
||||
for i = 1,15 do
|
||||
local key, err = GetOne(id,i)
|
||||
if not key then return oops(err) end
|
||||
list = list..key
|
||||
end
|
||||
return list
|
||||
end,
|
||||
}
|
||||
return PreCalc
|
|
@ -1,32 +1,32 @@
|
|||
--[[
|
||||
This is a library to read 14443a tags. It can be used something like this
|
||||
This is a library to read 14443a tags. It can be used something like this
|
||||
|
||||
local reader = require('read14a')
|
||||
result, err = reader.read14443a()
|
||||
if not result then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print(result.name)
|
||||
local reader = require('read14a')
|
||||
result, err = reader.read14443a()
|
||||
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,
|
||||
ISO14A_NO_SELECT = 0x80,
|
||||
ISO14A_TOPAZMODE = 0x100,
|
||||
ISO14A_NO_RATS = 0x200
|
||||
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,
|
||||
ISO14A_NO_SELECT = 0x80,
|
||||
ISO14A_TOPAZMODE = 0x100,
|
||||
ISO14A_NO_RATS = 0x200
|
||||
}
|
||||
|
||||
local ISO14443a_TYPES = {}
|
||||
local ISO14443a_TYPES = {}
|
||||
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C | NTAG"
|
||||
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
|
||||
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
|
||||
|
@ -45,50 +45,50 @@ ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
|
|||
|
||||
|
||||
local function tostring_14443a(sak)
|
||||
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
|
||||
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
|
||||
end
|
||||
|
||||
local function parse14443a(data)
|
||||
--[[
|
||||
--[[
|
||||
|
||||
Based on this struct :
|
||||
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;
|
||||
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_14443a(sak), data = data}
|
||||
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_14443a(sak), data = data}
|
||||
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
|
||||
-- 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
|
||||
--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
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||
return response,nil
|
||||
end
|
||||
|
||||
-- This function does a connect and retrieves som einfo
|
||||
|
@ -96,34 +96,34 @@ end
|
|||
-- @return if successfull: an table containing card info
|
||||
-- @return if unsuccessfull : nil, error
|
||||
local function read14443a(dont_disconnect, no_rats)
|
||||
local command, result, info, err, data
|
||||
local command, result, info, err, data
|
||||
|
||||
command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT }
|
||||
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
|
||||
if no_rats then
|
||||
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS
|
||||
end
|
||||
|
||||
local result,err = sendToDevice(command)
|
||||
if result then
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||
if arg0 == 0 then
|
||||
return nil, "iso14443a card select failed"
|
||||
end
|
||||
data = string.sub(result,count)
|
||||
info, err = parse14443a(data)
|
||||
else
|
||||
err ="No response from card"
|
||||
end
|
||||
if dont_disconnect then
|
||||
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||
end
|
||||
if no_rats then
|
||||
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS
|
||||
end
|
||||
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
local result,err = sendToDevice(command)
|
||||
if result then
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||
if arg0 == 0 then
|
||||
return nil, "iso14443a card select failed"
|
||||
end
|
||||
data = string.sub(result,count)
|
||||
info, err = parse14443a(data)
|
||||
else
|
||||
err ="No response from card"
|
||||
end
|
||||
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
end
|
||||
|
||||
---
|
||||
|
@ -131,20 +131,20 @@ end
|
|||
-- @return if successfull: an table containing card info
|
||||
-- @return if unsuccessfull : nil, error
|
||||
local function waitFor14443a()
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read14443a()
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read14443a()
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
end
|
||||
local library = {
|
||||
read = read14443a,
|
||||
waitFor14443a = waitFor14443a,
|
||||
parse14443a = parse14443a,
|
||||
sendToDevice = sendToDevice,
|
||||
ISO14A_COMMAND = ISO14A_COMMAND,
|
||||
read = read14443a,
|
||||
waitFor14443a = waitFor14443a,
|
||||
parse14443a = parse14443a,
|
||||
sendToDevice = sendToDevice,
|
||||
ISO14A_COMMAND = ISO14A_COMMAND,
|
||||
}
|
||||
|
||||
return library
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
--[[
|
||||
This is a library to read 14443b tags. It can be used something like this
|
||||
This is a library to read 14443b tags. It can be used something like this
|
||||
|
||||
local reader = require('read14b')
|
||||
result, err = reader.select1443b()
|
||||
if not result then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print(result.name)
|
||||
local reader = require('read14b')
|
||||
result, err = reader.select1443b()
|
||||
if not result then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print(result.name)
|
||||
|
||||
--]]
|
||||
-- Loads the commands-library
|
||||
|
@ -15,68 +15,68 @@ local cmds = require('commands')
|
|||
local utils = require('utils')
|
||||
local TIMEOUT = 2500
|
||||
local ISO14B_COMMAND = {
|
||||
ISO14B_CONNECT = 1,
|
||||
ISO14B_DISCONNECT = 2,
|
||||
ISO14B_APDU = 4,
|
||||
ISO14B_RAW = 8,
|
||||
ISO14B_REQUEST_TRIGGER = 0x10,
|
||||
ISO14B_APPEND_CRC = 0x20,
|
||||
ISO14B_SELECT_STD = 0x40,
|
||||
ISO14B_SELECT_SR = 0x80,
|
||||
ISO14B_CONNECT = 1,
|
||||
ISO14B_DISCONNECT = 2,
|
||||
ISO14B_APDU = 4,
|
||||
ISO14B_RAW = 8,
|
||||
ISO14B_REQUEST_TRIGGER = 0x10,
|
||||
ISO14B_APPEND_CRC = 0x20,
|
||||
ISO14B_SELECT_STD = 0x40,
|
||||
ISO14B_SELECT_SR = 0x80,
|
||||
}
|
||||
|
||||
local function parse1443b(data)
|
||||
--[[
|
||||
|
||||
Based on this struct :
|
||||
|
||||
typedef struct {
|
||||
byte_t uid[10];
|
||||
byte_t uidlen;
|
||||
byte_t atqb[7];
|
||||
byte_t chipid;
|
||||
byte_t cid;
|
||||
} __attribute__((__packed__)) iso14b_card_select_t;
|
||||
--[[
|
||||
|
||||
--]]
|
||||
|
||||
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
|
||||
uid = uid:sub(1, 2*uidlen)
|
||||
return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid }
|
||||
Based on this struct :
|
||||
|
||||
typedef struct {
|
||||
byte_t uid[10];
|
||||
byte_t uidlen;
|
||||
byte_t atqb[7];
|
||||
byte_t chipid;
|
||||
byte_t cid;
|
||||
} __attribute__((__packed__)) iso14b_card_select_t;
|
||||
|
||||
--]]
|
||||
|
||||
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
|
||||
uid = uid:sub(1, 2*uidlen)
|
||||
return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid }
|
||||
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
|
||||
-- @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(cmd, ignoreresponse)
|
||||
--core.clearCommandBuffer()
|
||||
local bytes = cmd:getBytes()
|
||||
local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes)
|
||||
local err = core.SendCommand(cmd:getBytes())
|
||||
if err then
|
||||
print('ERROR',err)
|
||||
return nil, err
|
||||
end
|
||||
if ignoreresponse then return nil,nil end
|
||||
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||
return response,nil
|
||||
--core.clearCommandBuffer()
|
||||
local bytes = cmd:getBytes()
|
||||
local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes)
|
||||
local err = core.SendCommand(cmd:getBytes())
|
||||
if err then
|
||||
print('ERROR',err)
|
||||
return nil, err
|
||||
end
|
||||
if ignoreresponse then return nil,nil end
|
||||
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||
return response,nil
|
||||
end
|
||||
--- Picks out and displays the data read from a tag
|
||||
-- Specifically, takes a usb packet, converts to a Command
|
||||
-- (as in commands.lua), takes the data-array and
|
||||
-- (as in commands.lua), takes the data-array and
|
||||
-- reads the number of bytes specified in arg1 (arg0 in c-struct)
|
||||
-- and displays the data
|
||||
-- @param usbpacket the data received from the device
|
||||
local function showData(usbpacket)
|
||||
local response = Command.parse(usbpacket)
|
||||
local len = response.arg2 * 2
|
||||
local data = string.sub(response.data, 0, len);
|
||||
print("<< ",data)
|
||||
local response = Command.parse(usbpacket)
|
||||
local len = response.arg2 * 2
|
||||
local data = string.sub(response.data, 0, len);
|
||||
print("<< ",data)
|
||||
end
|
||||
|
||||
|
||||
|
@ -85,74 +85,74 @@ end
|
|||
-- @return if unsuccessfull : nil, error
|
||||
local function read14443b(disconnect)
|
||||
|
||||
local command, result, info, err, data
|
||||
local command, result, info, err, data
|
||||
|
||||
local flags = ISO14B_COMMAND.ISO14B_CONNECT +
|
||||
ISO14B_COMMAND.ISO14B_SELECT_STD
|
||||
|
||||
if disconnect then
|
||||
print('DISCONNECT')
|
||||
flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
|
||||
end
|
||||
local flags = ISO14B_COMMAND.ISO14B_CONNECT +
|
||||
ISO14B_COMMAND.ISO14B_SELECT_STD
|
||||
|
||||
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
||||
local result, err = sendToDevice(command, false)
|
||||
if result then
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||
if arg0 == 0 then
|
||||
data = string.sub(result, count)
|
||||
info, err = parse1443b(data)
|
||||
else
|
||||
err = "iso14443b card select failed"
|
||||
end
|
||||
else
|
||||
err = "No response from card"
|
||||
end
|
||||
if disconnect then
|
||||
print('DISCONNECT')
|
||||
flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
|
||||
end
|
||||
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
|
||||
local result, err = sendToDevice(command, false)
|
||||
if result then
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||
if arg0 == 0 then
|
||||
data = string.sub(result, count)
|
||||
info, err = parse1443b(data)
|
||||
else
|
||||
err = "iso14443b card select failed"
|
||||
end
|
||||
else
|
||||
err = "No response from card"
|
||||
end
|
||||
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
end
|
||||
--PING / PONG - Custom Anticollison for Navigo.
|
||||
-- AA / BB ?!?
|
||||
-- local ping = ('BA00')
|
||||
-- result, err = sendRaw(ping, 1, 1)
|
||||
-- if result then
|
||||
-- resp = Command.parse( result )
|
||||
-- if arg1 == 0 then
|
||||
-- return nil, "iso14443b card - PING/PONG failed"
|
||||
-- end
|
||||
-- showData(result)
|
||||
-- resp = Command.parse( result )
|
||||
-- if arg1 == 0 then
|
||||
-- return nil, "iso14443b card - PING/PONG failed"
|
||||
-- end
|
||||
-- showData(result)
|
||||
-- else
|
||||
-- err = "No response from card"
|
||||
-- print(err)
|
||||
-- return nil, err
|
||||
-- err = "No response from card"
|
||||
-- print(err)
|
||||
-- return nil, err
|
||||
-- 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 waitFor14443b()
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read14443b(false)
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read14443b(false)
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
end
|
||||
|
||||
local library = {
|
||||
read = read14443b,
|
||||
waitFor14443b = waitFor14443b,
|
||||
parse1443b = parse1443b,
|
||||
sendToDevice = sendToDevice,
|
||||
showData = showData,
|
||||
ISO14B_COMMAND = ISO14B_COMMAND,
|
||||
read = read14443b,
|
||||
waitFor14443b = waitFor14443b,
|
||||
parse1443b = parse1443b,
|
||||
sendToDevice = sendToDevice,
|
||||
showData = showData,
|
||||
ISO14B_COMMAND = ISO14B_COMMAND,
|
||||
}
|
||||
|
||||
return library
|
|
@ -1,13 +1,13 @@
|
|||
--[[
|
||||
This is a library to read 15693 tags. It can be used something like this
|
||||
This is a library to read 15693 tags. It can be used something like this
|
||||
|
||||
local reader = require('read15')
|
||||
local info, err = reader.read()
|
||||
if not info then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print(info.UID)
|
||||
local reader = require('read15')
|
||||
local info, err = reader.read()
|
||||
if not info then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print(info.UID)
|
||||
|
||||
--]]
|
||||
-- Loads the commands-library
|
||||
|
@ -19,60 +19,60 @@ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
|||
--- 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
|
||||
-- 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)
|
||||
local err = core.SendCommand(command:getBytes())
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
if ignoreresponse then return nil, nil end
|
||||
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
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
|
||||
return response, nil
|
||||
end
|
||||
|
||||
local function errorString15693(number)
|
||||
local errors = {}
|
||||
errors[0x01] = "The command is not supported"
|
||||
errors[0x02] = "The command is not recognised"
|
||||
errors[0x03] = "The option is not supported."
|
||||
errors[0x0f] = "Unknown error."
|
||||
errors[0x10] = "The specified block is not available (doesn’t exist)."
|
||||
errors[0x11] = "The specified block is already -locked and thus cannot be locked again"
|
||||
errors[0x12] = "The specified block is locked and its content cannot be changed."
|
||||
errors[0x13] = "The specified block was not successfully programmed."
|
||||
errors[0x14] = "The specified block was not successfully locked."
|
||||
|
||||
return errors[number] or "Reserved for Future Use or Custom command error."
|
||||
local errors = {}
|
||||
errors[0x01] = "The command is not supported"
|
||||
errors[0x02] = "The command is not recognised"
|
||||
errors[0x03] = "The option is not supported."
|
||||
errors[0x0f] = "Unknown error."
|
||||
errors[0x10] = "The specified block is not available (doesn’t exist)."
|
||||
errors[0x11] = "The specified block is already -locked and thus cannot be locked again"
|
||||
errors[0x12] = "The specified block is locked and its content cannot be changed."
|
||||
errors[0x13] = "The specified block was not successfully programmed."
|
||||
errors[0x14] = "The specified block was not successfully locked."
|
||||
|
||||
return errors[number] or "Reserved for Future Use or Custom command error."
|
||||
end
|
||||
|
||||
|
||||
local function parse15693(data)
|
||||
local bytes = utils.ConvertAsciiToBytes(data)
|
||||
local tmp = utils.ConvertAsciiToHex(data)
|
||||
|
||||
-- define ISO15_CRC_CHECK 0F47
|
||||
local crcStr = utils.Crc15(tmp, #tmp)
|
||||
local bytes = utils.ConvertAsciiToBytes(data)
|
||||
local tmp = utils.ConvertAsciiToHex(data)
|
||||
|
||||
if string.sub(crcStr, #crcStr - 3) ~= '470F' then
|
||||
print("CRC", crc )
|
||||
return nil, "CRC failed"
|
||||
end
|
||||
-- define ISO15_CRC_CHECK 0F47
|
||||
local crcStr = utils.Crc15(tmp, #tmp)
|
||||
|
||||
if bytes[1] % 2 == 1 then
|
||||
-- Above is a poor-mans bit check:
|
||||
-- recv[0] & ISO15_RES_ERROR //(0x01)
|
||||
local err = "Tag returned error %i: %s"
|
||||
err = string.format(err, bytes[1], errorString15693(bytes[1]))
|
||||
return nil, err
|
||||
end
|
||||
local uid = utils.ConvertBytesToHex( bytes, true )
|
||||
uid = uid:sub(5, #uid-4)
|
||||
return { uid = uid, }
|
||||
if string.sub(crcStr, #crcStr - 3) ~= '470F' then
|
||||
print("CRC", crc )
|
||||
return nil, "CRC failed"
|
||||
end
|
||||
|
||||
if bytes[1] % 2 == 1 then
|
||||
-- Above is a poor-mans bit check:
|
||||
-- recv[0] & ISO15_RES_ERROR //(0x01)
|
||||
local err = "Tag returned error %i: %s"
|
||||
err = string.format(err, bytes[1], errorString15693(bytes[1]))
|
||||
return nil, err
|
||||
end
|
||||
local uid = utils.ConvertBytesToHex( bytes, true )
|
||||
uid = uid:sub(5, #uid-4)
|
||||
return { uid = uid, }
|
||||
end
|
||||
|
||||
-- This function does a connect and retrieves som info
|
||||
|
@ -83,62 +83,62 @@ local function read15693(slow, dont_readresponse)
|
|||
|
||||
--[[
|
||||
|
||||
We start by trying this command:
|
||||
MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one):
|
||||
|
||||
pm3> hf 15 info u
|
||||
UID=E007C1A257394244
|
||||
Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit
|
||||
pm3>
|
||||
|
||||
From which we obtain less information than the above one.
|
||||
|
||||
"260100" means
|
||||
0x26
|
||||
-- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK)
|
||||
-- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate
|
||||
-- #define ISO15_REQ_NONINVENTORY 0x00
|
||||
0x01
|
||||
inventory
|
||||
0x00
|
||||
|
||||
--]]
|
||||
We start by trying this command:
|
||||
MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one):
|
||||
|
||||
local command, result, info, err, data
|
||||
pm3> hf 15 info u
|
||||
UID=E007C1A257394244
|
||||
Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit
|
||||
pm3>
|
||||
|
||||
data = utils.Crc15("260100")
|
||||
From which we obtain less information than the above one.
|
||||
|
||||
command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND,
|
||||
arg1 = #data / 2,
|
||||
arg2 = 1,
|
||||
arg3 = 1,
|
||||
data = data}
|
||||
|
||||
if slow then
|
||||
command.arg2 = 0
|
||||
end
|
||||
if dont_readresponse then
|
||||
command.arg3 = 0
|
||||
end
|
||||
|
||||
local result, err = sendToDevice(command, dont_readresponse)
|
||||
if not result then
|
||||
print(err)
|
||||
return nil, "15693 identify: no answer"
|
||||
end
|
||||
|
||||
local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result)
|
||||
if len > 0 then
|
||||
data = string.sub(result, count, count+len-1)
|
||||
info, err = parse15693(data)
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
else
|
||||
return nil, "Failed to get response"
|
||||
end
|
||||
"260100" means
|
||||
0x26
|
||||
-- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK)
|
||||
-- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate
|
||||
-- #define ISO15_REQ_NONINVENTORY 0x00
|
||||
0x01
|
||||
inventory
|
||||
0x00
|
||||
|
||||
--]]
|
||||
|
||||
local command, result, info, err, data
|
||||
|
||||
data = utils.Crc15("260100")
|
||||
|
||||
command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND,
|
||||
arg1 = #data / 2,
|
||||
arg2 = 1,
|
||||
arg3 = 1,
|
||||
data = data}
|
||||
|
||||
if slow then
|
||||
command.arg2 = 0
|
||||
end
|
||||
if dont_readresponse then
|
||||
command.arg3 = 0
|
||||
end
|
||||
|
||||
local result, err = sendToDevice(command, dont_readresponse)
|
||||
if not result then
|
||||
print(err)
|
||||
return nil, "15693 identify: no answer"
|
||||
end
|
||||
|
||||
local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result)
|
||||
if len > 0 then
|
||||
data = string.sub(result, count, count+len-1)
|
||||
info, err = parse15693(data)
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
else
|
||||
return nil, "Failed to get response"
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
|
@ -146,19 +146,19 @@ end
|
|||
-- @return if successfull: an table containing card info
|
||||
-- @return if unsuccessfull : nil, error
|
||||
local function waitFor15693()
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read15693()
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
print("Waiting for card... press any key to quit")
|
||||
while not core.ukbhit() do
|
||||
res, err = read15693()
|
||||
if res then return res end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, "Aborted by user"
|
||||
end
|
||||
local library = {
|
||||
read = read15693,
|
||||
waitFor15693 = waitFor15693,
|
||||
parse15693 = parse15693,
|
||||
sendToDevice = sendToDevice,
|
||||
read = read15693,
|
||||
waitFor15693 = waitFor15693,
|
||||
parse15693 = parse15693,
|
||||
sendToDevice = sendToDevice,
|
||||
}
|
||||
|
||||
return library
|
||||
|
|
|
@ -109,16 +109,16 @@ m[0x6B]='ISSM France'
|
|||
m[0x6C]='Wisesec Ltd Israel'
|
||||
m[0x7C]='DB HiTek Co Ltd Korea'
|
||||
m[0x7D]='SATO Vicinity Australia'
|
||||
m[0x7E]='Holtek Taiwan'
|
||||
m[0x7E]='Holtek Taiwan'
|
||||
|
||||
return {
|
||||
lookupManufacturer = function (value)
|
||||
if type(value) == 'string' then
|
||||
local v = tonumber(value, 16)
|
||||
print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v))
|
||||
value = v
|
||||
end
|
||||
lookupManufacturer = function (value)
|
||||
if type(value) == 'string' then
|
||||
local v = tonumber(value, 16)
|
||||
print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v))
|
||||
value = v
|
||||
end
|
||||
|
||||
return m[value] or "no tag-info available"
|
||||
end,
|
||||
return m[value] or "no tag-info available"
|
||||
end,
|
||||
}
|
|
@ -1,430 +1,430 @@
|
|||
--[[
|
||||
This may be moved to a separate library at some point (Holiman)
|
||||
--]]
|
||||
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,
|
||||
|
||||
------------ FILE READING
|
||||
ReadDumpFile = function (filename)
|
||||
|
||||
filename = filename or 'dumpdata.bin'
|
||||
if #filename == 0 then
|
||||
return nil, 'Filename length is zero'
|
||||
end
|
||||
|
||||
infile = io.open(filename, "rb")
|
||||
if infile == nil then
|
||||
return nil, string.format("Could not read file %s",filename)
|
||||
end
|
||||
local t = infile:read("*all")
|
||||
io.close(infile)
|
||||
len = string.len(t)
|
||||
local _,hex = bin.unpack(("H%d"):format(len),t)
|
||||
return hex
|
||||
end,
|
||||
|
||||
------------ FILE WRITING (EML)
|
||||
--- Writes an eml-file.
|
||||
-- @param uid - the uid of the tag. Used in filename
|
||||
-- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
|
||||
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
|
||||
-- return filename if all went well,
|
||||
-- @reurn nil, error message if unsuccessfulls
|
||||
WriteDumpFile = function(uid, blockData)
|
||||
local destination = string.format("%s.eml", uid)
|
||||
local file = io.open(destination, "w")
|
||||
if file == nil then
|
||||
return nil, string.format("Could not write to file %s", destination)
|
||||
end
|
||||
local rowlen = string.len(blockData[1])
|
||||
|
||||
for i,block in ipairs(blockData) do
|
||||
if rowlen ~= string.len(block) then
|
||||
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
||||
end
|
||||
|
||||
local formatString = string.format("H%d", string.len(block))
|
||||
local _,hex = bin.unpack(formatString,block)
|
||||
file:write(hex.."\n")
|
||||
end
|
||||
file:close()
|
||||
return destination
|
||||
end,
|
||||
|
||||
------------ string split function
|
||||
Split = function( inSplitPattern, outResults )
|
||||
if not outResults then
|
||||
outResults = {}
|
||||
end
|
||||
local start = 1
|
||||
local splitStart, splitEnd = string.find( self, inSplitPattern, start )
|
||||
while splitStart do
|
||||
table.insert( outResults, string.sub( self, start, splitStart-1 ) )
|
||||
start = splitEnd + 1
|
||||
splitStart, splitEnd = string.find( self, inSplitPattern, start )
|
||||
end
|
||||
table.insert( outResults, string.sub( self, start ) )
|
||||
return outResults
|
||||
end,
|
||||
|
||||
----ISO14443-B CRC
|
||||
Crc14b = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
return utils.ConvertAsciiToHex(
|
||||
core.iso14443b_crc(s)
|
||||
)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
----ISO15693 CRC
|
||||
Crc15 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
return utils.ConvertAsciiToHex(
|
||||
core.iso15693_crc(s)
|
||||
)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ CRC-8 Legic checksums
|
||||
-- Takes a hex string and calculates a crc8
|
||||
Crc8Legic = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc8legic(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ CRC-16 ccitt checksums
|
||||
-- Takes a hex string and calculates a crc16
|
||||
Crc16 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc16(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
|
||||
------------ CRC-64 ecma checksums
|
||||
-- Takes a hex string and calculates a crc64 ecma hash
|
||||
Crc64 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc64(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
------------ CRC-64 ecma 182 checksums
|
||||
-- Takes a hex string and calculates a crc64 ecma182 hash
|
||||
Crc64_ecma182 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc64_ecma182(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ SHA1 hash
|
||||
-- Takes a string and calculates a SHA1 hash
|
||||
Sha1 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
return core.sha1(s)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
-- Takes a hex string and calculates a SHA1 hash
|
||||
Sha1Hex = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.sha1(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a number,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
SwapEndianness = function(s, len)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return '' end
|
||||
if type(s) ~= 'string' then return nil end
|
||||
|
||||
local retval = 0
|
||||
if len == 16 then
|
||||
local t = s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
elseif len == 24 then
|
||||
local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
elseif len == 32 then
|
||||
local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
end
|
||||
return retval
|
||||
end,
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a string,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
SwapEndiannessStr = function(s, len)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return '' end
|
||||
if type(s) ~= 'string' then return nil end
|
||||
|
||||
local retval
|
||||
if len == 16 then
|
||||
retval = s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 24 then
|
||||
retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 32 then
|
||||
retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
end
|
||||
return retval
|
||||
end,
|
||||
------------ CONVERSIONS
|
||||
|
||||
--
|
||||
-- Converts DECIMAL to HEX
|
||||
ConvertDecToHex = function(IN)
|
||||
local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0
|
||||
while IN > 0 do
|
||||
I = I+1
|
||||
IN, D = math.floor(IN/B), math.modf(IN, B) + 1
|
||||
OUT = string.sub(K, D, D)..OUT
|
||||
end
|
||||
return OUT
|
||||
end,
|
||||
---
|
||||
-- Convert Byte array to string of hex
|
||||
ConvertBytesToHex = function(bytes, reverse)
|
||||
if bytes == nil then return '' end
|
||||
if #bytes == 0 then return '' end
|
||||
local s={}
|
||||
if reverse then
|
||||
local j=1
|
||||
for i = #bytes, 1, -1 do
|
||||
s[i] = string.format("%02X", bytes[j])
|
||||
j = j + 1
|
||||
end
|
||||
else
|
||||
for i = 1, #bytes do
|
||||
s[i] = string.format("%02X", bytes[i])
|
||||
end
|
||||
end
|
||||
return table.concat(s)
|
||||
end,
|
||||
-- Convert byte array to string with ascii
|
||||
ConvertBytesToAscii = function(bytes)
|
||||
if bytes == nil then return '' end
|
||||
if #bytes == 0 then return '' end
|
||||
local s={}
|
||||
for i = 1, #(bytes) do
|
||||
s[i] = string.char(bytes[i])
|
||||
end
|
||||
return table.concat(s)
|
||||
end,
|
||||
ConvertHexToBytes = function(s)
|
||||
local t={}
|
||||
if s == nil then return t end
|
||||
if #s == 0 then return t end
|
||||
for k in s:gmatch"(%x%x)" do
|
||||
table.insert(t,tonumber(k,16))
|
||||
end
|
||||
return t
|
||||
end,
|
||||
ConvertAsciiToBytes = function(s, reverse)
|
||||
local t = {}
|
||||
if s == nil then return t end
|
||||
if #s == 0 then return t end
|
||||
|
||||
for k in s:gmatch"(.)" do
|
||||
table.insert(t, string.byte(k))
|
||||
end
|
||||
|
||||
if not reverse then
|
||||
return t
|
||||
end
|
||||
|
||||
local rev = {}
|
||||
if reverse then
|
||||
for i = #t, 1,-1 do
|
||||
table.insert(rev, t[i] )
|
||||
end
|
||||
end
|
||||
return rev
|
||||
end,
|
||||
|
||||
ConvertHexToAscii = function(s, useSafechars)
|
||||
if s == nil then return '' end
|
||||
if #s == 0 then return '' end
|
||||
local t={}
|
||||
for k in s:gmatch"(%x%x)" do
|
||||
|
||||
local n = tonumber(k,16)
|
||||
local c
|
||||
if useSafechars and ( (n < 32) or (n == 127) ) then
|
||||
c = '.';
|
||||
else
|
||||
c = string.char(n)
|
||||
end
|
||||
table.insert(t,c)
|
||||
end
|
||||
return table.concat(t)
|
||||
end,
|
||||
|
||||
ConvertAsciiToHex = function(s)
|
||||
if s == nil then return '' end
|
||||
if #s == 0 then return '' end
|
||||
local t={}
|
||||
for k in s:gmatch"(.)" do
|
||||
table.insert(t, string.format("%02X", string.byte(k)))
|
||||
end
|
||||
return table.concat(t)
|
||||
end,
|
||||
|
||||
hexlify = function(s)
|
||||
local u = require('utils')
|
||||
return u.ConvertAsciiToHex(s)
|
||||
end,
|
||||
|
||||
Chars2num = function(s)
|
||||
return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
|
||||
end,
|
||||
|
||||
-- use length of string to determine 8,16,32,64 bits
|
||||
bytes_to_int = function(str,endian,signed)
|
||||
local t = {str:byte(1, -1)}
|
||||
if endian == "big" then --reverse bytes
|
||||
local tt = {}
|
||||
for k = 1, #t do
|
||||
tt[#t-k+1] = t[k]
|
||||
end
|
||||
t = tt
|
||||
end
|
||||
local n = 0
|
||||
for k = 1, #t do
|
||||
n = n + t[k] * 2^((k-1) * 8)
|
||||
end
|
||||
if signed then
|
||||
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
|
||||
end
|
||||
return n
|
||||
end,
|
||||
|
||||
-- a simple implementation of a sleep command. Thanks to Mosci
|
||||
-- takes number of seconds to sleep
|
||||
Sleep = function(n)
|
||||
local clock = os.clock
|
||||
local t0 = clock()
|
||||
while clock() - t0 <= n do end
|
||||
return nil
|
||||
end,
|
||||
|
||||
-- function convertStringToBytes(str)
|
||||
-- local bytes = {}
|
||||
-- local strLength = string.len(str)
|
||||
-- for i=1,strLength do
|
||||
-- table.insert(bytes, string.byte(str, i))
|
||||
-- end
|
||||
|
||||
-- return bytes
|
||||
-- end
|
||||
|
||||
-- function convertBytesToString(bytes)
|
||||
-- local bytesLength = table.getn(bytes)
|
||||
-- local str = ""
|
||||
-- for i=1,bytesLength do
|
||||
-- str = str .. string.char(bytes[i])
|
||||
-- end
|
||||
|
||||
-- return str
|
||||
-- end
|
||||
|
||||
-- function convertHexStringToBytes(str)
|
||||
-- local bytes = {}
|
||||
-- local strLength = string.len(str)
|
||||
-- for k=2,strLength,2 do
|
||||
-- local hexString = "0x" .. string.sub(str, (k - 1), k)
|
||||
-- table.insert(bytes, hex.to_dec(hexString))
|
||||
-- end
|
||||
|
||||
-- return bytes
|
||||
-- end
|
||||
|
||||
-- function convertBytesToHexString(bytes)
|
||||
-- local str = ""
|
||||
-- local bytesLength = table.getn(bytes)
|
||||
-- for i=1,bytesLength do
|
||||
-- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
|
||||
-- if string.len(hexString) == 1 then
|
||||
-- hexString = "0" .. hexString
|
||||
-- end
|
||||
-- str = str .. hexString
|
||||
-- end
|
||||
|
||||
-- return str
|
||||
-- end
|
||||
|
||||
}
|
||||
--[[
|
||||
This may be moved to a separate library at some point (Holiman)
|
||||
--]]
|
||||
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,
|
||||
|
||||
------------ FILE READING
|
||||
ReadDumpFile = function (filename)
|
||||
|
||||
filename = filename or 'dumpdata.bin'
|
||||
if #filename == 0 then
|
||||
return nil, 'Filename length is zero'
|
||||
end
|
||||
|
||||
infile = io.open(filename, "rb")
|
||||
if infile == nil then
|
||||
return nil, string.format("Could not read file %s",filename)
|
||||
end
|
||||
local t = infile:read("*all")
|
||||
io.close(infile)
|
||||
len = string.len(t)
|
||||
local _,hex = bin.unpack(("H%d"):format(len),t)
|
||||
return hex
|
||||
end,
|
||||
|
||||
------------ FILE WRITING (EML)
|
||||
--- Writes an eml-file.
|
||||
-- @param uid - the uid of the tag. Used in filename
|
||||
-- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
|
||||
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation
|
||||
-- return filename if all went well,
|
||||
-- @reurn nil, error message if unsuccessfulls
|
||||
WriteDumpFile = function(uid, blockData)
|
||||
local destination = string.format("%s.eml", uid)
|
||||
local file = io.open(destination, "w")
|
||||
if file == nil then
|
||||
return nil, string.format("Could not write to file %s", destination)
|
||||
end
|
||||
local rowlen = string.len(blockData[1])
|
||||
|
||||
for i,block in ipairs(blockData) do
|
||||
if rowlen ~= string.len(block) then
|
||||
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
|
||||
end
|
||||
|
||||
local formatString = string.format("H%d", string.len(block))
|
||||
local _,hex = bin.unpack(formatString,block)
|
||||
file:write(hex.."\n")
|
||||
end
|
||||
file:close()
|
||||
return destination
|
||||
end,
|
||||
|
||||
------------ string split function
|
||||
Split = function( inSplitPattern, outResults )
|
||||
if not outResults then
|
||||
outResults = {}
|
||||
end
|
||||
local start = 1
|
||||
local splitStart, splitEnd = string.find( self, inSplitPattern, start )
|
||||
while splitStart do
|
||||
table.insert( outResults, string.sub( self, start, splitStart-1 ) )
|
||||
start = splitEnd + 1
|
||||
splitStart, splitEnd = string.find( self, inSplitPattern, start )
|
||||
end
|
||||
table.insert( outResults, string.sub( self, start ) )
|
||||
return outResults
|
||||
end,
|
||||
|
||||
----ISO14443-B CRC
|
||||
Crc14b = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
return utils.ConvertAsciiToHex(
|
||||
core.iso14443b_crc(s)
|
||||
)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
----ISO15693 CRC
|
||||
Crc15 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
return utils.ConvertAsciiToHex(
|
||||
core.iso15693_crc(s)
|
||||
)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ CRC-8 Legic checksums
|
||||
-- Takes a hex string and calculates a crc8
|
||||
Crc8Legic = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc8legic(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ CRC-16 ccitt checksums
|
||||
-- Takes a hex string and calculates a crc16
|
||||
Crc16 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc16(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
|
||||
------------ CRC-64 ecma checksums
|
||||
-- Takes a hex string and calculates a crc64 ecma hash
|
||||
Crc64 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc64(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
------------ CRC-64 ecma 182 checksums
|
||||
-- Takes a hex string and calculates a crc64 ecma182 hash
|
||||
Crc64_ecma182 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc64_ecma182(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ SHA1 hash
|
||||
-- Takes a string and calculates a SHA1 hash
|
||||
Sha1 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
return core.sha1(s)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
-- Takes a hex string and calculates a SHA1 hash
|
||||
Sha1Hex = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.sha1(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a number,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
SwapEndianness = function(s, len)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return '' end
|
||||
if type(s) ~= 'string' then return nil end
|
||||
|
||||
local retval = 0
|
||||
if len == 16 then
|
||||
local t = s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
elseif len == 24 then
|
||||
local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
elseif len == 32 then
|
||||
local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
retval = tonumber(t,16)
|
||||
end
|
||||
return retval
|
||||
end,
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a string,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
SwapEndiannessStr = function(s, len)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return '' end
|
||||
if type(s) ~= 'string' then return nil end
|
||||
|
||||
local retval
|
||||
if len == 16 then
|
||||
retval = s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 24 then
|
||||
retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 32 then
|
||||
retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
end
|
||||
return retval
|
||||
end,
|
||||
------------ CONVERSIONS
|
||||
|
||||
--
|
||||
-- Converts DECIMAL to HEX
|
||||
ConvertDecToHex = function(IN)
|
||||
local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0
|
||||
while IN > 0 do
|
||||
I = I+1
|
||||
IN, D = math.floor(IN/B), math.modf(IN, B) + 1
|
||||
OUT = string.sub(K, D, D)..OUT
|
||||
end
|
||||
return OUT
|
||||
end,
|
||||
---
|
||||
-- Convert Byte array to string of hex
|
||||
ConvertBytesToHex = function(bytes, reverse)
|
||||
if bytes == nil then return '' end
|
||||
if #bytes == 0 then return '' end
|
||||
local s={}
|
||||
if reverse then
|
||||
local j=1
|
||||
for i = #bytes, 1, -1 do
|
||||
s[i] = string.format("%02X", bytes[j])
|
||||
j = j + 1
|
||||
end
|
||||
else
|
||||
for i = 1, #bytes do
|
||||
s[i] = string.format("%02X", bytes[i])
|
||||
end
|
||||
end
|
||||
return table.concat(s)
|
||||
end,
|
||||
-- Convert byte array to string with ascii
|
||||
ConvertBytesToAscii = function(bytes)
|
||||
if bytes == nil then return '' end
|
||||
if #bytes == 0 then return '' end
|
||||
local s={}
|
||||
for i = 1, #(bytes) do
|
||||
s[i] = string.char(bytes[i])
|
||||
end
|
||||
return table.concat(s)
|
||||
end,
|
||||
ConvertHexToBytes = function(s)
|
||||
local t={}
|
||||
if s == nil then return t end
|
||||
if #s == 0 then return t end
|
||||
for k in s:gmatch"(%x%x)" do
|
||||
table.insert(t,tonumber(k,16))
|
||||
end
|
||||
return t
|
||||
end,
|
||||
ConvertAsciiToBytes = function(s, reverse)
|
||||
local t = {}
|
||||
if s == nil then return t end
|
||||
if #s == 0 then return t end
|
||||
|
||||
for k in s:gmatch"(.)" do
|
||||
table.insert(t, string.byte(k))
|
||||
end
|
||||
|
||||
if not reverse then
|
||||
return t
|
||||
end
|
||||
|
||||
local rev = {}
|
||||
if reverse then
|
||||
for i = #t, 1,-1 do
|
||||
table.insert(rev, t[i] )
|
||||
end
|
||||
end
|
||||
return rev
|
||||
end,
|
||||
|
||||
ConvertHexToAscii = function(s, useSafechars)
|
||||
if s == nil then return '' end
|
||||
if #s == 0 then return '' end
|
||||
local t={}
|
||||
for k in s:gmatch"(%x%x)" do
|
||||
|
||||
local n = tonumber(k,16)
|
||||
local c
|
||||
if useSafechars and ( (n < 32) or (n == 127) ) then
|
||||
c = '.';
|
||||
else
|
||||
c = string.char(n)
|
||||
end
|
||||
table.insert(t,c)
|
||||
end
|
||||
return table.concat(t)
|
||||
end,
|
||||
|
||||
ConvertAsciiToHex = function(s)
|
||||
if s == nil then return '' end
|
||||
if #s == 0 then return '' end
|
||||
local t={}
|
||||
for k in s:gmatch"(.)" do
|
||||
table.insert(t, string.format("%02X", string.byte(k)))
|
||||
end
|
||||
return table.concat(t)
|
||||
end,
|
||||
|
||||
hexlify = function(s)
|
||||
local u = require('utils')
|
||||
return u.ConvertAsciiToHex(s)
|
||||
end,
|
||||
|
||||
Chars2num = function(s)
|
||||
return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
|
||||
end,
|
||||
|
||||
-- use length of string to determine 8,16,32,64 bits
|
||||
bytes_to_int = function(str,endian,signed)
|
||||
local t = {str:byte(1, -1)}
|
||||
if endian == "big" then --reverse bytes
|
||||
local tt = {}
|
||||
for k = 1, #t do
|
||||
tt[#t-k+1] = t[k]
|
||||
end
|
||||
t = tt
|
||||
end
|
||||
local n = 0
|
||||
for k = 1, #t do
|
||||
n = n + t[k] * 2^((k-1) * 8)
|
||||
end
|
||||
if signed then
|
||||
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
|
||||
end
|
||||
return n
|
||||
end,
|
||||
|
||||
-- a simple implementation of a sleep command. Thanks to Mosci
|
||||
-- takes number of seconds to sleep
|
||||
Sleep = function(n)
|
||||
local clock = os.clock
|
||||
local t0 = clock()
|
||||
while clock() - t0 <= n do end
|
||||
return nil
|
||||
end,
|
||||
|
||||
-- function convertStringToBytes(str)
|
||||
-- local bytes = {}
|
||||
-- local strLength = string.len(str)
|
||||
-- for i=1,strLength do
|
||||
-- table.insert(bytes, string.byte(str, i))
|
||||
-- end
|
||||
|
||||
-- return bytes
|
||||
-- end
|
||||
|
||||
-- function convertBytesToString(bytes)
|
||||
-- local bytesLength = table.getn(bytes)
|
||||
-- local str = ""
|
||||
-- for i=1,bytesLength do
|
||||
-- str = str .. string.char(bytes[i])
|
||||
-- end
|
||||
|
||||
-- return str
|
||||
-- end
|
||||
|
||||
-- function convertHexStringToBytes(str)
|
||||
-- local bytes = {}
|
||||
-- local strLength = string.len(str)
|
||||
-- for k=2,strLength,2 do
|
||||
-- local hexString = "0x" .. string.sub(str, (k - 1), k)
|
||||
-- table.insert(bytes, hex.to_dec(hexString))
|
||||
-- end
|
||||
|
||||
-- return bytes
|
||||
-- end
|
||||
|
||||
-- function convertBytesToHexString(bytes)
|
||||
-- local str = ""
|
||||
-- local bytesLength = table.getn(bytes)
|
||||
-- for i=1,bytesLength do
|
||||
-- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
|
||||
-- if string.len(hexString) == 1 then
|
||||
-- hexString = "0" .. hexString
|
||||
-- end
|
||||
-- str = str .. hexString
|
||||
-- end
|
||||
|
||||
-- return str
|
||||
-- end
|
||||
|
||||
}
|
||||
return Utils
|
Loading…
Add table
Add a link
Reference in a new issue