Skip to content

Instantly share code, notes, and snippets.

@mjmckinnon
Created August 7, 2021 10:36
Show Gist options
  • Save mjmckinnon/b6cb6ec788e585e8034fb38579ce8f08 to your computer and use it in GitHub Desktop.
Save mjmckinnon/b6cb6ec788e585e8034fb38579ce8f08 to your computer and use it in GitHub Desktop.
Single script to restore Amiibo backups (540 byte .bin files) using a Proxmark3 (iceman build)
local cmds = require('commands')
local getopt = require('getopt')
local lib14a = require('read14a')
local utils = require('utils')
local ansicolors = require('ansicolors')
-- global
local DEBUG = true -- the debug flag
local bxor = bit32.bxor
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while args[i] do
dbg(args[i])
i = i+1
end
else
print('###', args)
end
end
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
return nil, err
end
--
--- Calculate amiibo pwd
local function get_amiibo_pwd(uid)
local tu = {}
-- put uid in table
for k in uid:gmatch"(%x%x)" do
table.insert(tu, tonumber(k, 16))
end
-- generate amiibo password based on this blog
-- https://nfc.toys/interop-ami.html
return string.format("%02X%02X%02X%02X",
bxor(tu[2], bxor(0xaa, tu[4])),
bxor(tu[3], bxor(0x55, tu[5])),
bxor(tu[4], bxor(0xaa, tu[6])),
bxor(tu[5], bxor(0x55, tu[7]))
)
end
--
--- inject uid into the image
--- you'll need to have this python amiibo utility
--- https://pyamiibo.readthedocs.io/en/latest/
local function injectuid(uid, image, newimage)
local tu = {}
-- put uid in table
for k in uid:gmatch"(%x%x)" do
table.insert(tu, tonumber(k, 16))
end
print('Injecting uid into '..image)
struid = string.format("%02X %02X %02X %02X %02X %02X %02X",
tu[1], tu[2], tu[3], tu[4], tu[5], tu[6], tu[7])
mycmd = '~/amiibo/amiibo_venv/bin/amiibo uid '..image..' "'..struid..'" '..newimage
print(mycmd)
res = os.execute(mycmd)
print(res)
return nil
end
--
--- firstphase of actions
local function firstphase(key, img)
print('Restoring image from file: '..img)
-- restore image
core.console('hf mfu restore -k FFFFFFFF -f '..img)
-- write block 3
core.console('hf mfu wrbl -b 3 -d F110FFEE -k FFFFFFFF')
-- write block 134
core.console('hf mfu wrbl -b 134 -d 80800000 -k FFFFFFFF')
-- write block 133 - new key
core.console('hf mfu wrbl -b 133 -d '..key..' -k FFFFFFFF')
-- write block 131
core.console('hf mfu wrbl -b 131 -d 00000004 -k '..key)
-- write block 132
core.console('hf mfu wrbl -b 132 -d 5F000000 -k '..key)
end
--
-- this second phase reads block two and you're supposed
-- to write back the first two bytes already on the tag
-- plus 0FE0 - for example if the card has 03 48 00 00 in block 2
-- we write back 03480FE0
local function secondphase(key, twobytes)
local wholepart = twobytes..'0FE0'
-- write this out
core.console('hf mfu wrbl -b 2 -d '..wholepart..' -k '..key)
-- last bit
core.console('hf mfu wrbl -b 130 -d 01000FBD -k '..key)
return 'Wrote: '..wholepart
end
--
--- The main entry point
function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
-- Arguments for the script
for o, a in getopt.getopt(args, 'f:') do
if o == 'f' then image = a end
if o == 'h' then print('help') end
end
-- output which image
print('We are making this: '..image)
local res, err
-- read the tag for its UID
print('Waiting for new tag...')
res, err = lib14a.waitFor14443a()
if err then return oops(err) end
uid = res['uid']
print('UID is '..uid)
-- new image filename has the uid in it
newimage = 'uid_'..uid..'_'..image
-- calculate the amiibo key
newkey = get_amiibo_pwd(uid)
print('Amiibo key is '..newkey)
-- inject uuid into amiibo image
injectuid(uid, image, newimage)
-- firstphase
firstphase(newkey, newimage)
-- read block 2 and grab the first byte
core.console('hf mfu rdbl -b 2')
-- ask for the digits
twobytes = utils.input('What are the first two bytes? XXXX')
-- secondphase
print(secondphase(newkey, twobytes))
print('Done.')
end
main(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment