added more keys (@equipter)
[RRG-proxmark3.git] / client / luascripts / hf_mf_tnp3_clone.lua
blob22c626e8005f8503dbc5c465c227033fd3d2dfc8
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
11 local bor = bit32.bor
12 local band = bit32.band
14 copyright = ''
15 author = "Iceman"
16 version = 'v1.0.3'
17 desc = [[
18 This script will try to make a barebones clone of a tnp3 tag on to a magic generation1 card.
20 example = [[
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
27 usage = [[
28 script run hf_mf_tnp3_clone [-h] [-t <toytype>] [-s <subtype>]
30 arguments = [[
31 -h : this help
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:
37 0612 - Lightcore
38 0118 - Series 1
39 0138 - Series 2
40 0234 - Special
41 023c - Special
42 0020 - Swapforce
45 local PM3_SUCCESS = 0
47 ---
48 -- This is only meant to be used when errors occur
49 local function oops(err)
50 print('ERROR:', err)
51 core.clearCommandBuffer()
52 return nil, err
53 end
54 -- Usage help
55 local function help()
56 print(copyright)
57 print(author)
58 print(version)
59 print(desc)
60 print(ansicolors.cyan..'Usage'..ansicolors.reset)
61 print(usage)
62 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
63 print(arguments)
64 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
65 print(example)
66 end
67 ---
68 -- decode response and get the blockdata from a normal mifare read command
69 local function getblockdata(response)
70 if not response then
71 return nil, 'No response from device'
72 end
73 if response.Status == PM3_SUCCESS then
74 return response.Data
75 else
76 return nil, "Couldn't read block.. ["..response.Status.."]"
77 end
78 end
80 local function readblock( blocknum, keyA )
81 -- Read block N
82 local keytype = '00'
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
87 return b
88 end
89 ---
90 -- decode response and get the blockdata from backdoor magic command
91 local function readmagicblock( blocknum )
92 -- Read block N
93 local CSETBLOCK_SINGLE_OPERATION = 0x1F
94 local c = Command:newMIX{
95 cmd = cmds.CMD_HF_MIFARE_CGETBL
96 , arg1 = CSETBLOCK_SINGLE_OPERATION
97 , arg3 = blocknum
99 local b, err = getblockdata(c:sendMIX())
100 if not b then return oops(err) end
101 return b
104 local function main(args)
106 print( string.rep('--',20) )
107 print( string.rep('--',20) )
109 local numBlocks = 64
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'
115 local atqa = '0F01'
116 local sak = '81'
117 -- Defaults to Gusto
118 local toytype = 'C201'
119 local subtype = '0030'
120 local DEBUG = true
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)
135 if item then
136 print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6], item[5], item[4]) )
137 else
138 print('[-] Didn\'t find item type. If you are sure about it, post on forum')
140 --15,16
141 --13-14
143 -- find tag
144 local card, err = lib14a.read(false, true)
145 if not card then return oops(err) end
147 -- load keys
148 local akeys = pre.GetAll(card.uid)
149 local keyA = akeys:sub(1, 12 )
151 local b0 = readblock(0, keyA)
152 if not b0 then
153 print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
154 b0, err = readmagicblock(0)
155 if not b0 then
156 oops('[!] '..err)
157 return oops('[!] failed reading block with chinese magic command. Quitting...')
160 core.clearCommandBuffer()
162 -- wipe card.
163 local cmd = (csetuid..' -u %s -a %s -s %s -w'):format(card.uid, atqa, sak)
164 core.console(cmd)
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)
173 core.console(cmd)
174 core.clearCommandBuffer()
176 local pos, key
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)
182 core.console(cmd)
185 core.clearCommandBuffer()
187 -- Set sector trailer S0, since it has different access rights
188 cmd = ('%s --blk 3 -d %s0f0f0f69000000000000'):format(cset, keyA)
189 core.console(cmd)
190 core.clearCommandBuffer()
192 main(args)