15:13
This commit is contained in:
parent
b9ac7cd6b0
commit
eda9b65091
Binary file not shown.
@ -2,6 +2,7 @@ import random
|
|||||||
import string
|
import string
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import hashlib
|
||||||
from .parser import Lexer, Parser
|
from .parser import Lexer, Parser
|
||||||
|
|
||||||
class LuauVMObfuscator:
|
class LuauVMObfuscator:
|
||||||
@ -16,11 +17,12 @@ class LuauVMObfuscator:
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Arithmetic keys for opcode decoding
|
# Arithmetic keys for opcode decoding
|
||||||
self.k1 = random.randint(100, 500)
|
self.k1 = random.randint(100, 1000)
|
||||||
self.k2 = random.randint(100, 500)
|
self.k2 = random.randint(100, 1000)
|
||||||
|
self.k3 = random.randint(100, 1000)
|
||||||
|
|
||||||
# Opcode to encoded ID: (real_index + k1) ^ k2
|
# Opcode to encoded ID: ((real_index + k1) ^ k2) + k3
|
||||||
self.op_to_id = {name: ((self.opcodes.index(name) + self.k1) ^ self.k2) % 1024 for name in self.opcodes}
|
self.op_to_id = {name: (((self.opcodes.index(name) + self.k1) ^ self.k2) + self.k3) % 4096 for name in self.opcodes}
|
||||||
|
|
||||||
# Variable Renaming Map
|
# Variable Renaming Map
|
||||||
self.var_map = {}
|
self.var_map = {}
|
||||||
@ -30,22 +32,22 @@ class LuauVMObfuscator:
|
|||||||
if hint in self.var_map:
|
if hint in self.var_map:
|
||||||
return self.var_map[hint]
|
return self.var_map[hint]
|
||||||
|
|
||||||
chars = "l1I0O"
|
chars = "lI1"
|
||||||
new_var = "_" + "".join(random.choice(chars) for _ in range(random.randint(10, 15)))
|
length = random.randint(32, 64)
|
||||||
|
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||||
while new_var in self.used_vars:
|
while new_var in self.used_vars:
|
||||||
new_var = "_" + "".join(random.choice(chars) for _ in range(random.randint(10, 15)))
|
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||||
|
|
||||||
self.used_vars.add(new_var)
|
self.used_vars.add(new_var)
|
||||||
self.var_map[hint] = new_var
|
self.var_map[hint] = new_var
|
||||||
return new_var
|
return new_var
|
||||||
|
|
||||||
def to_expr(self, n, depth=0):
|
def to_expr(self, n, depth=0):
|
||||||
# Recursively build complex expressions
|
if depth > 3 or (depth > 0 and random.random() < 0.15):
|
||||||
if depth > 2 or random.random() < 0.1:
|
|
||||||
return str(n)
|
return str(n)
|
||||||
|
|
||||||
r = random.randint(1, 1000)
|
r = random.randint(1, 2000)
|
||||||
choice = random.choice(['add', 'sub', 'xor', 'mul'])
|
choice = random.choice(['add', 'sub', 'xor', 'mul', 'shl', 'shr', 'not'])
|
||||||
|
|
||||||
if choice == 'add':
|
if choice == 'add':
|
||||||
return f"({self.to_expr(n - r, depth + 1)} + {self.to_expr(r, depth + 1)})"
|
return f"({self.to_expr(n - r, depth + 1)} + {self.to_expr(r, depth + 1)})"
|
||||||
@ -57,6 +59,13 @@ class LuauVMObfuscator:
|
|||||||
if n != 0 and n % 2 == 0:
|
if n != 0 and n % 2 == 0:
|
||||||
return f"({self.to_expr(n // 2, depth + 1)} * {self.to_expr(2, depth + 1)})"
|
return f"({self.to_expr(n // 2, depth + 1)} * {self.to_expr(2, depth + 1)})"
|
||||||
return f"({self.to_expr(n, depth + 1)})"
|
return f"({self.to_expr(n, depth + 1)})"
|
||||||
|
elif choice == 'shl':
|
||||||
|
# n = (n >> 1) << 1 + (n & 1)
|
||||||
|
return f"bit32.bor(bit32.lshift({self.to_expr(n >> 1, depth + 1)}, {self.to_expr(1, depth + 1)}), {self.to_expr(n & 1, depth + 1)})"
|
||||||
|
elif choice == 'shr':
|
||||||
|
return f"bit32.rshift({self.to_expr(n << 1, depth + 1)}, {self.to_expr(1, depth + 1)})"
|
||||||
|
elif choice == 'not':
|
||||||
|
return f"bit32.bnot(bit32.bnot({self.to_expr(n, depth + 1)}))"
|
||||||
|
|
||||||
return str(n)
|
return str(n)
|
||||||
|
|
||||||
@ -68,7 +77,10 @@ class LuauVMObfuscator:
|
|||||||
f"({self.to_expr(v1)} + {self.to_expr(v2)} > {self.to_expr(v1)})",
|
f"({self.to_expr(v1)} + {self.to_expr(v2)} > {self.to_expr(v1)})",
|
||||||
f"(math.floor(math.pi) == {self.to_expr(3)})",
|
f"(math.floor(math.pi) == {self.to_expr(3)})",
|
||||||
f"(string.len('SUPREME') == {self.to_expr(7)})",
|
f"(string.len('SUPREME') == {self.to_expr(7)})",
|
||||||
f"(bit32.bor({v1}, {v1}) == {v1})"
|
f"(bit32.bor({v1}, {v1}) == {v1})",
|
||||||
|
f"(bit32.band({v1}, {v1}) == {v1})",
|
||||||
|
f"(bit32.bxor({v1}, 0) == {v1})",
|
||||||
|
f"({self.to_expr(v2)} * 0 == 0)"
|
||||||
]
|
]
|
||||||
return random.choice(preds)
|
return random.choice(preds)
|
||||||
|
|
||||||
@ -100,7 +112,7 @@ class LuauVMObfuscator:
|
|||||||
next_shuffled = 0
|
next_shuffled = 0
|
||||||
|
|
||||||
packed = [
|
packed = [
|
||||||
inst[0] & 0xFF, (inst[0] >> 8) & 0xFF, # OP is now 2 bytes for more range
|
inst[0] & 0xFF, (inst[0] >> 8) & 0xFF,
|
||||||
inst[1], inst[2], inst[3],
|
inst[1], inst[2], inst[3],
|
||||||
next_shuffled & 0xFF, (next_shuffled >> 8) & 0xFF
|
next_shuffled & 0xFF, (next_shuffled >> 8) & 0xFF
|
||||||
]
|
]
|
||||||
@ -109,6 +121,9 @@ class LuauVMObfuscator:
|
|||||||
inst_str = "".join(chr(i) for inst in final_insts for i in inst)
|
inst_str = "".join(chr(i) for inst in final_insts for i in inst)
|
||||||
inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode()
|
inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode()
|
||||||
|
|
||||||
|
# Bytecode Checksum for Integrity
|
||||||
|
checksum = hashlib.md5(inst_str.encode('latin-1')).hexdigest()
|
||||||
|
|
||||||
encrypted_consts = []
|
encrypted_consts = []
|
||||||
salt = random.randint(10000, 99999)
|
salt = random.randint(10000, 99999)
|
||||||
for i, c in enumerate(bytecode['constants']):
|
for i, c in enumerate(bytecode['constants']):
|
||||||
@ -141,10 +156,14 @@ class LuauVMObfuscator:
|
|||||||
V_C = self.get_var("c")
|
V_C = self.get_var("c")
|
||||||
V_BIT = self.get_var("bit32")
|
V_BIT = self.get_var("bit32")
|
||||||
V_GS = self.get_var("getservice")
|
V_GS = self.get_var("getservice")
|
||||||
|
V_TRAP = self.get_var("trap")
|
||||||
|
V_CHECK = self.get_var("check")
|
||||||
|
V_IS_HOOKED = self.get_var("is_hooked")
|
||||||
|
V_PROTECT = self.get_var("protect")
|
||||||
|
V_METH = self.get_var("meth")
|
||||||
|
V_LUA_ENV = self.get_var("lua_env")
|
||||||
|
|
||||||
vm_lua = f"""
|
vm_lua = f"""local {V_LUA_ENV} = getfenv()
|
||||||
-- [[ LUAU-VM SUPREME V3 - ROBLOX EXECUTOR EXCLUSIVE ]]
|
|
||||||
local {V_ENV} = getfenv()
|
|
||||||
local {V_BIT} = bit32
|
local {V_BIT} = bit32
|
||||||
local {V_GS} = game.GetService
|
local {V_GS} = game.GetService
|
||||||
local {V_B64} = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
local {V_B64} = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
@ -163,14 +182,26 @@ local {V_D} = function(data)
|
|||||||
end))
|
end))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Advanced Integrity & Sandbox Detection
|
local function {V_IS_HOOKED}(f)
|
||||||
local function _S()
|
if type(f) ~= "function" then return false end
|
||||||
local d = {{ "getgenv", "getrenv", "getreg", "debug", "Drawing", "hookfunction" }}
|
local s = tostring(f)
|
||||||
local c = 0
|
if string.find(s, "hook") or string.find(s, "proxy") then return true end
|
||||||
for _, v in ipairs(d) do if {V_ENV}[v] then c = c + 1 end end
|
return false
|
||||||
if c == 0 and not ({self.opaque_predicate()}) then return false end
|
end
|
||||||
-- Check for Roblox specific globals
|
|
||||||
if not {V_ENV}["game"] or not {V_ENV}["task"] then return false end
|
local function {V_TRAP}()
|
||||||
|
local _ = function() while true do end end
|
||||||
|
task.spawn(_)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function {V_CHECK}()
|
||||||
|
local d = {{ "getgenv", "getrenv", "getreg", "debug", "Drawing", "hookfunction", "setreadonly", "make_writeable" }}
|
||||||
|
for _, v in ipairs(d) do
|
||||||
|
if {V_LUA_ENV}[v] then
|
||||||
|
if {V_IS_HOOKED}({V_LUA_ENV}[v]) then return false end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not {V_LUA_ENV}["game"] or not {V_LUA_ENV}["task"] then return false end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -179,17 +210,19 @@ local {V_CONSTS} = {V_GS}(game, "HttpService"):JSONDecode('{consts_json}')
|
|||||||
local {V_SALT} = {self.to_expr(salt)}
|
local {V_SALT} = {self.to_expr(salt)}
|
||||||
|
|
||||||
local function {V_EXEC}()
|
local function {V_EXEC}()
|
||||||
if not _S() then
|
if not {V_CHECK}() then {V_TRAP}() return end
|
||||||
-- Trap: Infinite loop or crash
|
|
||||||
local _trap = function() while true do end end
|
|
||||||
task.spawn(_trap)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local {V_REGS} = {{}}
|
local {V_REGS} = {{}}
|
||||||
local {V_CURR} = {self.to_expr(start_idx)}
|
local {V_CURR} = {self.to_expr(start_idx)}
|
||||||
local {V_RUN} = true
|
local {V_RUN} = true
|
||||||
|
|
||||||
|
local {V_PROTECT} = {{}}
|
||||||
|
setmetatable({V_PROTECT}, {{
|
||||||
|
__index = {V_LUA_ENV},
|
||||||
|
__newindex = function(_, k, v) {V_LUA_ENV}[k] = v end,
|
||||||
|
__metatable = "Locked"
|
||||||
|
}})
|
||||||
|
|
||||||
local function {V_GETC}(idx)
|
local function {V_GETC}(idx)
|
||||||
local c = {V_CONSTS}[idx + 1]
|
local c = {V_CONSTS}[idx + 1]
|
||||||
if not c then return nil end
|
if not c then return nil end
|
||||||
@ -210,7 +243,6 @@ local function {V_EXEC}()
|
|||||||
return c.v
|
return c.v
|
||||||
end
|
end
|
||||||
|
|
||||||
-- SUPREME DISPATCHER
|
|
||||||
while {V_RUN} do
|
while {V_RUN} do
|
||||||
if not ({self.opaque_predicate()}) then break end
|
if not ({self.opaque_predicate()}) then break end
|
||||||
local {V_PTR} = {V_CURR} * {self.to_expr(7)} + 1
|
local {V_PTR} = {V_CURR} * {self.to_expr(7)} + 1
|
||||||
@ -227,16 +259,16 @@ local function {V_EXEC}()
|
|||||||
{V_CURR} = next_l + (next_h * {self.to_expr(256)})
|
{V_CURR} = next_l + (next_h * {self.to_expr(256)})
|
||||||
|
|
||||||
local op_raw = op_l + (op_h * 256)
|
local op_raw = op_l + (op_h * 256)
|
||||||
local {V_OP} = {V_BIT}.bxor(op_raw, {self.to_expr(self.k2)}) - {self.to_expr(self.k1)}
|
local {V_OP} = ({V_BIT}.bxor(op_raw, {self.to_expr(self.k2)}) - {self.to_expr(self.k1)}) - {self.to_expr(self.k3)}
|
||||||
|
|
||||||
if {V_OP} == {self.to_expr(self.opcodes.index('MOVE'))} then
|
if {V_OP} == {self.to_expr(self.opcodes.index('MOVE'))} then
|
||||||
{V_REGS}[{V_A}] = {V_REGS}[{V_B}]
|
{V_REGS}[{V_A}] = {V_REGS}[{V_B}]
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('LOADK'))} then
|
elseif {V_OP} == {self.to_expr(self.opcodes.index('LOADK'))} then
|
||||||
{V_REGS}[{V_A}] = {V_GETC}({V_B})
|
{V_REGS}[{V_A}] = {V_GETC}({V_B})
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('GETGLOBAL'))} then
|
elseif {V_OP} == {self.to_expr(self.opcodes.index('GETGLOBAL'))} then
|
||||||
{V_REGS}[{V_A}] = {V_ENV}[{V_GETC}({V_B})]
|
{V_REGS}[{V_A}] = {V_PROTECT}[{V_GETC}({V_B})]
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('SETGLOBAL'))} then
|
elseif {V_OP} == {self.to_expr(self.opcodes.index('SETGLOBAL'))} then
|
||||||
{V_ENV}[{V_GETC}({V_B})] = {V_REGS}[{V_A}]
|
{V_PROTECT}[{V_GETC}({V_B})] = {V_REGS}[{V_A}]
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('CALL'))} then
|
elseif {V_OP} == {self.to_expr(self.opcodes.index('CALL'))} then
|
||||||
local f = {V_REGS}[{V_A}]
|
local f = {V_REGS}[{V_A}]
|
||||||
local args = {{}}
|
local args = {{}}
|
||||||
@ -247,13 +279,11 @@ local function {V_EXEC}()
|
|||||||
{V_RUN} = false
|
{V_RUN} = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Anti-Trace Junk
|
|
||||||
if not ({self.opaque_predicate()}) then {V_RUN} = false end
|
if not ({self.opaque_predicate()}) then {V_RUN} = false end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task.spawn({V_EXEC})
|
task.spawn({V_EXEC})"""
|
||||||
"""
|
|
||||||
return vm_lua
|
return vm_lua
|
||||||
|
|
||||||
def compile_to_bytecode(self, ast):
|
def compile_to_bytecode(self, ast):
|
||||||
@ -316,18 +346,17 @@ task.spawn({V_EXEC})
|
|||||||
return {"instructions": instructions, "constants": constants}
|
return {"instructions": instructions, "constants": constants}
|
||||||
|
|
||||||
def obfuscate(self, code):
|
def obfuscate(self, code):
|
||||||
if not code.strip(): return "-- No input"
|
if not code.strip(): return ""
|
||||||
try:
|
try:
|
||||||
lexer = Lexer(code)
|
lexer = Lexer(code)
|
||||||
tokens = lexer.tokenize()
|
tokens = lexer.tokenize()
|
||||||
parser = Parser(tokens)
|
parser = Parser(tokens)
|
||||||
ast = parser.parse()
|
ast = parser.parse()
|
||||||
if not ast: return "-- VM Parser: No valid structures found."
|
if not ast: return ""
|
||||||
bytecode = self.compile_to_bytecode(ast)
|
bytecode = self.compile_to_bytecode(ast)
|
||||||
return self.generate_vm_source(bytecode)
|
return self.generate_vm_source(bytecode)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
import traceback
|
return ""
|
||||||
return f"-- Error: {str(e)}\n{traceback.format_exc()}"
|
|
||||||
|
|
||||||
def obfuscate(code):
|
def obfuscate(code):
|
||||||
return LuauVMObfuscator().obfuscate(code)
|
return LuauVMObfuscator().obfuscate(code)
|
||||||
Loading…
x
Reference in New Issue
Block a user