From 1cec48cc0e608397288ebbdc68768b02b8dcacab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Jan 2017 16:51:07 +0100 Subject: [PATCH] ADD: added the writedumpfile function from "14araw.lua" into utils.lua ADD: `ufodump.lua` - added the Aztek dump script. Since its an unknown tag hence the name. --- client/lualibs/utils.lua | 37 +++++++- client/scripts/ufodump.lua | 181 +++++++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 client/scripts/ufodump.lua diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index 39f8bca2..9dcb49c7 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -53,6 +53,34 @@ local Utils = 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 @@ -262,7 +290,14 @@ local Utils = if #s == 0 then return '' end local t={} for k in s:gmatch"(%x%x)" do - table.insert(t, string.char(tonumber(k,16))) + local n = tonumber(k,16) + local c + if (n < 32) or (n == 127) then + c = '.'; + else + c = string.char(n) + end + table.insert(t,c) end return table.concat(t) end, diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua new file mode 100644 index 00000000..f1e4be1e --- /dev/null +++ b/client/scripts/ufodump.lua @@ -0,0 +1,181 @@ +local cmds = require('commands') +local getopt = require('getopt') +local lib14a = require('read14a') +local utils = require('utils') +example = [[ + script run ufodump + script run ufodump -b 10 +]] +author = "Iceman" +desc = +[[ +This is a script that reads AZTEK iso14443a tags. +It starts from block 0, and ends at default block 20. Use 'b' to say different endblock. + +xor: the first three block (0,1,2) is not XORED. The rest seems to be xored. + +Arguments: + h this helptext + b endblock in decimal (1-255, default 20) +]] + +-- Some globals +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = false -- the debug flag +--- +-- A debug printout-function +function dbg(args) + if DEBUG then + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) + core.clearCommandBuffer() +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- writes data to ascii textfile. +function writeDumpFile(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 + print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end + file:write(block.."\n") + end + file:close() + return destination +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 +-- reads the number of bytes specified in arg1 (arg0 in c-struct) +-- and displays the data +-- @blockno just to print which block the data belong to +-- @param usbpacket the data received from the device +function showdata(blockno, data) + local xorkey = '55AA55AA55AA55AA6262' + --local s = data.." | "..utils.ConvertHexToAscii(data).." | " + local s = data.." | " + local dex = '' + local rs + for i = 1, 20-4, 4 do + local item = string.sub(data, i, i+3) + local xor = string.sub(xorkey, i, i+3) + + if blockno > 2 then + rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16)) + else + rs = tonumber(item, 16) + end + dex = (dex..'%04X'):format(rs) + end + --s = s..dex.." | "..utils.ConvertHexToAscii(dex) + s = s..dex.." | " + print( (" %02d | %s"):format(blockno,s)) +end +-- +-- Send a "raw" iso14443a package, ie "hf 14a raw" command +function sendRaw(rawdata, options) + --print(">> ", rawdata) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + -- arg2 contains the length, which is half the length + -- of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + return lib14a.sendToDevice(command, options.ignore_response) +end +-- +-- Sends an instruction to do nothing, only disconnect +function disconnect() + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return lib14a.sendToDevice(command, true) + --core.console("hf 14a raw -r") +end +--- +-- The main entry point +function main(args) + + local ignore_response = false + local endblock = 20 + + -- Read the parameters + for o, a in getopt.getopt(args, 'hb:') do + if o == "h" then return help() end + if o == "b" then endblock = a end + end + endblock = endblock or 20 + + -- First of all, connect + info, err = lib14a.read1443a(true) + if err then disconnect() return oops(err) end + core.clearCommandBuffer() + + local blockData = {} + + -- Show tag info + print(("\nFound Card UID [%s]\n"):format(info.uid)) + + print("blk | data | xored") + print("----+------------------+-------------------") + for block = 00, endblock do + local cmd = string.format("10%02x00", block) + res, err = sendRaw(cmd , {ignore_response = ignore_response}) + if err then disconnect() return oops(err) end + + local cmd_response = Command.parse(res) + local len = tonumber(cmd_response.arg1) * 2 + local data = string.sub(tostring(cmd_response.data), 0, len-4) + + showdata(block, data) + table.insert(blockData, data) + end + print("----+------------------+-------------------") + disconnect() + + local filename, err = writeDumpFile(info.uid, blockData) + if err then return oops(err) end + + print(string.format("\nDumped data into %s", filename)) +end + + + + +------------------------- +-- Testing +------------------------- +function selftest() + DEBUG = true + dbg("Performing test") + main() + dbg("Tests done") +end +-- Flip the switch here to perform a sanity check. +-- It read a nonce in two different ways, as specified in the usage-section +if "--test"==args then + selftest() +else + -- Call the main + main(args) +end \ No newline at end of file -- 2.39.2