text
[RRG-proxmark3.git] / client / luascripts / hf_mfu_amiibo_sim.lua
blobe00248c90065cc3288fd29257c38fdc842b5ce47
1 local cmds = require('commands')
2 local getopt = require('getopt')
3 local bin = require('bin')
4 local utils = require('utils')
5 local ansicolors = require('ansicolors')
6 local amiibo_tools = require('amiibo_tools')
8 copyright = ''
9 author = 'George Talusan'
10 version = 'v0.0.2'
11 desc = [[
12 This script will try to load a binary datadump of an Amiibo.
13 It will recalculate PWD and PACK if necessary.
15 example = [[
16 1. script run hf_mfu_amiibo_sim
17 2. script run hf_mfu_amiibo_sim -f myfile
19 usage = [[
20 script run hf_mfu_amiibo_sim [-h] [-f <filename>]
22 arguments = [[
23 -h : this help
24 -f : filename for the datadump to read (bin)
27 local DEBUG = false -- the debug flag
29 local bxor = bit32.bxor
30 local sub = string.sub
31 local format = string.format
33 ---
34 -- A debug printout-function
35 local function dbg(args)
36 if not DEBUG then return end
37 if type(args) == 'table' then
38 local i = 1
39 while result[i] do
40 dbg(result[i])
41 i = i+1
42 end
43 else
44 print('###', args)
45 end
46 end
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 ---
55 -- Usage help
56 local function help()
57 print(copyright)
58 print(author)
59 print(version)
60 print(desc)
61 print(ansicolors.cyan..'Usage'..ansicolors.reset)
62 print(usage)
63 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
64 print(arguments)
65 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
66 print(example)
67 end
69 -- Exit message
70 local function ExitMsg(msg)
71 print( string.rep('--',20) )
72 print( string.rep('--',20) )
73 print(msg)
74 print()
75 end
77 local function LoadEmulator(uid, blocks)
78 io.write('Sending Amiibo to emulator memory')
79 local cmd, blockdata
80 for i=0,148,1 do
81 blockdata = blocks[i]
82 io.write('.')
83 io.flush()
84 core.clearCommandBuffer()
85 cmd = Command:newNG{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, data = ('%02x%02x%02x%s'):format(i, 1, 4, blockdata)}
86 local err, msg = cmd:sendNG(true)
87 if err == nil then return err, msg end
88 end
89 io.write('\n')
90 end
92 local function main(args)
93 print( string.rep('--',20) )
94 print( string.rep('--',20) )
96 local result, err, hex
97 local inputTemplate = 'dumpdata.bin'
99 for o, a in getopt.getopt(args, 'hf:u:') do
100 if o == 'h' then return help() end
101 if o == 'f' then inputTemplate = a end
104 print(('Loading data from %s'):format(inputTemplate))
105 hex, err = utils.ReadDumpFile(inputTemplate)
106 if not hex then return oops(err) end
108 -- only deal with missing PWD and PACK, or with 56 emu hdr
109 if #hex ~= 1064 and #hex ~= 1080 and #hex ~= 1192 then return oops('Expecting either a plain binary or emulator dump') end
111 local amiibo_offset = (#hex == 1064 or #hex == 1080) and 0 or 112
112 local amiibo_info = hex:sub(amiibo_offset + 169, amiibo_offset + 169 + 15):lower()
113 local amiibo_game = amiibo_info:sub(1, 3)
114 local amiibo_type = amiibo_info:sub(7, 8)
115 local amiibo_series = amiibo_info:sub(13, 14)
117 dbg('raw: '..ansicolors.green..amiibo_info..ansicolors.reset)
118 print('game: '..ansicolors.green..amiibo_tools.db.game_series[("0x%s"):format(amiibo_game)]..ansicolors.reset)
119 print('character: '..ansicolors.green..amiibo_tools.db.amiibos[("0x%s"):format(amiibo_info)].name..ansicolors.reset)
120 print('type: '..ansicolors.green..amiibo_tools.db.types[("0x%s"):format(amiibo_type)]..ansicolors.reset)
121 print('series: '..ansicolors.green..amiibo_tools.db.amiibo_series[("0x%s"):format(amiibo_series)]..ansicolors.reset)
123 local blocks = {}
124 local blockindex = 0
126 -- add empty header if necessary
127 if (#hex == 1064 or #hex == 1080) then
128 for i = 0, 13, 1 do
129 blocks[i] = '00000000'
131 blocks[2] = '00000086'
132 blockindex = 14
134 for i = 1, #hex, 8 do
135 blocks[blockindex] = hex:sub(i, i+7)
136 blockindex = blockindex + 1
139 -- force lock bytes, otherwise the Amiibo won't be recognized
140 blocks[16] = blocks[16]:sub(1, 4)..'0FE0'
142 -- add PWD and PACK
143 local uid = blocks[14]:sub(1, 6)..blocks[15]:sub(1, 8)
144 blocks[147] = ("%08x"):format(bxor(bxor(tonumber(sub(uid, 2, 10), 16), tonumber(sub(uid, 6, 14), 16)), 0xaa55aa55))
145 blocks[148] = "80800000"
147 err = LoadEmulator(uid, blocks)
148 if err then return oops(err) end
149 core.clearCommandBuffer()
150 core.console(("hf mfu sim -t 7 -u %s"):format(uid))
152 main(args)