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 local dumplib
= require('html_dumplib')
8 local toys
= require('default_toys')
12 script run tnp3dump -n
13 script run tnp3dump -p
14 script run tnp3dump -k aabbccddeeff
15 script run tnp3dump -k aabbccddeeff -n
16 script run tnp3dump -o myfile
17 script run tnp3dump -n -o myfile
18 script run tnp3dump -p -o myfile
19 script run tnp3dump -k aabbccddeeff -n -o myfile
22 usage
= "script run tnp3dump -k <key> -n -p -o <filename>"
24 This script will try to dump the contents of a Mifare TNP3xxx card.
25 It will need a valid KeyA in order to find the other keys and decode the card.
28 -k <key> : Sector 0 Key A.
29 -n : Use the nested cmd to find all keys
30 -p : Use the precalc to find all keys
31 -o : filename for the saved dumps
33 local RANDOM
= '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
34 local TIMEOUT
= 2000 -- Shouldn't take longer than 2 seconds
35 local DEBUG
= false -- the debug flag
39 -- A debug printout-function
45 if type(args
) == "table" then
56 -- This is only meant to be used when errors occur
64 print("Example usage")
70 print( string.rep('--',20) )
71 print( string.rep('--',20) )
76 local function readdumpkeys(infile
)
77 t
= infile
:read("*all")
79 local len
,hex
= bin
.unpack(("H%d"):format(len
),t
)
83 local function waitCmd()
84 local response
= core
.WaitForResponseTimeout(cmds
.CMD_ACK
,TIMEOUT
)
86 local count
,cmd
,arg0
= bin
.unpack('LL',response
)
88 local count
,arg1
,arg2
,data
= bin
.unpack('LLH511',response
,count
)
91 return nil, "Couldn't read block.."
94 return nil, "No response from device"
97 local function main(args
)
99 print( string.rep('--',20) )
100 print( string.rep('--',20) )
105 local useNested
= false
106 local usePreCalc
= false
107 local cmdReadBlockString
= 'hf mf rdbl %d A %s'
108 local input
= "dumpkeys.bin"
109 local outputTemplate
= os
.date("toydump_%Y-%m-%d_%H%M%S");
111 -- Arguments for the script
112 for o
, a
in getopt
.getopt(args
, 'hk:npo:') do
113 if o
== "h" then return help() end
114 if o
== "k" then keyA
= a
end
115 if o
== "n" then useNested
= true end
116 if o
== "p" then usePreCalc
= true end
117 if o
== "o" then outputTemplate
= a
end
120 -- validate input args.
121 keyA
= keyA
or '4b0b20107ccb'
122 if #(keyA
) ~= 12 then
123 return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA
))
127 local cmdSetDbgOff
= "hf mf dbg 0"
128 core
.console( cmdSetDbgOff
)
130 result
, err
= lib14a
.read14443a(false, true)
135 core
.clearCommandBuffer()
138 print((' Found tag %s'):format(result
.name
))
140 dbg(('Using keyA : %s'):format(keyA
))
142 --Trying to find the other keys
144 core
.console( ('hf mf nested 1 0 A %s d'):format(keyA
) )
147 core
.clearCommandBuffer()
151 local pre
= require('precalc')
152 akeys
= pre
.GetAll(result
.uid
)
154 print('Loading dumpkeys.bin')
155 local hex
, err
= utils
.ReadDumpFile(input
)
159 akeys
= hex
:sub(0,12*16)
163 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_READBL
, arg1
= 0,arg2
= 0,arg3
= 0, data
= keyA
}
164 err
= core
.SendCommand(cmd
:getBytes())
165 if err
then return oops(err
) end
166 local block0
, err
= waitCmd()
167 if err
then return oops(err
) end
170 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_READBL
, arg1
= 1,arg2
= 0,arg3
= 0, data
= keyA
}
171 err
= core
.SendCommand(cmd
:getBytes())
172 if err
then return oops(err
) end
173 local block1
, err
= waitCmd()
174 if err
then return oops(err
) end
176 local tmpHash
= block0
..block1
..'%02x'..RANDOM
183 print('Reading card data')
184 core
.clearCommandBuffer()
187 io
.write('Reading blocks > ')
188 for blockNo
= 0, numBlocks
-1, 1 do
190 if core
.ukbhit() then
191 print("aborted by user")
195 pos
= (math
.floor( blockNo
/ 4 ) * 12)+1
196 key
= akeys
:sub(pos
, pos
+ 11 )
197 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_READBL
, arg1
= blockNo
,arg2
= 0,arg3
= 0, data
= key
}
198 local err
= core
.SendCommand(cmd
:getBytes())
199 if err
then return oops(err
) end
200 local blockdata
, err
= waitCmd()
201 if err
then return oops(err
) end
204 if blockNo
%4 ~= 3 then
207 -- Block 0-7 not encrypted
208 blocks
[blockNo
+1] = ('%02d :: %s'):format(blockNo
,blockdata
)
210 -- blocks with zero not encrypted.
211 if string.find(blockdata
, '^0+$') then
212 blocks
[blockNo
+1] = ('%02d :: %s'):format(blockNo
,blockdata
)
214 local baseStr
= utils
.ConvertHexToAscii(tmpHash
:format(blockNo
))
215 local key
= md5
.sumhexa(baseStr
)
216 local aestest
= core
.aes128_decrypt(key
, blockdata
)
217 local hex
= utils
.ConvertAsciiToBytes(aestest
)
218 hex
= utils
.ConvertBytesToHex(hex
)
219 blocks
[blockNo
+1] = ('%02d :: %s'):format(blockNo
,hex
)
220 io
.write(blockNo
..',')
224 -- Sectorblocks, not encrypted
225 blocks
[blockNo
+1] = ('%02d :: %s%s'):format(blockNo
,key
,blockdata
:sub(13,32))
230 core
.clearCommandBuffer()
236 for _
,s
in pairs(blocks
) do
237 local slice
= s
:sub(8,#s
)
238 local str
= utils
.ConvertBytesToAscii(
239 utils
.ConvertHexToBytes(slice
)
241 emldata
= emldata
..slice
..'\n'
242 for c
in (str
):gmatch('.') do
243 bindata
[#bindata
+1] = c
247 print( string.rep('--',20) )
249 local uid
= block0
:sub(1,8)
250 local toytype
= block1
:sub(1,4)
251 local cardidLsw
= block1
:sub(9,16)
252 local cardidMsw
= block1
:sub(16,24)
253 local cardid
= block1
:sub(9,24)
254 local subtype
= block1
:sub(25,28)
256 -- Write dump to files
258 local foo
= dumplib
.SaveAsBinary(bindata
, outputTemplate
..'-'..uid
..'.bin')
259 print(("Wrote a BIN dump to: %s"):format(foo
))
260 local bar
= dumplib
.SaveAsText(emldata
, outputTemplate
..'-'..uid
..'.eml')
261 print(("Wrote a EML dump to: %s"):format(bar
))
264 print( string.rep('--',20) )
267 local item
= toys
.Find(toytype
, subtype
)
269 print((' ITEM TYPE : %s - %s (%s)'):format(item
[6],item
[5], item
[4]) )
271 print((' ITEM TYPE : 0x%s 0x%s'):format(toytype
, subtype
))
274 print( (' UID : 0x%s'):format(uid
) )
275 print( (' CARDID : 0x%s'):format(cardid
) )
276 print( string.rep('--',20) )
278 core
.clearCommandBuffer()