X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/024b97c5076d1c644fe84b250882569923b67c0c..eabe8cea775c61e32eb64557199baf1b167aa50d:/client/scripts/tnp3sim.lua diff --git a/client/scripts/tnp3sim.lua b/client/scripts/tnp3sim.lua index f43dafa2..ca729f38 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/scripts/tnp3sim.lua @@ -4,8 +4,9 @@ local bin = require('bin') local lib14a = require('read14a') local utils = require('utils') local md5 = require('md5') -local toyNames = require('default_toys') - +local toys = require('default_toys') +local pre = require('precalc') + example =[[ 1. script run tnp3sim 2. script run tnp3sim -m @@ -23,16 +24,26 @@ Arguments: -h : this help -m : Maxed out items (experimental) -i : filename for the datadump to read (bin) -]] + + ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = true -- the debug flag +local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + +local band = bit32.band +local bor = bit32.bor +local lshift = bit32.lshift +local rshift = bit32.rshift +local byte = string.byte +local char = string.char +local sub = string.sub +local format = string.format + --- -- 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 @@ -48,6 +59,7 @@ end -- This is only meant to be used when errors occur function oops(err) print("ERROR: ",err) + return nil,err end --- -- Usage help @@ -65,7 +77,6 @@ function ExitMsg(msg) print() end - local function writedumpfile(infile) t = infile:read("*all") len = string.len(t) @@ -95,6 +106,14 @@ local function GetCheckSum(blocks, dataarea, chksumtype) return utils.SwapEndianness(crc,16) end +local function SetAllCheckSum(blocks) + print('Updating all checksums') + SetCheckSum(blocks, 3) + SetCheckSum(blocks, 2) + SetCheckSum(blocks, 1) + SetCheckSum(blocks, 0) +end + local function SetCheckSum(blocks, chksumtype) if blocks == nil then return nil, 'Argument \"blocks\" nil' end @@ -142,7 +161,8 @@ function CalcCheckSum(blocks, dataarea, chksumtype) end local function ValidateCheckSums(blocks) - + print(' Validating checksums') + local isOk, crc, calc -- Checksum Type 0 crc = GetCheckSum(blocks,1,0) @@ -185,40 +205,142 @@ local function ValidateCheckSums(blocks) 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 +local function AddKey(keys, blockNo, data) + local pos = (math.floor( blockNo / 4 ) * 12)+1 + local key = keys:sub(pos, pos + 11 ) + return key..data:sub(13) +end -local function LoadEmulator(blocks) - local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' - local cmd - local blockdata +local function LoadEmulator(uid, blocks) + print('Sending dumpdata to emulator memory') + local keys = pre.GetAll(uid) + local cmd, 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 base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM) 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 + local enc = core.aes128_encrypt(key, blockdata) + blockdata = utils.ConvertAsciiToHex(enc) io.write( _..',') end + else + -- add keys if not existing.. + if ( blockdata:sub(1,12) == '000000000000' ) then + blockdata = AddKey(keys, _, blockdata) + end end - - cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 0, data = blockdata} + core.clearCommandBuffer() + cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata} local err = core.SendCommand(cmd:getBytes()) - if err then - return err - end + if err then return err end end io.write('\n') end +local function Num2Card(m, l) + + local k = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00 + } + local msw = tonumber(utils.SwapEndiannessStr(m,32),16) + local lsw = tonumber(utils.SwapEndiannessStr(l,32),16) + + if msw > 0x17ea1 then + return "too big" + end + + if msw == 0x17ea1 and lsw > 0x8931fee8 then + return "out of range" + end + + local s = "" + local index + for i = 1,10 do + index, msw, lsw = DivideByK( msw, lsw) + if ( index <= 1 ) then + s = char(k[index]) .. s + else + s = char(k[index-1]) .. s + end + print (index-1, msw, lsw) + end + return s +end +--33LRT-LM9Q9 +--7, 122, 3474858630 +--20, 4, 1008436634 +--7, 0, 627182959 +--17, 0, 21626998 +--16, 0, 745758 +--23, 0, 25715 +--21, 0, 886 +--16, 0, 30 +--1, 0, 1 +--1, 0, 0 + +function DivideByK(msw, lsw) + + local lowLSW + local highLSW + local remainder = 0 + local RADIX = 29 + + --local num = 0 | band( rshift(msw,16), 0xffff) + local num = band( rshift(msw, 16), 0xffff) + + --highLSW = 0 | lshift( (num / RADIX) , 16) + highLSW = lshift( (num / RADIX) , 16) + remainder = num % RADIX + + num = bor( lshift(remainder,16), band(msw, 0xffff)) + + --highLSW |= num / RADIX + highLSW = highLSW or (num / RADIX) + remainder = num % RADIX + + num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff))) + + --lowLSW = 0 | (num / RADIX) << 16 + lowLSW = 0 or (lshift( (num / RADIX), 16)) + remainder = num % RADIX + + num = bor( lshift(remainder,16) , band(lsw, 0xffff) ) + + lowLSW = bor(lowLSW, (num / RADIX)) + remainder = num % RADIX + return remainder, highLSW, lowLSW + + -- uint num = 0 | (msw >> 16) & 0xffff; + + -- highLSW = 0 | (num / RADIX) << 16; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | (msw & 0xffff); + + -- highLSW |= num / RADIX; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | ((lsw >> 16) & 0xffff); + + -- lowLSW = 0 | (num / RADIX) << 16; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | (lsw & 0xffff); + + -- lowLSW |= num / RADIX; + -- remainder = num % RADIX; + +end + local function main(args) print( string.rep('--',20) ) @@ -241,19 +363,6 @@ local function main(args) 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) @@ -266,31 +375,50 @@ local function main(args) blockindex = blockindex + 1 end - if DEBUG then - print('Validating checksums in the loaded datadump') - ValidateCheckSums(blocks) - end + if DEBUG then 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) + local toytype = blocks[1]:sub(1,4) + local cardidLsw = blocks[1]:sub(9,16) + local cardidMsw = blocks[1]:sub(17,24) + local subtype = blocks[1]:sub(25,28) -- Show info print( string.rep('--',20) ) - print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) + + local item = toys.Find( toytype, subtype) + if item then + local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4]) + print(' ITEM TYPE : '..itemStr ) + else + print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) ) + end + print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s'):format(cardid ) ) + print( (' CARDID : 0x%s %s [%s]'):format( + cardidMsw,cardidLsw, + --Num2Card(cardidMsw, cardidLsw)) + '') + ) print( string.rep('--',20) ) - -- lets do something. - -- + + -- Experience should be: local experience = blocks[8]:sub(1,6) - print(('Experience : %d'):format(utils.SwapEndianness(experience,24))) + print(('Experience : %d'):format(utils.SwapEndianness(experience,16))) + local money = blocks[8]:sub(7,10) print(('Money : %d'):format(utils.SwapEndianness(money,16))) + + -- + + -- Sequence number + local seqnum = blocks[8]:sub(18,19) + print(('Sequence number : %d'):format( tonumber(seqnum,16))) + local fairy = blocks[9]:sub(1,8) --FD0F = Left, FF0F = Right local path = 'not choosen' @@ -303,6 +431,12 @@ local function main(args) local hat = blocks[9]:sub(8,11) print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) + + local level = blocks[13]:sub(27,28) + print(('LEVEL : %d'):format( tonumber(level,16))) + + --local health = blocks[]:sub(); + --print(('Health : %d'):format( tonumber(health,16)) --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. local heropoints = blocks[13]:sub(20,23) @@ -312,6 +446,11 @@ local function main(args) local challenges = blocks[16]:sub(25,32) print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) + -- Character Name + local name1 = blocks[10]:sub(1,32) + local name2 = blocks[12]:sub(1,32) + print('Custom name : '..utils.ConvertHexToAscii(name1..name2)) + if maxed then print('Lets try to max out some values') -- max out money, experience @@ -333,23 +472,18 @@ local function main(args) --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') + SetAllCheckSum(blocks) + + -- Validate Checksums ValidateCheckSums(blocks) end - + --Load dumpdata to emulator memory if DEBUG then - print('Sending dumpdata to emulator memory') - err = LoadEmulator(blocks) + err = LoadEmulator(uid, blocks) if err then return oops(err) end core.clearCommandBuffer() - print('The simulation is now prepared.\n --> run \"hf mf sim 5 '..uid..'\" <--') + print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--') end end main(args) \ No newline at end of file