Skip to content

hf_mfu_amiibo_sim might be out of date with the lua bindings #3074

@leehambley

Description

@leehambley

Ignoring a bit the bug template sorry, I'm on one laptop, but my dev tools are on my other. I need to post here to prepare a patch for myself for a PR from my other machine.

The code here https://github.com/RfidResearchGroup/proxmark3/blob/master/client/luascripts/hf_mfu_amiibo_sim.lua#L85 seems to use an incorrect version of Command::newNG which throws loads of out-of-bounds write errors:

rewriting it with this patch allows me to read exactly the data from a .bin on my laptop with my phone, and comparing with the input file, it's identical:

diff --git a/luascripts/hf_mfu_amiibo_sim.lua b/luascripts/hf_mfu_amiibo_sim.lua
index 0000000..0000000 100644
--- a/luascripts/hf_mfu_amiibo_sim.lua
+++ b/luascripts/hf_mfu_amiibo_sim.lua
@@
-arguments = [[
-    -h             : this help
-    -f             : filename for the datadump to read (bin)
-]]
+arguments = [[
+    -h             : this help
+    -f             : filename for the datadump to read (bin)
+    -M             : force legacy per-block MEMSET loader (default uses hf mfu eload)
+]]
@@
-local function LoadEmulator(uid, blocks)
-    io.write('Sending Amiibo to emulator memory')
-    local cmd
-    for i = 0, 148, 1 do
-        local block = blocks[i]
-        if not block or #block ~= 8 then return false, ('Invalid block %d (%s)'):format(i, tostring(block)) end
-
-        -- Payload layout (LE): startBlock(2 bytes) | blockCount(1) | bytesPerBlock(1) | data
-        local payload = ('%04x%02x%02x%s'):format(i, 1, 4, block)
-        cmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, arg1 = 0, arg2 = 0, arg3 = 0, data = payload}
-        local pkt, msg = cmd:sendMIX(false, nil, false)
-        if pkt == nil then
-            return false, ('memset failed at block %d: %s'):format(i, tostring(msg))
-        end
-        local _, _, _, _, status = bin.unpack('SSIsS', pkt)
-        if status ~= 0 then
-            return false, ('memset failed at block %d: status 0x%04x'):format(i, status)
-        end
-    end
-    io.write('\n')
-    return true
-end
+local function LoadViaEload(blocks)
+    io.write('Sending Amiibo to emulator memory (eload)')
+    local blob, err = BlocksToBinary(blocks, 148)
+    if not blob then return false, err end
+
+    local tmp = '/tmp/amiibo_emul.bin'
+    if DEBUG then dbg(('writing temp image to %s'):format(tmp)) end
+    local fh, ferr = io.open(tmp, 'wb')
+    if not fh then return false, ferr end
+    fh:write(blob)
+    fh:close()
+
+    core.clearCommandBuffer()
+    local ok, msg = core.console(('hf mfu eload -f %s'):format(tmp))
+    if ok == false then return false, msg or 'eload command failed' end
+    io.write('\n')
+    return true
+end
+
+local function LoadViaMemset(blocks)
+    io.write('Sending Amiibo to emulator memory (MEMSET)')
+    local cmd
+    for i = 0, 148, 1 do
+        local block = blocks[i]
+        if not block or #block ~= 8 then return false, ('Invalid block %d (%s)'):format(i, tostring(block)) end
+
+        -- Payload layout (LE): startBlock(2 bytes) | blockCount(1) | bytesPerBlock(1) | data
+        local payload = ('%04x%02x%02x%s'):format(i, 1, 4, block)
+        cmd = Command:newMIX{cmd = cmds.CMD_HF_MIFARE_EML_MEMSET, arg1 = 0, arg2 = 0, arg3 = 0, data = payload}
+        local pkt, msg = cmd:sendMIX(false, nil, false)
+        if pkt == nil then
+            return false, ('memset failed at block %d: %s'):format(i, tostring(msg))
+        end
+        local _, _, _, _, status = bin.unpack('SSIsS', pkt)
+        if status ~= 0 then
+            return false, ('memset failed at block %d: status 0x%04x'):format(i, status)
+        end
+    end
+    io.write('\n')
+    return true
+end
@@
-    local inputTemplate = 'dumpdata.bin'
+    local inputTemplate = 'dumpdata.bin'
+    local force_memset = false
@@
-    for o, a in getopt.getopt(args, 'hf:u:') do
+    for o, a in getopt.getopt(args, 'hf:Mu:') do
         if o == 'h' then return help() end
         if o == 'f' then inputTemplate = a end
+        if o == 'M' then force_memset = true end
     end
@@
-    err = LoadEmulator(uid, blocks)
-    if err then return oops(err) end
+    local ok, loadErr
+    if force_memset then
+        ok, loadErr = LoadViaMemset(blocks)
+    else
+        ok, loadErr = LoadViaEload(blocks)
+    end
+    if not ok then return oops(loadErr) end
     core.clearCommandBuffer()
     core.console(("hf mfu sim -t 7 -u %s"):format(uid))
 end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions