224ce36e |
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') |
411105e0 |
6 | local toys = require('default_toys') |
224ce36e |
7 | |
8 | local lsh = bit32.lshift |
9 | local rsh = bit32.rshift |
10 | local bor = bit32.bor |
11 | local band = bit32.band |
12 | |
13 | example =[[ |
411105e0 |
14 | script run tnp3clone |
15 | script run tnp3clone -h |
ab7fdfcb |
16 | script run tnp3clone -l |
411105e0 |
17 | script run tnp3clone -t aa00 -s 0030 |
224ce36e |
18 | |
19 | ]] |
20 | author = "Iceman" |
411105e0 |
21 | usage = "script run tnp3clone -t <toytype> -s <subtype>" |
224ce36e |
22 | desc =[[ |
23 | This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card. |
24 | |
25 | Arguments: |
26 | -h : this help |
ab7fdfcb |
27 | -l : list all known toy tokens |
28 | -t <data> : toytype id, 4hex symbols |
411105e0 |
29 | -s <data> : subtype id, 4hex symbols |
8e0cf023 |
30 | |
31 | For fun, try the following subtype id: |
32 | 0612 - Lightcore |
33 | 0118 - Series 1 |
34 | 0138 - Series 2 |
35 | 0234 - Special |
36 | 023c - Special |
ab7fdfcb |
37 | 0020 - Swapforce |
224ce36e |
38 | ]] |
39 | |
40 | |
41 | -- This is only meant to be used when errors occur |
42 | function oops(err) |
43 | print("ERROR: ",err) |
44 | end |
45 | -- Usage help |
46 | function help() |
47 | print(desc) |
48 | print("Example usage") |
49 | print(example) |
50 | end |
51 | |
52 | local function waitCmd() |
53 | local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000) |
54 | if response then |
55 | local count,cmd,arg0 = bin.unpack('LL',response) |
56 | if(arg0==1) then |
57 | local count,arg1,arg2,data = bin.unpack('LLH511',response,count) |
58 | return data:sub(1,32) |
59 | else |
60 | return nil, "Couldn't read block." |
61 | end |
62 | end |
63 | return nil, "No response from device" |
64 | end |
65 | |
66 | local function readblock( blocknum, keyA ) |
67 | -- Read block 0 |
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 |
73 | return block0 |
74 | end |
75 | local function readmagicblock( blocknum ) |
76 | -- Read block 0 |
77 | local CSETBLOCK_SINGLE_OPERATION = 0x1F |
78 | cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} |
ab7fdfcb |
79 | err = core.SendCommand(cmd:getBytes()) |
224ce36e |
80 | if err then return nil, err end |
81 | local block0, err = waitCmd() |
82 | if err then return nil, err end |
83 | return block0 |
84 | end |
85 | |
86 | local function main(args) |
87 | |
411105e0 |
88 | print( string.rep('--',20) ) |
89 | print( string.rep('--',20) ) |
90 | |
224ce36e |
91 | local numBlocks = 64 |
92 | local cset = 'hf mf csetbl ' |
411105e0 |
93 | local csetuid = 'hf mf csetuid ' |
224ce36e |
94 | local cget = 'hf mf cgetbl ' |
95 | local empty = '00000000000000000000000000000000' |
96 | local AccAndKeyB = '7F078869000000000000' |
97 | -- Defaults to Gusto |
98 | local toytype = 'C201' |
411105e0 |
99 | local subtype = '0030' |
100 | local DEBUG = true |
224ce36e |
101 | |
102 | -- Arguments for the script |
ab7fdfcb |
103 | for o, a in getopt.getopt(args, 'ht:s:l') do |
224ce36e |
104 | if o == "h" then return help() end |
105 | if o == "t" then toytype = a end |
411105e0 |
106 | if o == "s" then subtype = a end |
ab7fdfcb |
107 | if o == "l" then return toys.List() end |
224ce36e |
108 | end |
ab7fdfcb |
109 | |
411105e0 |
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 |
112 | |
113 | -- look up type, find & validate types |
114 | local item = toys.Find( toytype, subtype) |
115 | if item then |
116 | print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) |
117 | else |
118 | print('Didn\'t find item type. If you are sure about it, report it in') |
119 | end |
120 | --15,16 |
121 | --13-14 |
122 | |
224ce36e |
123 | |
124 | -- find tag |
125 | result, err = lib14a.read1443a(false) |
126 | if not result then return oops(err) end |
127 | |
224ce36e |
128 | -- load keys |
129 | local akeys = pre.GetAll(result.uid) |
130 | local keyA = akeys:sub(1, 12 ) |
131 | |
132 | local b0 = readblock(0,keyA) |
133 | if not b0 then |
134 | print('failed reading block with factorydefault key. Trying chinese magic read.') |
135 | b0, err = readmagicblock(0) |
136 | if not b0 then |
137 | oops(err) |
138 | return oops('failed reading block with chinese magic command. quitting...') |
139 | end |
140 | end |
141 | |
142 | -- wipe card. |
411105e0 |
143 | local cmd = (csetuid..'%s 0004 08 w'):format(result.uid) |
224ce36e |
144 | core.console(cmd) |
ab7fdfcb |
145 | |
146 | local b1 = toytype..string.rep('00',10)..subtype |
224ce36e |
147 | |
224ce36e |
148 | local calc = utils.Crc16(b0..b1) |
149 | local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) |
150 | |
151 | local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) |
152 | core.console(cmd) |
153 | |
154 | local pos, key |
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) |
160 | core.console(cmd) |
161 | end |
162 | end |
163 | core.clearCommandBuffer() |
164 | end |
165 | main(args) |