]>
Commit | Line | Data |
---|---|---|
1cec48cc | 1 | local cmds = require('commands') |
2 | local getopt = require('getopt') | |
3 | local lib14a = require('read14a') | |
4 | local utils = require('utils') | |
5 | example = [[ | |
6 | script run ufodump | |
7 | script run ufodump -b 10 | |
8 | ]] | |
9 | author = "Iceman" | |
10 | desc = | |
11 | [[ | |
12 | This is a script that reads AZTEK iso14443a tags. | |
13 | It starts from block 0, and ends at default block 20. Use 'b' to say different endblock. | |
14 | ||
15 | xor: the first three block (0,1,2) is not XORED. The rest seems to be xored. | |
16 | ||
17 | Arguments: | |
18 | h this helptext | |
19 | b endblock in decimal (1-255, default 20) | |
20 | ]] | |
21 | ||
22 | -- Some globals | |
23 | local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds | |
24 | local DEBUG = false -- the debug flag | |
25 | --- | |
26 | -- A debug printout-function | |
27 | function dbg(args) | |
28 | if DEBUG then | |
29 | print("###", args) | |
30 | end | |
31 | end | |
32 | --- | |
33 | -- This is only meant to be used when errors occur | |
34 | function oops(err) | |
35 | print("ERROR: ",err) | |
36 | core.clearCommandBuffer() | |
37 | end | |
38 | --- | |
39 | -- Usage help | |
40 | function help() | |
41 | print(desc) | |
42 | print("Example usage") | |
43 | print(example) | |
44 | end | |
45 | -- | |
46 | -- writes data to ascii textfile. | |
47 | function writeDumpFile(uid, blockData) | |
48 | local destination = string.format("%s.eml", uid) | |
49 | local file = io.open(destination, "w") | |
50 | if file == nil then | |
51 | return nil, string.format("Could not write to file %s", destination) | |
52 | end | |
53 | local rowlen = string.len(blockData[1]) | |
54 | ||
55 | for i,block in ipairs(blockData) do | |
56 | if rowlen ~= string.len(block) then | |
57 | print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) | |
58 | end | |
59 | file:write(block.."\n") | |
60 | end | |
61 | file:close() | |
62 | return destination | |
63 | end | |
64 | -- | |
65 | --- Picks out and displays the data read from a tag | |
66 | -- Specifically, takes a usb packet, converts to a Command | |
67 | -- (as in commands.lua), takes the data-array and | |
68 | -- reads the number of bytes specified in arg1 (arg0 in c-struct) | |
69 | -- and displays the data | |
70 | -- @blockno just to print which block the data belong to | |
71 | -- @param usbpacket the data received from the device | |
72 | function showdata(blockno, data) | |
73 | local xorkey = '55AA55AA55AA55AA6262' | |
1cec48cc | 74 | local s = data.." | " |
75 | local dex = '' | |
76 | local rs | |
77 | for i = 1, 20-4, 4 do | |
78 | local item = string.sub(data, i, i+3) | |
79 | local xor = string.sub(xorkey, i, i+3) | |
80 | ||
81 | if blockno > 2 then | |
82 | rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16)) | |
83 | else | |
84 | rs = tonumber(item, 16) | |
85 | end | |
86 | dex = (dex..'%04X'):format(rs) | |
87 | end | |
1cec48cc | 88 | s = s..dex.." | " |
89 | print( (" %02d | %s"):format(blockno,s)) | |
90 | end | |
91 | -- | |
92 | -- Send a "raw" iso14443a package, ie "hf 14a raw" command | |
93 | function sendRaw(rawdata, options) | |
94 | --print(">> ", rawdata) | |
95 | local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC | |
96 | local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, | |
97 | arg1 = flags, -- Send raw | |
98 | -- arg2 contains the length, which is half the length | |
99 | -- of the ASCII-string rawdata | |
100 | arg2 = string.len(rawdata)/2, | |
101 | data = rawdata} | |
102 | return lib14a.sendToDevice(command, options.ignore_response) | |
103 | end | |
104 | -- | |
105 | -- Sends an instruction to do nothing, only disconnect | |
106 | function disconnect() | |
107 | local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } | |
108 | -- We can ignore the response here, no ACK is returned for this command | |
109 | -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details | |
110 | return lib14a.sendToDevice(command, true) | |
111 | --core.console("hf 14a raw -r") | |
112 | end | |
113 | --- | |
114 | -- The main entry point | |
115 | function main(args) | |
116 | ||
117 | local ignore_response = false | |
118 | local endblock = 20 | |
119 | ||
120 | -- Read the parameters | |
121 | for o, a in getopt.getopt(args, 'hb:') do | |
122 | if o == "h" then return help() end | |
123 | if o == "b" then endblock = a end | |
124 | end | |
125 | endblock = endblock or 20 | |
126 | ||
127 | -- First of all, connect | |
128 | info, err = lib14a.read1443a(true) | |
129 | if err then disconnect() return oops(err) end | |
130 | core.clearCommandBuffer() | |
131 | ||
132 | local blockData = {} | |
133 | ||
134 | -- Show tag info | |
135 | print(("\nFound Card UID [%s]\n"):format(info.uid)) | |
136 | ||
137 | print("blk | data | xored") | |
138 | print("----+------------------+-------------------") | |
139 | for block = 00, endblock do | |
140 | local cmd = string.format("10%02x00", block) | |
141 | res, err = sendRaw(cmd , {ignore_response = ignore_response}) | |
142 | if err then disconnect() return oops(err) end | |
143 | ||
144 | local cmd_response = Command.parse(res) | |
145 | local len = tonumber(cmd_response.arg1) * 2 | |
146 | local data = string.sub(tostring(cmd_response.data), 0, len-4) | |
147 | ||
148 | showdata(block, data) | |
149 | table.insert(blockData, data) | |
150 | end | |
151 | print("----+------------------+-------------------") | |
152 | disconnect() | |
153 | ||
154 | local filename, err = writeDumpFile(info.uid, blockData) | |
155 | if err then return oops(err) end | |
156 | ||
157 | print(string.format("\nDumped data into %s", filename)) | |
158 | end | |
159 | ||
160 | ||
161 | ||
162 | ||
163 | ------------------------- | |
164 | -- Testing | |
165 | ------------------------- | |
166 | function selftest() | |
167 | DEBUG = true | |
168 | dbg("Performing test") | |
169 | main() | |
170 | dbg("Tests done") | |
171 | end | |
172 | -- Flip the switch here to perform a sanity check. | |
173 | -- It read a nonce in two different ways, as specified in the usage-section | |
174 | if "--test"==args then | |
175 | selftest() | |
176 | else | |
177 | -- Call the main | |
178 | main(args) | |
179 | end |