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'
74+ -- local s = data.." | "..utils.ConvertHexToAscii(data).." | "
75+ local s = data .. " | "
76+ local dex = ' '
77+ local rs
78+ for i = 1 , 20 - 4 , 4 do
79+ local item = string.sub (data , i , i + 3 )
80+ local xor = string.sub (xorkey , i , i + 3 )
81+
82+ if blockno > 2 then
83+ rs = bit32.bxor (tonumber (item ,16 ) , tonumber (xor ,16 ))
84+ else
85+ rs = tonumber (item , 16 )
86+ end
87+ dex = (dex .. ' %04X' ):format (rs )
88+ end
89+ -- s = s..dex.." | "..utils.ConvertHexToAscii(dex)
90+ s = s .. dex .. " | "
91+ print ( (" %02d | %s" ):format (blockno ,s ))
92+ end
93+ --
94+ -- Send a "raw" iso14443a package, ie "hf 14a raw" command
95+ function sendRaw (rawdata , options )
96+ -- print(">> ", rawdata)
97+ local flags = lib14a .ISO14A_COMMAND .ISO14A_NO_DISCONNECT + lib14a .ISO14A_COMMAND .ISO14A_RAW + lib14a .ISO14A_COMMAND .ISO14A_APPEND_CRC
98+ local command = Command :new {cmd = cmds .CMD_READER_ISO_14443a ,
99+ arg1 = flags , -- Send raw
100+ -- arg2 contains the length, which is half the length
101+ -- of the ASCII-string rawdata
102+ arg2 = string.len (rawdata )/ 2 ,
103+ data = rawdata }
104+ return lib14a .sendToDevice (command , options .ignore_response )
105+ end
106+ --
107+ -- Sends an instruction to do nothing, only disconnect
108+ function disconnect ()
109+ local command = Command :new {cmd = cmds .CMD_READER_ISO_14443a , arg1 = 0 , }
110+ -- We can ignore the response here, no ACK is returned for this command
111+ -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
112+ return lib14a .sendToDevice (command , true )
113+ -- core.console("hf 14a raw -r")
114+ end
115+ ---
116+ -- The main entry point
117+ function main (args )
118+
119+ local ignore_response = false
120+ local endblock = 20
121+
122+ -- Read the parameters
123+ for o , a in getopt .getopt (args , ' hb:' ) do
124+ if o == " h" then return help () end
125+ if o == " b" then endblock = a end
126+ end
127+ endblock = endblock or 20
128+
129+ -- First of all, connect
130+ info , err = lib14a .read1443a (true )
131+ if err then disconnect () return oops (err ) end
132+ core .clearCommandBuffer ()
133+
134+ local blockData = {}
135+
136+ -- Show tag info
137+ print ((" \n Found Card UID [%s]\n " ):format (info .uid ))
138+
139+ print (" blk | data | xored" )
140+ print (" ----+------------------+-------------------" )
141+ for block = 00 , endblock do
142+ local cmd = string.format (" 10%02x00" , block )
143+ res , err = sendRaw (cmd , {ignore_response = ignore_response })
144+ if err then disconnect () return oops (err ) end
145+
146+ local cmd_response = Command .parse (res )
147+ local len = tonumber (cmd_response .arg1 ) * 2
148+ local data = string.sub (tostring (cmd_response .data ), 0 , len - 4 )
149+
150+ showdata (block , data )
151+ table.insert (blockData , data )
152+ end
153+ print (" ----+------------------+-------------------" )
154+ disconnect ()
155+
156+ local filename , err = writeDumpFile (info .uid , blockData )
157+ if err then return oops (err ) end
158+
159+ print (string.format (" \n Dumped data into %s" , filename ))
160+ end
161+
162+
163+
164+
165+ ---- ---------------------
166+ -- Testing
167+ ---- ---------------------
168+ function selftest ()
169+ DEBUG = true
170+ dbg (" Performing test" )
171+ main ()
172+ dbg (" Tests done" )
173+ end
174+ -- Flip the switch here to perform a sanity check.
175+ -- It read a nonce in two different ways, as specified in the usage-section
176+ if " --test" == args then
177+ selftest ()
178+ else
179+ -- Call the main
180+ main (args )
181+ end
0 commit comments