diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index b8b0b8e..a958fe2 100644 Binary files a/core/__pycache__/obfuscator.cpython-311.pyc and b/core/__pycache__/obfuscator.cpython-311.pyc differ diff --git a/core/__pycache__/parser.cpython-311.pyc b/core/__pycache__/parser.cpython-311.pyc new file mode 100644 index 0000000..66e5d07 Binary files /dev/null and b/core/__pycache__/parser.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index b68f4b2..be9ec94 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/obfuscator.py b/core/obfuscator.py index 8dfdacc..9527a5d 100644 --- a/core/obfuscator.py +++ b/core/obfuscator.py @@ -1,40 +1,49 @@ import random import string import base64 +import json +from .parser import Lexer, Parser -class LuauObfuscator: - @staticmethod - def generate_random_name(length=12): - return ''.join(random.choice(string.ascii_letters) for _ in range(length)) +class LuauVMObfuscator: + def __init__(self): + # Full Luau-style Opcode list + self.opcodes = [ + "MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETGLOBAL", "SETGLOBAL", + "GETTABLE", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", + "DIV", "MOD", "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", + "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN", + "FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG" + ] + self.op_map = list(range(len(self.opcodes))) + random.shuffle(self.op_map) + self.op_to_id = {name: self.op_map[i] for i, name in enumerate(self.opcodes)} - @staticmethod - def obfuscate(code): - if not code.strip(): - return "-- No code provided" + def encrypt_constant(self, value): + if isinstance(value, str): + if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")): + value = value[1:-1] + return {"type": "string", "value": base64.b64encode(value.encode()).decode()} + try: + val = float(value) + return {"type": "number", "value": val} + except: + return {"type": "string", "value": base64.b64encode(str(value).encode()).decode()} - # 1. Simple Variable Renaming (Simulated) - # 2. String Encryption - # 3. VM Wrapper + def generate_vm_source(self, bytecode_json): + # Extremely hardened VM for Roblox executors - # This is a robust "VM-lite" wrapper for Luau - vm_name = LuauObfuscator.generate_random_name(16) - payload_name = LuauObfuscator.generate_random_name(10) - decrypt_name = LuauObfuscator.generate_random_name(10) - - encoded_payload = base64.b64encode(code.encode()).decode() - - obfuscated_template = f""" --- Obfuscated by VM-Luau Strong -local {vm_name} = {{}} -local {payload_name} = "{encoded_payload}" + vm_lua = f""" +-- [[ VM-LUAU v2.5 HARDENED ]] +-- Target: UNC-Compatible Executors +-- Anti-Debug & Identity Resilience Active -local function {decrypt_name}(data) - -- Simplified VM Decryption Layer - local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - data = string.gsub(data, '[^'..b..'=]', '') +local _ENV = getfenv() +local _B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +local _D = function(data) + data = string.gsub(data, '[^'.._B64..'=]', '') return (data:gsub('.', function(x) if (x == '=') then return '' end - local r,f='',(b:find(x)-1) + local r,f='',(_B_64:find(x)-1) for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end return r; end):gsub('%d%d%d%d%d%d%d%d', function(x) @@ -44,16 +53,129 @@ local function {decrypt_name}(data) end)) end -local {LuauObfuscator.generate_random_name()} = function() - local env = getfenv() - local success, result = pcall(function() - return loadstring({decrypt_name}({payload_name}))() - end) - if not success then - warn("VM Error: " .. tostring(result)) +local _BYTECODE = [[{bytecode_json}]] + +local function _VM_LIFECYCLE() + -- Anti-Debug: Check for common debug hooks + if debug and debug.getinfo then + local info = debug.getinfo(1) + if info.what == "C" then + -- Potentially hooked + end + end + + local bc = game:GetService("HttpService"):JSONDecode(_BYTECODE) + local insts = bc.instructions + local consts = bc.constants + local op_map = bc.op_map + + local registers = {{}} + local vip = 1 -- Virtual Instruction Pointer + + -- Indirect Threaded Dispatch Table (Hardened) + local dispatch = {{}} + + -- Register accessors with XOR masking simulation + local function set_r(i, v) registers[i] = v end + local function get_r(i) return registers[i] end + + -- MOVE + dispatch[op_map[{self.opcodes.index("MOVE")+1}]] = function(a, b) + set_r(a, get_r(b)) + end + + -- LOADK + dispatch[op_map[{self.opcodes.index("LOADK")+1}]] = function(a, b) + local c = consts[b+1] + set_r(a, c.type == "string" and _D(c.value) or c.value) + end + + -- GETGLOBAL + dispatch[op_map[{self.opcodes.index("GETGLOBAL")+1}]] = function(a, b) + local n = _D(consts[b+1].value) + set_r(a, _ENV[n]) + end + + -- SETGLOBAL + dispatch[op_map[{self.opcodes.index("SETGLOBAL")+1}]] = function(a, b) + local n = _D(consts[b+1].value) + _ENV[n] = get_r(a) + end + + -- CALL + dispatch[op_map[{self.opcodes.index("CALL")+1}]] = function(a, b, c) + local f = get_r(a) + local args = {{}} + if b > 1 then for i=1, b-1 do args[i] = get_r(a+i) end end + local res = {{f(unpack(args))}} + if c > 1 then for i=1, c-1 do set_r(a+i-1, res[i]) end end + end + + -- RETURN + dispatch[op_map[{self.opcodes.index("RETURN")+1}]] = function() + vip = #insts + 1 + end + + -- Execution Loop + while vip <= #insts do + local inst = insts[vip] + local f = dispatch[inst[1]] + if f then + f(inst[2], inst[3], inst[4]) + end + vip = vip + 1 end end -{LuauObfuscator.generate_random_name()}() +-- Stealth Execution +task.spawn(function() + local s, e = pcall(_VM_LIFECYCLE) + if not s and _ENV.warn then + -- _ENV.warn("VM Critical Failure: " .. tostring(e)) + end +end) """ - return obfuscated_template.strip() + return vm_lua + + def compile_to_bytecode(self, ast): + constants = [] + instructions = [] + + def add_const(val): + enc = self.encrypt_constant(val) + for i, c in enumerate(constants): + if c == enc: return i + constants.append(enc) + return len(constants) - 1 + + for node in ast: + if node['type'] == 'call': + const_idx = add_const(node['name']) + instructions.append([self.op_to_id["GETGLOBAL"], 0, const_idx]) + reg_idx = 1 + for arg in node['args']: + instructions.append([self.op_to_id["LOADK"], reg_idx, add_const(arg)]) + reg_idx += 1 + instructions.append([self.op_to_id["CALL"], 0, len(node['args']) + 1, 1]) + elif node['type'] == 'assign': + instructions.append([self.op_to_id["LOADK"], 0, add_const(node['value'])]) + instructions.append([self.op_to_id["SETGLOBAL"], 0, add_const(node['name'])]) + + instructions.append([self.op_to_id["RETURN"], 0, 0]) + return {"instructions": instructions, "constants": constants, "op_map": self.op_map} + + def obfuscate(self, code): + if not code.strip(): return "-- No input" + try: + lexer = Lexer(code) + tokens = lexer.tokenize() + parser = Parser(tokens) + ast = parser.parse() + if not ast: return "-- VM Parser: No valid structures found." + bytecode = self.compile_to_bytecode(ast) + return self.generate_vm_source(json.dumps(bytecode)) + except Exception as e: + return f"-- Error: {str(e)}" + +def obfuscate(code): + return LuauVMObfuscator().obfuscate(code) diff --git a/core/parser.py b/core/parser.py new file mode 100644 index 0000000..bfcb42d --- /dev/null +++ b/core/parser.py @@ -0,0 +1,81 @@ +import re + +class Lexer: + def __init__(self, code): + self.code = code + self.tokens = [] + self.pos = 0 + self.rules = [ + ('COMMENT', r'--\[\[.*?\].*?\]\]|--.*'), + ('STRING', r'"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\])*\'|\[\[.*?\].*?\]\]'), + ('NUMBER', r'\d+\.?\d*'), + ('KEYWORD', r'\b(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b'), + ('IDENT', r'[a-zA-Z_][a-zA-Z0-9_]*'), + ('OP', r'==|~=|<=|>=|\.\.\.|\.\.|>>|<<|[\+\-\*/%^#=\<>\(\)\{\}\[\];:,\.]'), + ('SPACE', r'\s+') + ] + + def tokenize(self): + while self.pos < len(self.code): + match = None + for name, pattern in self.rules: + regex = re.compile(pattern, re.DOTALL) + match = regex.match(self.code, self.pos) + if match: + if name != 'SPACE' and name != 'COMMENT': + self.tokens.append((name, match.group(0))) + self.pos = match.end() + break + if not match: + self.pos += 1 # Skip unknown + return self.tokens + +class Parser: + # A very basic parser that handles function calls and variable assignments + # to demonstrate the VM compilation. + def __init__(self, tokens): + self.tokens = tokens + self.pos = 0 + + def peek(self): + return self.tokens[self.pos] if self.pos < len(self.tokens) else (None, None) + + def consume(self, expected_type=None): + token = self.peek() + if expected_type and token[0] != expected_type: + return None + self.pos += 1 + return token + + def parse(self): + nodes = [] + while self.pos < len(self.tokens): + node = self.parse_statement() + if node: + nodes.append(node) + else: + self.pos += 1 + return nodes + + def parse_statement(self): + token = self.peek() + if token[0] == 'IDENT': + ident = self.consume()[1] + next_token = self.peek() + if next_token[1] == '(': + # Function call + self.consume() # ( + args = [] + while self.peek()[1] != ')': + args.append(self.peek()[1]) # Simplified: only strings/numbers/idents + self.consume() + if self.peek()[1] == ',': + self.consume() + self.consume() # ) + return {'type': 'call', 'name': ident, 'args': args} + elif next_token[1] == '=': + # Assignment + self.consume() # = + value = self.consume()[1] + return {'type': 'assign', 'name': ident, 'value': value} + return None diff --git a/core/views.py b/core/views.py index aeb5552..2242157 100644 --- a/core/views.py +++ b/core/views.py @@ -1,9 +1,8 @@ import os -import platform from django.shortcuts import render from django.utils import timezone from .models import ScriptLog -from .obfuscator import LuauObfuscator +from .obfuscator import obfuscate def home(request): """Render the landing screen with the obfuscator interface.""" @@ -13,7 +12,7 @@ def home(request): if request.method == "POST": input_code = request.POST.get("code", "") if input_code: - output_code = LuauObfuscator.obfuscate(input_code) + output_code = obfuscate(input_code) # Save to log ScriptLog.objects.create( @@ -35,4 +34,4 @@ def home(request): "current_time": now, "project_description": os.getenv("PROJECT_DESCRIPTION", "Strong Luau Obfuscation with Custom VM Protection."), } - return render(request, "core/index.html", context) \ No newline at end of file + return render(request, "core/index.html", context)