]>
Commit | Line | Data |
---|---|---|
40762506 | 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 | ||
7 | local lsh = bit32.lshift | |
8 | local rsh = bit32.rshift | |
9 | local bor = bit32.bor | |
10 | local band = bit32.band | |
11 | ||
12 | example =[[ | |
13 | script run tnp3dump | |
14 | script run tnp3dump -h | |
15 | script run tnp3dump -t aa00 | |
16 | ||
17 | ]] | |
18 | author = "Iceman" | |
19 | usage = "script run tnp3clone -t <toytype>" | |
20 | desc =[[ | |
21 | This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card. | |
22 | ||
23 | Arguments: | |
24 | -h : this help | |
25 | -k <key> : toytype id, 4 hex symbols. | |
26 | ]] | |
27 | ||
28 | ||
29 | -- This is only meant to be used when errors occur | |
30 | function oops(err) | |
31 | print("ERROR: ",err) | |
32 | end | |
33 | -- Usage help | |
34 | function help() | |
35 | print(desc) | |
36 | print("Example usage") | |
37 | print(example) | |
38 | end | |
39 | ||
40 | local function waitCmd() | |
41 | local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000) | |
42 | if response then | |
43 | local count,cmd,arg0 = bin.unpack('LL',response) | |
44 | if(arg0==1) then | |
45 | local count,arg1,arg2,data = bin.unpack('LLH511',response,count) | |
46 | return data:sub(1,32) | |
47 | else | |
48 | return nil, "Couldn't read block." | |
49 | end | |
50 | end | |
51 | return nil, "No response from device" | |
52 | end | |
53 | ||
7b47fa9b | 54 | local function readblock( blocknum, keyA ) |
40762506 | 55 | -- Read block 0 |
7b47fa9b | 56 | cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA} |
40762506 | 57 | err = core.SendCommand(cmd:getBytes()) |
7b47fa9b | 58 | if err then return nil, err end |
40762506 | 59 | local block0, err = waitCmd() |
7b47fa9b | 60 | if err then return nil, err end |
61 | return block0 | |
62 | end | |
63 | local function readmagicblock( blocknum ) | |
64 | -- Read block 0 | |
65 | local CSETBLOCK_SINGLE_OPERATION = 0x1F | |
66 | cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} | |
67 | err = core.SendCommand(cmd:getBytes()) | |
68 | if err then return nil, err end | |
69 | local block0, err = waitCmd() | |
70 | if err then return nil, err end | |
40762506 | 71 | return block0 |
72 | end | |
73 | ||
74 | local function main(args) | |
75 | ||
76 | local numBlocks = 64 | |
7b47fa9b | 77 | local cset = 'hf mf csetbl ' |
78 | local cget = 'hf mf cgetbl ' | |
40762506 | 79 | local empty = '00000000000000000000000000000000' |
80 | local AccAndKeyB = '7F078869000000000000' | |
81 | -- Defaults to Gusto | |
82 | local toytype = 'C201' | |
83 | ||
84 | -- Arguments for the script | |
85 | for o, a in getopt.getopt(args, 'ht:') do | |
86 | if o == "h" then return help() end | |
87 | if o == "t" then toytype = a end | |
88 | end | |
89 | ||
90 | if #toytype ~= 4 then return oops('Wrong size in toytype. (4hex symbols)') end | |
91 | ||
92 | -- find tag | |
93 | result, err = lib14a.read1443a(false) | |
94 | if not result then return oops(err) end | |
95 | ||
96 | -- Show tag info | |
97 | print((' Found tag %s'):format(result.name)) | |
98 | ||
99 | -- load keys | |
100 | local akeys = pre.GetAll(result.uid) | |
101 | local keyA = akeys:sub(1, 12 ) | |
102 | ||
7b47fa9b | 103 | local b0 = readblock(0,keyA) |
104 | if not b0 then | |
105 | print('failed reading block with factorydefault key. Trying chinese magic read.') | |
106 | b0, err = readmagicblock(0) | |
107 | if not b0 then | |
108 | oops(err) | |
109 | return oops('failed reading block with chinese magic command. quitting...') | |
110 | end | |
111 | end | |
40762506 | 112 | |
6c81ae55 | 113 | -- wipe card. |
114 | local cmd = (cset..' %s 0004 08 w'):format( b0) | |
115 | core.console(cmd) | |
116 | ||
117 | ||
118 | local b1 = toytype..'000000000000000000000000' | |
40762506 | 119 | local calc = utils.Crc16(b0..b1) |
120 | local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) | |
121 | ||
7b47fa9b | 122 | local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) |
6c81ae55 | 123 | core.console(cmd) |
40762506 | 124 | |
125 | local pos, key | |
126 | for blockNo = 2, numBlocks-1, 1 do | |
127 | pos = (math.floor( blockNo / 4 ) * 12)+1 | |
128 | key = akeys:sub(pos, pos + 11 ) | |
6c81ae55 | 129 | if blockNo%4 == 3 then |
40762506 | 130 | cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) |
6c81ae55 | 131 | core.console(cmd) |
132 | end | |
40762506 | 133 | end |
6c81ae55 | 134 | core.clearCommandBuffer() |
40762506 | 135 | end |
136 | main(args) |