]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/scripts/tnp3.lua
fixing scripts/tnp3.lua
[proxmark3-svn] / client / scripts / tnp3.lua
1 local cmds = require('commands')
2 local getopt = require('getopt')
3 local bin = require('bin')
4 local lib14a = require('read14a')
5 local utils = require('utils')
6 local md5 = require('md5')
7
8 example =[[
9 1. script run tnp3
10 2. script run tnp3 -k aabbccddeeff
11 ]]
12 author = "Iceman"
13 usage = "script run tnp3 -k <key>"
14 desc =[[
15 This script will try to dump the contents of a Mifare TNP3xxx card.
16 It will need a valid KeyA in order to find the other keys and decode the card.
17 Arguments:
18 -h - this help
19 -k <key> - Sector 0 Key A.
20 ]]
21
22 local hashconstant = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
23
24 local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
25 local DEBUG = true -- the debug flag
26 local numBlocks = 64
27 local numSectors = 16
28 ---
29 -- A debug printout-function
30 function dbg(args)
31 if not DEBUG then
32 return
33 end
34
35 if type(args) == "table" then
36 local i = 1
37 while result[i] do
38 dbg(result[i])
39 i = i+1
40 end
41 else
42 print("###", args)
43 end
44 end
45 ---
46 -- This is only meant to be used when errors occur
47 function oops(err)
48 print("ERROR: ",err)
49 end
50 ---
51 -- Usage help
52 function help()
53 print(desc)
54 print("Example usage")
55 print(example)
56 end
57 --
58 -- Exit message
59 function ExitMsg(msg)
60 print( string.rep('--',20) )
61 print( string.rep('--',20) )
62 print(msg)
63 print()
64 end
65
66 local function show(data)
67 if DEBUG then
68 local formatString = ("H%d"):format(string.len(data))
69 local _,hexdata = bin.unpack(formatString, data)
70 dbg("Hexdata" , hexdata)
71 end
72 end
73
74 local function readdumpkeys(infile)
75 t = infile:read("*all")
76 len = string.len(t)
77 local len,hex = bin.unpack(("H%d"):format(len),t)
78 --print(len,hex)
79 return hex
80 end
81
82 local function waitCmd()
83 local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
84 if response then
85 local count,cmd,arg0 = bin.unpack('LL',response)
86 if(arg0==1) then
87 local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
88 return data:sub(1,32)
89 else
90 return nil, "Couldn't read block.."
91 end
92 end
93 return nil, "No response from device"
94 end
95
96 local function main(args)
97
98 print( string.rep('--',20) )
99 print( string.rep('--',20) )
100 print()
101
102 local keyA
103 local cmd
104 local err
105 local cmdReadBlockString = 'hf mf rdbl %d A %s'
106 local input = "dumpkeys.bin"
107
108 -- Arguments for the script
109 for o, a in getopt.getopt(args, 'hk:') do
110 if o == "h" then return help() end
111 if o == "k" then keyA = a end
112 end
113
114 -- validate input args.
115 keyA = keyA or '4b0b20107ccb'
116 if #(keyA) ~= 12 then
117 return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
118 end
119
120 result, err = lib14a.read1443a(false)
121 if not result then
122 print(err)
123 return
124 end
125 print((' Found tag : %s'):format(result.name))
126
127 core.clearCommandBuffer()
128
129 if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
130 print('This is not a TNP3xxx tag. aborting.')
131 return
132 end
133
134 -- Show info
135 print(('Using keyA : %s'):format(keyA))
136 print( string.rep('--',20) )
137
138 print('Trying to find other keys. ')
139 --core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
140
141 -- Reading found keys file
142 local infile = io.open(input, "rb")
143 if infile == nil then
144 return oops('Could not read file ', input)
145 end
146 local akeys = readdumpkeys(infile):sub(0,12*16)
147
148 --print( ('KEYS: %s'):format(akeys))
149
150 print('Reading data need to dump data')
151
152 -- Read block 0
153 cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
154 err = core.SendCommand(cmd:getBytes())
155 if err then return oops(err) end
156 local block0, err = waitCmd()
157 if err then return oops(err) end
158
159 -- Read block 1
160 cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1,arg2 = 0,arg3 = 0, data = keyA}
161 local err = core.SendCommand(cmd:getBytes())
162 if err then return oops(err) end
163 local block1, err = waitCmd()
164 if err then return oops(err) end
165
166 print('Dumping data')
167
168 -- main loop
169 print('BLOCK MD5 DECRYPTED ASCII' )
170
171 local key
172 local keyPosStart = 0
173 local block
174 for block = 0, numBlocks-1, 1 do
175 local b = (block+1)%4
176 if b ~= 0 then
177 keyPosStart = (math.floor( block / 4 ) * 12)+1
178 key = akeys:sub(keyPosStart, keyPosStart + 12 )
179 --print( ('%02d %s'):format(block, key))
180
181 cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = block ,arg2 = 0,arg3 = 0, data = key}
182 local err = core.SendCommand(cmd:getBytes())
183 if err then return oops(err) end
184 local blockdata, err = waitCmd()
185 if err then return oops(err) end
186
187 local base = ('%s%s%02d%s'):format(block0, block1, block, hashconstant)
188 local md5hash = md5.sumhexa(base)
189 local aestest = core.aes(md5hash, blockdata)
190
191 local _,hex = bin.unpack(("H%d"):format(16),aestest)
192
193 local hexascii = string.gsub(hex, '(%x%x)',
194 function(value)
195 return string.char(tonumber(value, 16))
196 end
197 )
198
199 print( ('%02d :: %s :: %s :: %s :: %s'):format(block,key,md5hash,hex,hexascii) )
200
201 if core.ukbhit() then
202 print("aborted by user")
203 break
204 end
205 end
206 end
207 end
208
209 main(args)
Impressum, Datenschutz