diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index a5a3068..0bc962a 100644 Binary files a/core/__pycache__/obfuscator.cpython-311.pyc and b/core/__pycache__/obfuscator.cpython-311.pyc differ diff --git a/core/obfuscator.py b/core/obfuscator.py index d30098b..b7f0d9a 100644 --- a/core/obfuscator.py +++ b/core/obfuscator.py @@ -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) \ No newline at end of file + return LuauVMObfuscator().obfuscate(code)