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')
7 local ansicolors
= require('ansicolors')
9 local lsh
= bit32
.lshift
10 local rsh
= bit32
.rshift
12 local band
= bit32
.band
18 This script will try to make a barebones clone of a tnp3 tag on to a magic generation1 card.
21 script run hf_mf_tnp3_clone
22 script run hf_mf_tnp3_clone -h
23 script run hf_mf_tnp3_clone -l
24 script run hf_mf_tnp3_clone -t aa00 -s 0030
28 script run hf_mf_tnp3_clone [-h] [-t <toytype>] [-s <subtype>]
32 -l : list all known toy tokens
33 -t <data> : toytype id, 4hex symbols
34 -s <data> : subtype id, 4hex symbols
36 For fun, try the following subtype id:
48 -- This is only meant to be used when errors occur
49 local function oops(err
)
51 core
.clearCommandBuffer()
60 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
62 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
64 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
68 -- decode response and get the blockdata from a normal mifare read command
69 local function getblockdata(response
)
71 return nil, 'No response from device'
73 if response
.Status
== PM3_SUCCESS
then
76 return nil, "Couldn't read block.. ["..response
.Status
.."]"
80 local function readblock( blocknum
, keyA
)
83 local data
= ('%02x%s%s'):format(blocknum
, keytype
, keyA
)
84 local c
= Command
:newNG
{cmd
= cmds
.CMD_HF_MIFARE_READBL
, data
= data
}
85 local b
, err
= getblockdata(c
:sendNG(false))
86 if not b
then return oops(err
) end
90 -- decode response and get the blockdata from backdoor magic command
91 local function readmagicblock( blocknum
)
93 local CSETBLOCK_SINGLE_OPERATION
= 0x1F
94 local c
= Command
:newMIX
{
95 cmd
= cmds
.CMD_HF_MIFARE_CGETBL
96 , arg1
= CSETBLOCK_SINGLE_OPERATION
99 local b
, err
= getblockdata(c
:sendMIX())
100 if not b
then return oops(err
) end
104 local function main(args
)
106 print( string.rep('--',20) )
107 print( string.rep('--',20) )
110 local cset
= 'hf mf csetbl '
111 local csetuid
= 'hf mf csetuid '
112 local cget
= 'hf mf cgetbl '
113 local empty
= '00000000000000000000000000000000'
114 local AccAndKeyB
= '7F0F0869000000000000'
118 local toytype
= 'C201'
119 local subtype
= '0030'
122 -- Arguments for the script
123 for o
, a
in getopt
.getopt(args
, 'ht:s:l') do
124 if o
== 'h' then return help() end
125 if o
== 't' then toytype
= a
end
126 if o
== 's' then subtype
= a
end
127 if o
== 'l' then return toys
.List() end
130 if #toytype
~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
131 if #subtype
~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
133 -- look up type, find & validate types
134 local item
= toys
.Find( toytype
, subtype
)
136 print( ('[+] Looking up input: Found %s - %s (%s)'):format(item
[6], item
[5], item
[4]) )
138 print('[-] Didn\'t find item type. If you are sure about it, post on forum')
144 local card
, err
= lib14a
.read(false, true)
145 if not card
then return oops(err
) end
148 local akeys
= pre
.GetAll(card
.uid
)
149 local keyA
= akeys
:sub(1, 12 )
151 local b0
= readblock(0, keyA
)
153 print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
154 b0
, err
= readmagicblock(0)
157 return oops('[!] failed reading block with chinese magic command. Quitting...')
160 core
.clearCommandBuffer()
163 local cmd
= (csetuid
..' -u %s -a %s -s %s -w'):format(card
.uid
, atqa
, sak
)
165 core
.clearCommandBuffer()
167 local b1
= toytype
..string.rep('00',10)..subtype
169 local calc
= utils
.Crc16(b0
..b1
)
170 local calcEndian
= bor(rsh(calc
,8), lsh(band(calc
, 0xff), 8))
172 local cmd
= (cset
..'--blk 1 -d %s%04x'):format( b1
, calcEndian
)
174 core
.clearCommandBuffer()
177 for blockNo
= 2, numBlocks
-1, 1 do
178 pos
= (math
.floor( blockNo
/ 4 ) * 12)+1
179 key
= akeys
:sub(pos
, pos
+ 11 )
180 if blockNo
%4 == 3 then
181 cmd
= ('%s --blk %d -d %s%s'):format(cset
,blockNo
,key
,AccAndKeyB
)
185 core
.clearCommandBuffer()
187 -- Set sector trailer S0, since it has different access rights
188 cmd
= ('%s --blk 3 -d %s0f0f0f69000000000000'):format(cset
, keyA
)
190 core
.clearCommandBuffer()