14:56
This commit is contained in:
parent
a998fae926
commit
33ef3d1b36
Binary file not shown.
@ -14,40 +14,81 @@ class LuauVMObfuscator:
|
||||
"LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN",
|
||||
"FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG"
|
||||
]
|
||||
# Randomize opcode mapping
|
||||
self.op_order = list(range(len(self.opcodes)))
|
||||
random.shuffle(self.op_order)
|
||||
|
||||
# Arithmetic keys for opcode decoding
|
||||
self.k1 = random.randint(10, 100)
|
||||
self.k2 = random.randint(10, 100)
|
||||
self.k1 = random.randint(50, 200)
|
||||
self.k2 = random.randint(50, 200)
|
||||
self.k3 = random.randint(1, 10) # Multiplier/Step
|
||||
|
||||
# Opcode to encoded ID: (real_index + k1) ^ k2
|
||||
self.op_to_id = {name: ((self.opcodes.index(name) + self.k1) ^ self.k2) % 256 for name in self.opcodes}
|
||||
|
||||
def encrypt_string(self, s, key):
|
||||
return "".join(chr(ord(c) ^ ((key + i) % 256)) for i, c in enumerate(s))
|
||||
# More complex XOR scheme: each byte depends on previous byte and index
|
||||
res = []
|
||||
last = key % 256
|
||||
for i, c in enumerate(s):
|
||||
k = (key + i + last) % 256
|
||||
last = ord(c)
|
||||
res.append(chr(ord(c) ^ k))
|
||||
return "".join(res)
|
||||
|
||||
def generate_vm_source(self, bytecode):
|
||||
raw_instructions = bytecode['instructions']
|
||||
# Each instruction is [OP, A, B, C]
|
||||
|
||||
# SHUFFLE AND FLATTEN:
|
||||
# We will add a 'next' index to each instruction to break linear execution.
|
||||
# Format: [OP, A, B, C, NEXT_IDX_L, NEXT_IDX_H] (6 bytes)
|
||||
shuffled = []
|
||||
indices = list(range(len(raw_instructions)))
|
||||
random.shuffle(indices)
|
||||
|
||||
# Map original index to shuffled index
|
||||
pos_map = {orig: shuffled_idx for shuffled_idx, orig in enumerate(indices)}
|
||||
|
||||
# Prepare 6-byte instructions
|
||||
final_insts = [None] * len(raw_instructions)
|
||||
for i, orig_idx in enumerate(indices):
|
||||
inst = raw_instructions[orig_idx]
|
||||
|
||||
# Find next shuffled index
|
||||
if orig_idx + 1 < len(raw_instructions):
|
||||
next_orig = orig_idx + 1
|
||||
next_shuffled = pos_map[next_orig]
|
||||
else:
|
||||
next_shuffled = 0 # End
|
||||
|
||||
# Pack: [OP, A, B, C, Next_L, Next_H]
|
||||
packed = [
|
||||
inst[0], inst[1], inst[2], inst[3],
|
||||
next_shuffled & 0xFF, (next_shuffled >> 8) & 0xFF
|
||||
]
|
||||
final_insts[i] = packed
|
||||
|
||||
# Pack instructions into a string
|
||||
inst_str = "".join(chr(i) for inst in bytecode['instructions'] 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()
|
||||
|
||||
# Prepare constants
|
||||
encrypted_consts = []
|
||||
salt = random.randint(1000, 9999)
|
||||
for i, c in enumerate(bytecode['constants']):
|
||||
if c['type'] == 'string':
|
||||
# Encrypt with index-based key
|
||||
key = (i * 137 + 42) % 256
|
||||
# Encrypt with complex key
|
||||
key = (i * 149 + salt) % 256
|
||||
enc_val = self.encrypt_string(c['value'], key)
|
||||
encrypted_consts.append({"t": 1, "v": base64.b64encode(enc_val.encode('latin-1')).decode()})
|
||||
else:
|
||||
encrypted_consts.append({"t": 2, "v": c['value']})
|
||||
|
||||
consts_json = json.dumps(encrypted_consts)
|
||||
|
||||
# Starting shuffled index
|
||||
start_idx = pos_map[0]
|
||||
|
||||
vm_lua = f"""
|
||||
-- [[ LUAU-VM PROTECTED ]]
|
||||
-- [[ LUAU-VM HARDENED - V2 ]]
|
||||
local _ENV = getfenv()
|
||||
local _B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
local _D = function(data)
|
||||
@ -64,12 +105,31 @@ local _D = function(data)
|
||||
end))
|
||||
end
|
||||
|
||||
-- Anti-Analysis Layer
|
||||
local function _CHECK()
|
||||
-- Check for common hooks or debuggers
|
||||
local suspicious = {{ "getgenv", "getrenv", "getreg", "debug" }}
|
||||
for _, s in ipairs(suspicious) do
|
||||
if _ENV[s] then
|
||||
-- Fake failure or subtle corruption
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local _INST_RAW = _D('{inst_b64}')
|
||||
local _CONSTS = game:GetService("HttpService"):JSONDecode('{consts_json}')
|
||||
local _SALT = {salt}
|
||||
|
||||
local function _EXECUTE()
|
||||
if _CHECK() then
|
||||
-- Insert bogus delay or crash if hooked
|
||||
for i=1, 100000 do local x = math.sin(i) end
|
||||
end
|
||||
|
||||
local registers = {{}}
|
||||
local vip = 1
|
||||
local current = {start_idx}
|
||||
local running = true
|
||||
|
||||
local function get_const(idx)
|
||||
@ -77,22 +137,34 @@ local function _EXECUTE()
|
||||
if not c then return nil end
|
||||
if c.t == 1 then
|
||||
local raw = _D(c.v)
|
||||
local key = (idx * 137 + 42) % 256
|
||||
local key = (idx * 149 + _SALT) % 256
|
||||
local res = ""
|
||||
local last = key % 256
|
||||
for i=1, #raw do
|
||||
res = res .. string.char(bit32.bxor(string.byte(raw, i), (key + i - 1) % 256))
|
||||
local k = (key + i + last - 1) % 256
|
||||
local b = string.byte(raw, i)
|
||||
local char_code = bit32.bxor(b, k)
|
||||
res = res .. string.char(char_code)
|
||||
last = char_code
|
||||
end
|
||||
return res
|
||||
end
|
||||
return c.v
|
||||
end
|
||||
|
||||
while running and vip <= #_INST_RAW do
|
||||
local op_raw = string.byte(_INST_RAW, vip)
|
||||
local a = string.byte(_INST_RAW, vip + 1)
|
||||
local b = string.byte(_INST_RAW, vip + 2)
|
||||
local c = string.byte(_INST_RAW, vip + 3)
|
||||
vip = vip + 4
|
||||
-- MEGA-DISPATCH LOOP (Control-Flow Flattening)
|
||||
while running do
|
||||
local ptr = current * 6 + 1
|
||||
if ptr > #_INST_RAW then break end
|
||||
|
||||
local op_raw = string.byte(_INST_RAW, ptr)
|
||||
local a = string.byte(_INST_RAW, ptr + 1)
|
||||
local b = string.byte(_INST_RAW, ptr + 2)
|
||||
local c = string.byte(_INST_RAW, ptr + 3)
|
||||
local next_l = string.byte(_INST_RAW, ptr + 4)
|
||||
local next_h = string.byte(_INST_RAW, ptr + 5)
|
||||
|
||||
current = next_l + (next_h * 256)
|
||||
|
||||
-- Arithmetic Opcode Decoding
|
||||
local op = bit32.bxor(op_raw, {self.k2}) - {self.k1}
|
||||
@ -114,6 +186,11 @@ local function _EXECUTE()
|
||||
elseif op == {self.opcodes.index('RETURN')} then
|
||||
running = false
|
||||
end
|
||||
|
||||
-- Bogus execution path to confuse static analysis
|
||||
if op == -999 then
|
||||
running = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -129,7 +206,7 @@ task.spawn(_EXECUTE)
|
||||
|
||||
def add_const(val):
|
||||
if isinstance(val, str):
|
||||
if (val.startswith('"') and val.endswith('"')) or (val.startswith("'" ) and val.endswith("'" )):
|
||||
if (val.startswith("'") and val.endswith("'")) or (val.startswith("\"") and val.endswith("\"")):
|
||||
val = val[1:-1]
|
||||
|
||||
for i, c in enumerate(constants):
|
||||
@ -193,4 +270,4 @@ task.spawn(_EXECUTE)
|
||||
return f"-- Error: {str(e)}\n{traceback.format_exc()}"
|
||||
|
||||
def obfuscate(code):
|
||||
return LuauVMObfuscator().obfuscate(code)
|
||||
return LuauVMObfuscator().obfuscate(code)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user