1 local cmds
= require('commands')
2 local getopt
= require('getopt')
3 local lib14a
= require('read14a')
4 local utils
= require('utils')
5 local pre
= require('precalc')
6 local toys
= require('default_toys')
8 local lsh
= bit32
.lshift
9 local rsh
= bit32
.rshift
11 local band
= bit32
.band
15 script run tnp3clone -h
16 script run tnp3clone -l
17 script run tnp3clone -t aa00 -s 0030
21 usage
= "script run tnp3clone -t <toytype> -s <subtype>"
23 This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
27 -l : list all known toy tokens
28 -t <data> : toytype id, 4hex symbols
29 -s <data> : subtype id, 4hex symbols
31 For fun, try the following subtype id:
41 -- This is only meant to be used when errors occur
48 print("Example usage")
52 local function waitCmd()
53 local response
= core
.WaitForResponseTimeout(cmds
.CMD_ACK
,2000)
55 local count
,cmd
,arg0
= bin
.unpack('LL',response
)
57 local count
,arg1
,arg2
,data
= bin
.unpack('LLH511',response
,count
)
60 return nil, "Couldn't read block."
63 return nil, "No response from device"
66 local function readblock( blocknum
, keyA
)
68 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_READBL
, arg1
= blocknum
, arg2
= 0, arg3
= 0, data
= keyA
}
69 err
= core
.SendCommand(cmd
:getBytes())
70 if err
then return nil, err
end
71 local block0
, err
= waitCmd()
72 if err
then return nil, err
end
75 local function readmagicblock( blocknum
)
77 local CSETBLOCK_SINGLE_OPERATION
= 0x1F
78 cmd
= Command
:new
{cmd
= cmds
.CMD_MIFARE_CGETBLOCK
, arg1
= CSETBLOCK_SINGLE_OPERATION
, arg2
= 0, arg3
= blocknum
}
79 err
= core
.SendCommand(cmd
:getBytes())
80 if err
then return nil, err
end
81 local block0
, err
= waitCmd()
82 if err
then return nil, err
end
86 local function main(args
)
88 print( string.rep('--',20) )
89 print( string.rep('--',20) )
92 local cset
= 'hf mf csetbl '
93 local csetuid
= 'hf mf csetuid '
94 local cget
= 'hf mf cgetbl '
95 local empty
= '00000000000000000000000000000000'
96 local AccAndKeyB
= '7F078869000000000000'
98 local toytype
= 'C201'
99 local subtype
= '0030'
102 -- Arguments for the script
103 for o
, a
in getopt
.getopt(args
, 'ht:s:l') do
104 if o
== "h" then return help() end
105 if o
== "t" then toytype
= a
end
106 if o
== "s" then subtype
= a
end
107 if o
== "l" then return toys
.List() end
110 if #toytype
~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end
111 if #subtype
~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end
113 -- look up type, find & validate types
114 local item
= toys
.Find( toytype
, subtype
)
116 print( (' Looking up input: Found %s - %s (%s)'):format(item
[6],item
[5], item
[4]) )
118 print('Didn\'t find item type. If you are sure about it, report it in')
125 result
, err
= lib14a
.read14443a(false, true)
126 if not result
then return oops(err
) end
129 local akeys
= pre
.GetAll(result
.uid
)
130 local keyA
= akeys
:sub(1, 12 )
132 local b0
= readblock(0,keyA
)
134 print('failed reading block with factorydefault key. Trying chinese magic read.')
135 b0
, err
= readmagicblock(0)
138 return oops('failed reading block with chinese magic command. quitting...')
143 local cmd
= (csetuid
..'%s 0004 08 w'):format(result
.uid
)
146 local b1
= toytype
..string.rep('00',10)..subtype
148 local calc
= utils
.Crc16(b0
..b1
)
149 local calcEndian
= bor(rsh(calc
,8), lsh(band(calc
, 0xff), 8))
151 local cmd
= (cset
..'1 %s%04x'):format( b1
, calcEndian
)
155 for blockNo
= 2, numBlocks
-1, 1 do
156 pos
= (math
.floor( blockNo
/ 4 ) * 12)+1
157 key
= akeys
:sub(pos
, pos
+ 11 )
158 if blockNo
%4 == 3 then
159 cmd
= ('%s %d %s%s'):format(cset
,blockNo
,key
,AccAndKeyB
)
163 core
.clearCommandBuffer()