From: iceman1001 Date: Fri, 14 Nov 2014 12:24:45 +0000 (+0100) Subject: REN: renamed tnp3.lua to tnp3dump.lua since that name is more explainatory X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/bd5d0f07e9330f18088f626bc1d18857aeaeaa8e?ds=sidebyside REN: renamed tnp3.lua to tnp3dump.lua since that name is more explainatory ADD: added tnp3sim.lua a script which loads a dump and sends it to the pm3 device memory. --- diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 901ccd49..35bf2a00 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1623,6 +1623,7 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) { PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); break; + break; } keyA = bytes_to_num(data, 6); keyB = bytes_to_num(data + 10, 6); diff --git a/client/scripts/test.lua b/client/scripts/test.lua deleted file mode 100644 index 76adc985..00000000 --- a/client/scripts/test.lua +++ /dev/null @@ -1,10 +0,0 @@ -local foo = "This shows how to use some standard libraries" -print(foo) -local answer -repeat - io.write("Continue with this operation (y/n)? ") - io.flush() - answer=io.read() -until answer=="y" or answer=="n" -local x = "Ok then, %s" -print (x:format("whatever")) \ No newline at end of file diff --git a/client/scripts/tnp3.lua b/client/scripts/tnp3.lua deleted file mode 100644 index 77de766f..00000000 --- a/client/scripts/tnp3.lua +++ /dev/null @@ -1,273 +0,0 @@ -local cmds = require('commands') -local getopt = require('getopt') -local bin = require('bin') -local lib14a = require('read14a') -local utils = require('utils') -local md5 = require('md5') -local dumplib = require('html_dumplib') -local toyNames = require('default_toys') - -example =[[ - 1. script run tnp3 - 2. script run tnp3 -n - 3. script run tnp3 -k aabbccddeeff - 4. script run tnp3 -k aabbccddeeff -n - 5. script run tnp3 -o myfile - 6. script run tnp3 -n -o myfile - 7. script run tnp3 -k aabbccddeeff -n -o myfile -]] -author = "Iceman" -usage = "script run tnp3 -k -n -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. -Arguments: - -h : this help - -k : Sector 0 Key A. - -n : Use the nested cmd to find all keys - -o : filename for the saved dumps -]] - -local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' - -local TIMEOUT = 2000 -- 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 type(args) == "table" then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print("###", args) - end -end ---- --- This is only meant to be used when errors occur -function oops(err) - print("ERROR: ",err) -end ---- --- Usage help -function help() - print(desc) - print("Example usage") - print(example) -end --- --- Exit message -function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() -end - -local function readdumpkeys(infile) - t = infile:read("*all") - len = string.len(t) - local len,hex = bin.unpack(("H%d"):format(len),t) - return hex -end - -local function waitCmd() - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - if response then - 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.." - 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) -end - -local function main(args) - - print( string.rep('--',20) ) - print( string.rep('--',20) ) - - local keyA - local cmd - local err - local useNested = 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 - if o == "h" then return help() end - if o == "k" then keyA = a end - if o == "n" then useNested = true end - if o == "o" then outputTemplate = a end - end - - -- validate input args. - keyA = keyA or '4b0b20107ccb' - if #(keyA) ~= 12 then - return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA)) - end - - -- Turn off Debug - local cmdSetDbgOff = "hf mf dbg 0" - core.console( cmdSetDbgOff) - - result, err = lib14a.read1443a(false) - if not result then - return oops(err) - end - - 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)) - - --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) - 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} - err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - local block0, err = waitCmd() - if err then return oops(err) end - - -- Read 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 - - local key - local pos = 0 - local blockNo - local blocks = {} - - print('Reading card data') - core.clearCommandBuffer() - - -- main loop - io.write('Decrypting blocks > ') - for blockNo = 0, numBlocks-1, 1 do - - if core.ukbhit() then - print("aborted by user") - break - end - - 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} - local err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - 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) - 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) - --local _,hex = bin.unpack(("H%d"):format(16),aestest) - - -- blocks with zero not encrypted. - if string.find(blockdata, '^0+$') then - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) - else - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) - io.write( blockNo..',') - end - end - else - -- Sectorblocks, not encrypted - blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) - end - end - io.write('\n') - - core.clearCommandBuffer() - - -- Print results - local bindata = {} - local emldata = '' - - for _,s in pairs(blocks) do - local slice = s:sub(8,#s) - local str = utils.ConvertBytesToAscii( - utils.ConvertHexToBytes(slice) - ) - emldata = emldata..slice..'\n' - for c in (str):gmatch('.') do - bindata[#bindata+1] = c - end - end - - -- 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)) - end - - local uid = block0:sub(1,8) - local itemtype = block1:sub(1,4) - local cardid = block1:sub(9,24) - - -- 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( string.rep('--',20) ) - -end -main(args) \ No newline at end of file diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua new file mode 100644 index 00000000..520161b9 --- /dev/null +++ b/client/scripts/tnp3dump.lua @@ -0,0 +1,272 @@ +local cmds = require('commands') +local getopt = require('getopt') +local bin = require('bin') +local lib14a = require('read14a') +local utils = require('utils') +local md5 = require('md5') +local dumplib = require('html_dumplib') +local toyNames = 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 +]] +author = "Iceman" +usage = "script run tnp3dump -k -n -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. +Arguments: + -h : this help + -k : Sector 0 Key A. + -n : Use the nested cmd to find all keys + -o : filename for the saved dumps +]] + +local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + +local TIMEOUT = 2000 -- 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 type(args) == "table" then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end + +local function readdumpkeys(infile) + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + return hex +end + +local function waitCmd() + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + if response then + 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.." + 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) +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + + local keyA + local cmd + local err + local useNested = 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 + if o == "h" then return help() end + if o == "k" then keyA = a end + if o == "n" then useNested = true end + if o == "o" then outputTemplate = a end + end + + -- validate input args. + keyA = keyA or '4b0b20107ccb' + if #(keyA) ~= 12 then + return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA)) + end + + -- Turn off Debug + local cmdSetDbgOff = "hf mf dbg 0" + core.console( cmdSetDbgOff) + + result, err = lib14a.read1443a(false) + if not result then + return oops(err) + end + + 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)) + + --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) + 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} + err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + local block0, err = waitCmd() + if err then return oops(err) end + + -- Read 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 + + local key + local pos = 0 + local blockNo + local blocks = {} + + print('Reading card data') + core.clearCommandBuffer() + + -- main loop + io.write('Decrypting blocks > ') + for blockNo = 0, numBlocks-1, 1 do + + if core.ukbhit() then + print("aborted by user") + break + end + + 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} + local err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + 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) + 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) + else + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + io.write( blockNo..',') + end + end + else + -- Sectorblocks, not encrypted + blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) + end + end + io.write('\n') + + core.clearCommandBuffer() + + -- Print results + local bindata = {} + local emldata = '' + + for _,s in pairs(blocks) do + local slice = s:sub(8,#s) + local str = utils.ConvertBytesToAscii( + utils.ConvertHexToBytes(slice) + ) + emldata = emldata..slice..'\n' + for c in (str):gmatch('.') do + bindata[#bindata+1] = c + end + end + + -- 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)) + end + + local uid = block0:sub(1,8) + local itemtype = block1:sub(1,4) + local cardid = block1:sub(9,24) + + -- 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( string.rep('--',20) ) + +end +main(args) \ No newline at end of file diff --git a/client/scripts/tnp3sim.lua b/client/scripts/tnp3sim.lua new file mode 100644 index 00000000..ce772022 --- /dev/null +++ b/client/scripts/tnp3sim.lua @@ -0,0 +1,383 @@ +local cmds = require('commands') +local getopt = require('getopt') +local bin = require('bin') +local lib14a = require('read14a') +local utils = require('utils') +local md5 = require('md5') +local toyNames = require('default_toys') + +example =[[ + 1. script run tnp3sim + 2. script run tnp3sim -m + 3. script run tnp3sim -m -i myfile +]] +author = "Iceman" +usage = "script run tnp3sim -h -m -i " +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. +Arguments: + -h : this help + -m : Maxed out item + -i : filename for the datadump to read (bin) +]] + +local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = true -- the debug flag +--- +-- A debug printout-function +function dbg(args) + if not DEBUG then + return + end + + if type(args) == "table" then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end + +local function writedumpfile(infile) + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + return hex +end +-- blocks with data +-- there are two dataareas, in block 8 or block 36, ( 1==8 , +-- checksum type = 0, 1, 2, 3 +local function GetCheckSum(blocks, dataarea, chksumtype) + + local crc + local area = 36 + if dataarea == 1 then + area = 8 + end + + if chksumtype == 0 then + crc = blocks[1]:sub(29,32) + elseif chksumtype == 1 then + crc = blocks[area]:sub(29,32) + elseif chksumtype == 2 then + crc = blocks[area]:sub(25,28) + elseif chksumtype == 3 then + crc = blocks[area]:sub(21,24) + end + return utils.SwapEndianness(crc,16) +end + +local function SetCheckSum(blocks, chksumtype) + + if blocks == nil then return nil, 'Argument \"blocks\" nil' end + local newcrc + local area1 = 8 + local area2 = 36 + + if chksumtype == 0 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0)) + blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + elseif chksumtype == 1 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1)) + blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1)) + blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + elseif chksumtype == 2 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,2)) + blocks[area1] = blocks[area1]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(29,32) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,2)) + blocks[area2] = blocks[area2]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(29,32) + elseif chksumtype == 3 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,3)) + blocks[area1] = blocks[area1]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(25,32) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,3)) + blocks[area2] = blocks[area2]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(25,32) + end +end + +function CalcCheckSum(blocks, dataarea, chksumtype) + local area = 36 + if dataarea == 1 then + area = 8 + end + + if chksumtype == 0 then + data = blocks[0]..blocks[1]:sub(1,28) + elseif chksumtype == 1 then + data = blocks[area]:sub(1,28)..'0500' + elseif chksumtype == 2 then + data = blocks[area+1]..blocks[area+2]..blocks[area+4] + elseif chksumtype == 3 then + data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0) + end + return utils.Crc16(data) +end + +local function ValidateCheckSums(blocks) + + local isOk, crc, calc + -- Checksum Type 0 + crc = GetCheckSum(blocks,1,0) + calc = CalcCheckSum(blocks, 1, 0) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 1 (DATAAREAHEADER 1) + crc = GetCheckSum(blocks,1,1) + calc = CalcCheckSum(blocks,1,1) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 1 (DATAAREAHEADER 2) + crc = GetCheckSum(blocks,2,1) + calc = CalcCheckSum(blocks,2,1) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 2 (DATAAREA 1) + crc = GetCheckSum(blocks,1,2) + calc = CalcCheckSum(blocks,1,2) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 2 (DATAAREA 2) + crc = GetCheckSum(blocks,2,2) + calc = CalcCheckSum(blocks,2,2) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 3 (DATAAREA 1) + crc = GetCheckSum(blocks,1,3) + calc = CalcCheckSum(blocks,1,3) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 3 (DATAAREA 2) + crc = GetCheckSum(blocks,2,3) + calc = CalcCheckSum(blocks,2,3) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) +end + +-- function EncryptData() + -- local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + -- if blockNo%4 ~= 3 then + -- if blockNo < 8 then + -- -- Block 0-7 not encrypted + -- 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) + -- --local _,hex = bin.unpack(("H%d"):format(16),aestest) + + -- -- blocks with zero not encrypted. + -- if string.find(blockdata, '^0+$') then + -- blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + -- else + -- blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + -- io.write( blockNo..',') + -- end + -- end + -- else + -- -- Sectorblocks, not encrypted + -- blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) + -- end + +-- end + +local function LoadEmulator(blocks) + local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + local cmd + local blockdata + for _,b in pairs(blocks) do + + blockdata = b + + if _%4 ~= 3 then + if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then + local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , HASHCONSTANT) + local baseStr = utils.ConvertHexToAscii(base) + local key = md5.sumhexa(baseStr) + local enc = core.aes(key, blockdata) + local hex = utils.ConvertAsciiToBytes(enc) + hex = utils.ConvertBytesToHex(hex) + + blockdata = hex + io.write( _..',') + end + end + + cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 0, data = blockdata} + local err = core.SendCommand(cmd:getBytes()) + if err then + return err + end + end + io.write('\n') +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + + local result, err, hex + local maxed = false + local inputTemplate = "dumpdata.bin" + local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M"); + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hmi:o:') do + if o == "h" then return help() end + if o == "m" then maxed = true end + if o == "o" then outputTemplate = a end + if o == "i" then inputTemplate = a end + end + + -- Turn off Debug + local cmdSetDbgOff = "hf mf dbg 0" + core.console( cmdSetDbgOff) + + -- Look for tag present on reader, + result, err = lib14a.read1443a(false) + if not result then return oops(err) end + + 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)) + + -- Load dump.bin file + print( (' Load data from %s'):format(inputTemplate)) + hex, err = utils.ReadDumpFile(inputTemplate) + if not hex then return oops(err) end + + local blocks = {} + local blockindex = 0 + for i = 1, #hex, 32 do + blocks[blockindex] = hex:sub(i,i+31) + blockindex = blockindex + 1 + end + + if DEBUG then + print('Validating checksums in the loaded datadump') + ValidateCheckSums(blocks) + end + + -- + print( string.rep('--',20) ) + print(' Gathering info') + local uid = blocks[0]:sub(1,8) + local itemtype = blocks[1]:sub(1,4) + local cardid = blocks[1]:sub(9,24) + + -- 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( string.rep('--',20) ) + + -- lets do something. + -- + local experience = blocks[8]:sub(1,6) + print(('Experience : %d'):format(utils.SwapEndianness(experience,24))) + local money = blocks[8]:sub(7,10) + print(('Money : %d'):format(utils.SwapEndianness(money,16))) + local fairy = blocks[9]:sub(1,8) + --FD0F = Left, FF0F = Right + local path = 'not choosen' + if fairy:sub(2,2) == 'D' then + path = 'Left' + elseif fairy:sub(2,2) == 'F' then + path = 'Right' + end + print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path)) + + local hat = blocks[9]:sub(8,11) + print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) + + --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. + local heropoints = blocks[13]:sub(20,23) + print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16))) + + --0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed. + local challenges = blocks[16]:sub(25,32) + print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) + + if maxed then + print('Lets try to max out some values') + -- max out money, experience + --print (blocks[8]) + blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32) + blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32) + --print (blocks[8]) + + -- max out hero challenges + --print (blocks[16]) + blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF' + blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF' + --print (blocks[16]) + + -- max out heropoints + --print (blocks[13]) + blocks[13] = blocks[13]:sub(1,19)..'0064'..blocks[13]:sub(24,32) + blocks[41] = blocks[41]:sub(1,19)..'0064'..blocks[41]:sub(24,32) + --print (blocks[13]) + + -- Update Checksums + print('Updating all checksums') + SetCheckSum(blocks, 3) + SetCheckSum(blocks, 2) + SetCheckSum(blocks, 1) + SetCheckSum(blocks, 0) + + print('Validating all checksums') + ValidateCheckSums(blocks) + end + + --Load dumpdata to emulator memory + if DEBUG then + print('Sending dumpdata to emulator memory') + err = LoadEmulator(blocks) + if err then return oops(err) end + core.clearCommandBuffer() + print('The simulation is now prepared. run \"hf mf sim\" ') + end +end +main(args) \ No newline at end of file