Skip to content

Instantly share code, notes, and snippets.

@Pir00t
Created November 6, 2025 12:37
Show Gist options
  • Select an option

  • Save Pir00t/6d1e8833b2ba2754cce515c1a5ab5c72 to your computer and use it in GitHub Desktop.

Select an option

Save Pir00t/6d1e8833b2ba2754cce515c1a5ab5c72 to your computer and use it in GitHub Desktop.
My Hawaii Vacation Lua Decode
#!/usr/bin/env lua
-- Placeholder for the actual key
local __K = "YOUR_12K_CHARACTER_KEY_HERE"
-- Helper function to create UTF-8 character from bytes
local function __U8(a, b, c, d)
return string.char(a, b, c, d)
end
-- Create the 16-token alphabet (hex nibbles 0-F)
local function __T()
return {
__U8(240, 159, 140, 186), -- 0
__U8(240, 159, 140, 180), -- 1
__U8(240, 159, 140, 138), -- 2
__U8(240, 159, 140, 139), -- 3
__U8(240, 159, 165, 165), -- 4
__U8(240, 159, 140, 136), -- 5
__U8(240, 159, 144, 162), -- 6
__U8(240, 159, 144, 160), -- 7
__U8(240, 159, 144, 172), -- 8
__U8(240, 159, 144, 139), -- 9
__U8(240, 159, 144, 154), -- A
__U8(240, 159, 144, 179), -- B
__U8(240, 159, 144, 161), -- C
__U8(240, 159, 166, 128), -- D
__U8(240, 159, 166, 136), -- E
__U8(240, 159, 144, 153) -- F
}
end
-- Simple hash function for key
local function S(k)
k = tostring(k or "")
local s = 3237919422
for i = 1, #k do
s = (s * 1315423911 + k:byte(i)) % 4294967296
end
return s
end
-- Linear congruential generator for keystream
local function M(seed)
return function()
seed = (1664525 * seed + 1013904223) % 4294967296
return seed
end
end
-- 4-bit XOR function
local function X(a, b)
local r, p = 0, 1
for _ = 1, 4 do
local A = a % 2
local B = b % 2
if (A + B) % 2 == 1 then
r = r + p
end
a = (a - A) / 2
b = (b - B) / 2
p = p * 2
end
return r
end
-- Main decoder function
local function __D(t, k)
local T = __T()
local toklen = 4
if k == nil then
k = __K
end
local key_on = k ~= nil and k ~= ""
local permute = true and key_on
-- Build permutation table
local perm = {}
for n = 0, 15 do
perm[n] = n
end
if permute then
local r = M(S(tostring(k) .. "|perm"))
for i = 15, 1, -1 do
local j = r() % (i + 1)
perm[i], perm[j] = perm[j], perm[i]
end
end
-- Build decode map
local dec_map = {}
for n = 0, 15 do
local idx = permute and perm[n] or n
dec_map[T[idx + 1]] = n
end
-- Remove whitespace from input
t = (t or ""):gsub("%s+", "")
local out, n, i, step = {}, #t, 1, toklen * 2
-- Setup keystream for XOR
local ks
if key_on then
local r = M(S(tostring(k) .. "|xor"))
function ks()
local v = r() % 256
return (v - v % 16) / 16, v % 16
end
end
-- Decode pairs of tokens
while n >= i + step - 1 do
local a = t:sub(i, i + toklen - 1)
local b = t:sub(i + toklen, i + step - 1)
local hi, lo = dec_map[a], dec_map[b]
if not hi or not lo then
break
end
if ks then
local kh, kl = ks()
hi = X(hi, kh)
lo = X(lo, kl)
end
out[#out + 1] = string.char(hi * 16 + lo)
i = i + step
end
return table.concat(out)
end
-- Convert escaped string to actual bytes
local function unescape_string(s)
-- Convert \240\159\140\186 style escapes to actual characters
return s:gsub("\\(%d%d%d)", function(d)
return string.char(tonumber(d))
end)
end
-- Test function to decode all strings in a file
local function decode_all_strings(filename)
local f = io.open(filename, "r")
if not f then
print("Error: Cannot open file " .. filename)
return
end
local content = f:read("*all")
f:close()
-- Pattern to match __D("...", __K) or __D('...', __K) calls
-- This captures the escaped string content
local results = {}
local count = 0
-- Match both single and double quoted strings
for encoded in content:gmatch('__D%("([^"]+)", __K%)') do
count = count + 1
local unescaped = unescape_string(encoded)
local decoded = __D(unescaped, __K)
if decoded and #decoded > 0 then
-- Try to show first 40 chars of encoded for reference
local preview = encoded:sub(1, 40)
if #encoded > 40 then preview = preview .. "..." end
table.insert(results, {
num = count,
encoded = preview,
decoded = decoded
})
end
end
for encoded in content:gmatch("__D%('([^']+)', __K%)") do
count = count + 1
local unescaped = unescape_string(encoded)
local decoded = __D(unescaped, __K)
if decoded and #decoded > 0 then
local preview = encoded:sub(1, 40)
if #encoded > 40 then preview = preview .. "..." end
table.insert(results, {
num = count,
encoded = preview,
decoded = decoded
})
end
end
return results
end
-- Main execution
if arg[1] == "test" then
-- Test with specific encoded string (with escape sequences)
local encoded = arg[2]
if encoded then
local unescaped = unescape_string(encoded)
print("Decoded: " .. __D(unescaped, __K))
else
print("Usage: lua decoder.lua test <encoded_string>")
end
elseif arg[1] == "file" then
-- Decode all strings from file
local filename = arg[2] or "decompiled.lua"
print("Decoding strings from: " .. filename)
print(string.rep("=", 70))
local results = decode_all_strings(filename)
if #results == 0 then
print("WARNING: No strings found!")
print("\nDebugging: Checking if key is set...")
if __K == "YOUR_12K_CHARACTER_KEY_HERE" then
print("ERROR: You need to replace __K with the actual key!")
else
print("Key is set (length: " .. #__K .. ")")
print("\nTrying to decode a test string...")
-- Try decoding one of the constants we can see
local test = unescape_string("\\240\\159\\140\\138\\240\\159\\144\\172")
print("Test decode result: [" .. __D(test, __K) .. "]")
end
else
for i, result in ipairs(results) do
print(string.format("%3d. %s", result.num, result.decoded))
print(" Encoded: " .. result.encoded)
print()
end
end
print(string.rep("=", 70))
print("Total strings decoded: " .. #results)
else
-- Interactive mode
print("Prometheus String Decoder")
print("Usage:")
print(" lua decoder.lua test <encoded_string> - Decode single string")
print(" lua decoder.lua file [filename] - Decode all strings from file")
print()
if __K == "YOUR_12K_CHARACTER_KEY_HERE" then
print("WARNING: Key not set! Replace __K with actual key")
else
print("Key length: " .. #__K .. " characters")
end
end
-- Export the decoder function for use as module
return {
decode = __D,
decode_all = decode_all_strings
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment