X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/b915fda392487a876ccc7b0c8b79a1b31ca5e398..905c55de2bbe642412b47ed4e92344096c817fac:/client/scripts/tnp3dump.lua diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index 520161b9..613cf581 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -5,19 +5,21 @@ local lib14a = require('read14a') local utils = require('utils') local md5 = require('md5') local dumplib = require('html_dumplib') -local toyNames = require('default_toys') +local toys = require('default_toys') example =[[ - 1. script run tnp3dump - 2. script run tnp3dump -n - 3. script run tnp3dump -k aabbccddeeff - 4. script run tnp3dump -k aabbccddeeff -n - 5. script run tnp3dump -o myfile - 6. script run tnp3dump -n -o myfile - 7. script run tnp3dump -k aabbccddeeff -n -o myfile + script run tnp3dump + script run tnp3dump -n + script run tnp3dump -p + script run tnp3dump -k aabbccddeeff + script run tnp3dump -k aabbccddeeff -n + script run tnp3dump -o myfile + script run tnp3dump -n -o myfile + script run tnp3dump -p -o myfile + script run tnp3dump -k aabbccddeeff -n -o myfile ]] author = "Iceman" -usage = "script run tnp3dump -k -n -o " +usage = "script run tnp3dump -k -n -p -o " desc =[[ This script will try to dump the contents of a Mifare TNP3xxx card. It will need a valid KeyA in order to find the other keys and decode the card. @@ -25,21 +27,18 @@ Arguments: -h : this help -k : Sector 0 Key A. -n : Use the nested cmd to find all keys + -p : Use the precalc to find all keys -o : filename for the saved dumps ]] - -local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' - -local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' +local TIMEOUT = 2500 -- Shouldn't take longer than 2 seconds local DEBUG = false -- the debug flag local numBlocks = 64 local numSectors = 16 --- -- A debug printout-function function dbg(args) - if not DEBUG then - return - end + if not DEBUG then return end if type(args) == "table" then local i = 1 @@ -55,6 +54,7 @@ end -- This is only meant to be used when errors occur function oops(err) print("ERROR: ",err) + return nil,err end --- -- Usage help @@ -80,27 +80,17 @@ local function readdumpkeys(infile) end local function waitCmd() - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) if response then - local count,cmd,arg0 = bin.unpack('LL',response) + local count, cmd, arg0 = bin.unpack('LL',response) if(arg0==1) then local count,arg1,arg2,data = bin.unpack('LLH511',response,count) return data:sub(1,32) else - return nil, "Couldn't read block.." + return nil, "Couldn't read block.. ["..arg0.."]" end end - return nil, "No response from device" -end - -local function computeCrc16(s) - local hash = core.crc16(utils.ConvertHexToAscii(s)) - return hash -end - -local function reverseCrcBytes(crc) - crc2 = crc:sub(3,4)..crc:sub(1,2) - return tonumber(crc2,16) + return nil, 'No response from device' end local function main(args) @@ -112,18 +102,20 @@ local function main(args) local cmd local err local useNested = false + local usePreCalc = false local cmdReadBlockString = 'hf mf rdbl %d A %s' local input = "dumpkeys.bin" local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); -- Arguments for the script - for o, a in getopt.getopt(args, 'hk:no:') do + for o, a in getopt.getopt(args, 'hk:npo:') do if o == "h" then return help() end if o == "k" then keyA = a end if o == "n" then useNested = true end + if o == "p" then usePreCalc = true end if o == "o" then outputTemplate = a end end - + -- validate input args. keyA = keyA or '4b0b20107ccb' if #(keyA) ~= 12 then @@ -141,61 +133,72 @@ local function main(args) core.clearCommandBuffer() - if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx - return oops('This is not a TNP3xxx tag. aborting.') - end - -- Show tag info - print((' Found tag : %s'):format(result.name)) - print(('Using keyA : %s'):format(keyA)) + print((' Found tag %s'):format(result.name)) + + dbg(('Using keyA : %s'):format(keyA)) --Trying to find the other keys if useNested then core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) end - + core.clearCommandBuffer() - -- Loading keyfile - print('Loading dumpkeys.bin') - local hex, err = utils.ReadDumpFile(input) - if not hex then - return oops(err) + local akeys = '' + if usePreCalc then + local pre = require('precalc') + akeys = pre.GetAll(result.uid) + dbg(akeys) + else + print('Loading dumpkeys.bin') + local hex, err = utils.ReadDumpFile(input) + if not hex then + return oops(err) + end + akeys = hex:sub(0,12*16) end - - local akeys = hex:sub(0,12*16) - + -- Read block 0 - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA} + dbg('Reading block 0') + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA} err = core.SendCommand(cmd:getBytes()) if err then return oops(err) end local block0, err = waitCmd() if err then return oops(err) end + core.clearCommandBuffer() + -- Read block 1 - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1,arg2 = 0,arg3 = 0, data = keyA} + dbg('Reading block 1') + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA} err = core.SendCommand(cmd:getBytes()) if err then return oops(err) end local block1, err = waitCmd() if err then return oops(err) end + core.clearCommandBuffer() + + local tmpHash = block0..block1..'%02x'..RANDOM + local key local pos = 0 local blockNo local blocks = {} - - print('Reading card data') - core.clearCommandBuffer() - + -- main loop - io.write('Decrypting blocks > ') + io.write('Reading blocks > ') for blockNo = 0, numBlocks-1, 1 do + io.flush() + if core.ukbhit() then print("aborted by user") break end + core.clearCommandBuffer() + pos = (math.floor( blockNo / 4 ) * 12)+1 key = akeys:sub(pos, pos + 11 ) cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key} @@ -204,25 +207,24 @@ local function main(args) local blockdata, err = waitCmd() if err then return oops(err) end + if blockNo%4 ~= 3 then + if blockNo < 8 then -- Block 0-7 not encrypted - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else - local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT) - local baseStr = utils.ConvertHexToAscii(base) - local md5hash = md5.sumhexa(baseStr) - local aestest = core.aes(md5hash, blockdata) - - local hex = utils.ConvertAsciiToBytes(aestest) - hex = utils.ConvertBytesToHex(hex) - -- blocks with zero not encrypted. if string.find(blockdata, '^0+$') then - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else + local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo)) + local key = md5.sumhexa(baseStr) + local aestest = core.aes128_decrypt(key, blockdata) + local hex = utils.ConvertAsciiToHex(aestest) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) - io.write( blockNo..',') + io.write(blockNo..',') end end else @@ -240,33 +242,44 @@ local function main(args) for _,s in pairs(blocks) do local slice = s:sub(8,#s) - local str = utils.ConvertBytesToAscii( - utils.ConvertHexToBytes(slice) - ) + local str = utils.ConvertHexToAscii(slice) emldata = emldata..slice..'\n' for c in (str):gmatch('.') do bindata[#bindata+1] = c - end + end end + + print( string.rep('--',20) ) + + local uid = block0:sub(1,8) + local toytype = block1:sub(1,4) + local cardidLsw = block1:sub(9,16) + local cardidMsw = block1:sub(16,24) + local cardid = block1:sub(9,24) + local subtype = block1:sub(25,28) -- Write dump to files if not DEBUG then - local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin') - print(("Wrote a BIN dump to the file %s"):format(foo)) - local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml') - print(("Wrote a EML dump to the file %s"):format(bar)) + local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin') + print(("Wrote a BIN dump to: %s"):format(foo)) + local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml') + print(("Wrote a EML dump to: %s"):format(bar)) end + + print( string.rep('--',20) ) + -- Show info - local uid = block0:sub(1,8) - local itemtype = block1:sub(1,4) - local cardid = block1:sub(9,24) + local item = toys.Find(toytype, subtype) + if item then + print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) ) + else + print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype)) + end - -- Show info - print( string.rep('--',20) ) - print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) - print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s'):format(cardid ) ) + print( (' UID : 0x%s'):format(uid) ) + print( (' CARDID : 0x%s'):format(cardid ) ) print( string.rep('--',20) ) - + + core.clearCommandBuffer() end main(args) \ No newline at end of file