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.
This commit is contained in:
iceman1001 2014-11-14 13:24:45 +01:00
parent b22f7a6bc6
commit bd5d0f07e9
4 changed files with 392 additions and 19 deletions

View file

@ -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);

View file

@ -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"))

View file

@ -8,16 +8,16 @@ 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
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 tnp3 -k <key> -n -o <filename>"
usage = "script run tnp3dump -k <key> -n -o <filename>"
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.
@ -216,7 +216,6 @@ local function main(args)
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

383
client/scripts/tnp3sim.lua Normal file
View file

@ -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 <filename>"
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)