Skip to content

Instantly share code, notes, and snippets.

@cmsj
Last active February 13, 2023 09:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmsj/3122f57689dbb97b4a172f0ca8c1f342 to your computer and use it in GitHub Desktop.
Save cmsj/3122f57689dbb97b4a172f0ca8c1f342 to your computer and use it in GitHub Desktop.
Proxmark3 (iceman) Lua script to easily write Galaxy's Edge kyber crystal data to EM4305 rfid tags
local cmds = require('commands')
local getopt = require('getopt')
local bin = require('bin')
local utils = require('utils')
local cmds = require('commands')
local ansicolors = require('ansicolors')
copyright = 'Various copyrights - Based on hf_mfu_amiibo_sim.lua'
author = 'Chris Jones <cmsj@tenshu.net>'
version = 'v2.0'
desc = [[
Easily write Disney kyber crystal information to EM4305 tags.
Before using this script, please make sure your rfid tag is working properly, e.g. with: lf em 4x05 info
Save this script to ~/.proxmark3/luascripts/
]]
example = [[
1. script run kyber -c oldluke
2. script run kyber -c red
3. script run kyber -l
]]
usage = [[
script run kyber [-h] [-l] -c NAME
]]
arguments = [[
-h : this help
-l : show all of the krystal names available, and their color
-c NAME : the name of a crystal to write to the tag, or the name of one of the available colors
-i : identify a crystal
]]
local DEBUG = false -- the debug flag
local format = string.format
local addr4 = "0001805F"
local addr5 = "000001FF"
local crystals = {
quigonjinn = {"0C803000", "green"},
yoda = {"00C03000", "green"},
yoda8ball = {"5D183000", "green"},
oldobiwan = {"29803000", "blue"},
oldluke = {"25C03000", "blue"},
mace1 = {"6F803000", "purple"},
mace2 = {"63C03000", "purple"},
templeguard = {"7B003000", "yellow"},
mazkanata = {"77403000", "yellow"},
chirrut = {"14403000", "white"},
ahsoka = {"18003000", "white"},
vader = {"5E003000", "red"},
vader8ball = {"3E183000", "red"},
palpatine = {"52403000", "red"},
maul = {"46C03000", "red"},
dooku = {"31403000", "red"},
snoke = {"1B183000", "black"}
}
---
-- A debug printout-function
local function dbg(args)
if not DEBUG then return end
if type(args) == 'table' then
local i = 1
while result[i] do
dbg(result[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(ansicolors.red..'ERROR: '..err..ansicolors.clear)
core.clearCommandBuffer()
return nil, err
end
---
-- Usage help
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print(ansicolors.cyan..'Usage'..ansicolors.reset)
print(usage)
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
print(arguments)
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
print(example)
end
---
-- Print crystal list
local function list_crystals()
local tkeys = {}
for k in pairs(crystals) do table.insert(tkeys, k) end
table.sort(tkeys)
print(ansicolors.cyan..'Available crystal names:'..ansicolors.reset)
for _,k in ipairs(tkeys) do
v = crystals[k]
print(" "..k.." ("..v[2]..")")
end
end
--
-- Identify a crystal
local function identify()
local res = nil
-- Check address 4
res = core.em4x05_read("4", "", "")
if res == nil then
oops("Error reading crystal (address 4), check alignment and try again")
return
end
local r_addr4 = string.upper(("%08x"):format(res))
if r_addr4 ~= addr4 then
oops("Incorrect value read for address 4. Expected: "..addr4.." got: "..r_addr4)
return
end
print("Address 4 matches expected value ("..addr4..")")
-- Check address 5
res = core.em4x05_read("5", "", "")
if res == nil then
oops("Error reading crystal (address 5), check alignment and try again")
return
end
local r_addr5 = string.upper(("%08x"):format(res))
if r_addr5 ~= addr5 then
oops("Incorrect value read for address 5. Expected: "..addr5.." got: "..r_addr5)
return
end
print("Address 5 matches expected value ("..addr5..")")
res = core.em4x05_read("6", "", "")
if res == nil then
oops("Error reading crystal (address 6), check alignment and try again")
return
end
local id = string.upper(("%08x"):format(res))
local name = nil
print("Address 6 contains value ("..id..")")
for k,v in pairs(crystals) do
-- print("Checking: "..v[1].." against: "..id.."...")
if v[1] == id then
name = k
--print("Crystal identified as: "..k)
break
end
end
if name == nil then
oops("Unknown crystal: "..id)
return nil
end
local color = crystals[name][2]
local bgcolor = nil
if color == "purple" then color = "magenta" end
bgcolor = ansicolors["on"..color]
print("Crystal identified as: "..bgcolor..ansicolors[color].." "..name.." "..ansicolors.clear)
end
--
-- Exit message
local function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local result, err, hex
local inputTemplate = nil
for o, a in getopt.getopt(args, 'hlic:') do
if o == 'h' then return help() end
if o == 'l' then return list_crystals() end
if o == 'i' then return identify() end
if o == 'c' then inputTemplate = a end
end
if inputTemplate == nil then
oops("No crystal name specified")
return help()
end
local crystal = nil
-- Check if the supplied input template is either a key in our data, or a color name
if crystals[inputTemplate] ~= nil then
crystal = crystals[inputTemplate]
else
for k,v in pairs(crystals) do
if v[2] == inputTemplate then
crystal = v
break
end
end
end
if crystal == nil then
return oops("Unable to find a matching crystal for: "..inputTemplate)
end
print((ansicolors.green..'Preparing crystal for: %s'..ansicolors.clear):format(inputTemplate))
print(string.format("Crystal data: \n color: %s\n addr4: %s\n addr5: %s\n addr6: %s", crystal[2], addr4, addr5, crystal[1]))
core.clearCommandBuffer()
print(ansicolors.green.."\nWriting crystal values:"..ansicolors.clear)
core.console(("lf em 4x05 write -a 04 -d %s"):format(addr4))
core.console(("lf em 4x05 write -a 05 -d %s"):format(addr5))
core.console(("lf em 4x05 write -a 06 -d %s"):format(crystal[1]))
print(ansicolors.green.."\nChecking crystal values:"..ansicolors.clear)
identify()
-- print(ansicolors.green.."\nReading values, please check they are correct:"..ansicolors.clear)
-- core.console("lf em 4x05 read -a 04")
-- core.console("lf em 4x05 read -a 05")
-- core.console("lf em 4x05 read -a 06")
end
main(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment