]> git.zerfleddert.de Git - proxmark3-svn/blame - client/scripts/ndef_dump.lua
cmdhf14b.c: fixing a crash in the crc computation when missing data (e.g. with 'hf...
[proxmark3-svn] / client / scripts / ndef_dump.lua
CommitLineData
1686e4d1 1
2-- Ability to read what card is there
3local getopt = require('getopt')
4local cmds = require('commands')
5local taglib = require('taglib')
6
7local desc =
8[[This script will automatically recognize and dump full content of a NFC NDEF Initialized tag; non-initialized tags will be ignored.
9
10Arguments:
11 -d debug logging on
12 -h this help
13
14]]
15local example = "script run xxx"
16local author = "Martin Holst Swende & Asper"
17
18
19
20
21---
22-- PrintAndLog
23function prlog(...)
24 -- TODO; replace this with a call to the proper PrintAndLog
25 print(...)
26end
27---
28-- Usage help
29function help()
30 prlog(desc)
31 prlog("Example usage")
32 prlog(example)
33end
34
35function debug(...)
36 if DEBUG then
37 prlog("debug:", ...)
38 end
39end
40
41---
42-- This is only meant to be used when errors occur
43function oops(err)
44 prlog("ERROR: ",err)
45 return nil,err
46end
47
48local function show(data)
49 if DEBUG then
50 local formatString = ("H%d"):format(string.len(data))
51 local _,hexdata = bin.unpack(formatString, data)
52 debug("Hexdata" , hexdata)
53 end
54end
55--- Fire up a connection with a tag, return uid
56-- @return UID if successfull
57-- @return nil, errormessage if unsuccessfull
58
59local function open()
60 debug("Opening connection")
61 core.clearCommandBuffer()
62 local x = string.format("hf 14a raw -r -p -s")
63 debug(x)
64 core.console(x)
65 debug("done")
66 data, err = waitCmd(true)
67 if err then return oops(err) end
68 show(data)
69 local formatString = ("H%d"):format(string.len(data))
70 local _,uid = bin.unpack(formatString, data)
71 return uid
72end
73--- Shut down tag communication
74-- return no return values
75local function close()
76 debug("Closing connection")
77 core.clearCommandBuffer()
78 local x = string.format("hf 14a raw -r")
79 debug(x)
80 core.console(x)
81 debug("done")
82 --data, err = waitCmd(true)
83 --data, err = waitCmd(false)
84
85end
86
87
88---_ Gets data from a block
89-- @return {block, block+1, block+2, block+3} if successfull
90-- @return nil, errormessage if unsuccessfull
91local function getBlock(block)
92 local data, err
93
94 core.clearCommandBuffer()
95
96 local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
97 debug(x)
98 core.console(x)
99 debug("done")
100 -- By now, there should be an ACK waiting from the device, since
101 -- we used the -r flag (don't read response).
102
103 data, err = waitCmd(false)
104 if err then return oops(err) end
105 show(data)
106
107 if string.len(data) < 18 then
ba33066c 108 return nil, ("Expected at least 18 bytes, got %d - this tag is not NDEF-compliant"):format(string.len(data))
1686e4d1 109 end
110 -- Now, parse out the block data
111 -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
112 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
113 b0 = string.sub(data,1,4)
114 b1 = string.sub(data,5,8)
115 b2 = string.sub(data,9,12)
116 b3 = string.sub(data,13,16)
117 return {b0,b1,b2,b3}
118end
119
120
121--- This function is a lua-implementation of
122-- cmdhf14a.c:waitCmd(uint8_t iSelect)
123function waitCmd(iSelect)
124 local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
125 if response then
126 local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
127
128 local iLen = arg0
129 if iSelect then iLen = arg1 end
130 debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
131 if iLen == 0 then return nil, "No response from tag" end
132 local recv = string.sub(response,count, iLen+count-1)
133 return recv
134 end
135 return nil, "No response from device"
136end
137
138
139
140local function main( args)
141 debug("script started")
142 local err, data, data2,k,v,i
143 -- Read the parameters
144 for o, a in getopt.getopt(args, 'hd') do
145 if o == "h" then help() return end
146 if o == "d" then DEBUG = true end
147 end
148
149 -- Info contained within the tag (block 0 example)
150 -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
151 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
152 -- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
153 -- M = Manufacturer info
154 -- N = NDEF-Structure-Compliant (if value is E1)
155 -- V = NFC Forum Specification version (if 10 = v1.0)
156
157 -- First, 'connect' (fire up the field) and get the uid
158 local uidHexstr = open()
159
160 -- First, get blockt 3 byte 2
161 local blocks, err = getBlock(0)
162 if err then return oops(err) end
163 -- Block 3 contains number of blocks
164 local b3chars = {string.byte(blocks[4], 1,4)}
165 local numBlocks = b3chars[3] * 2 + 6
166 prlog("Number of blocks:", numBlocks)
167
168 -- NDEF compliant?
169 if b3chars[1] ~= 0xE1 then
170 return oops("This tag is not NDEF-Complian")
171 end
172
173 local ndefVersion = b3chars[2]
174
175 -- Block 1, byte 1 contains manufacturer info
176 local bl1_b1 = string.byte(blocks[1], 1)
177 local manufacturer = taglib.lookupManufacturer(bl1_b1)
178
179 -- Reuse existing info
180 local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
181
182
183 --[[ Due to the infineon my-d move bug
184 (if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12)
185 the only way to avoid this is to send the read command as many times as block numbers
186 removing bytes from 5 to 18 from each answer.
187 --]]
188 prlog("Dumping data...please wait")
189 for i=4,numBlocks-1,1 do
190 blocks, err = getBlock(i)
191 if err then return oops(err) end
192 table.insert(blockData,blocks[1])
193 end
194 -- Deactivate field
195 close()
196 -- Print results
197 prlog(string.format("Tag manufacturer: %s", manufacturer))
198 prlog(string.format("Tag UID: %s", uidHexstr))
199 prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
200
201 for k,v in ipairs(blockData) do
202 prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))
203 end
204end
205main(args)
Impressum, Datenschutz