From d2c45727f6fae781120e7c4cc47d8c263c6ad9c2 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 31 Jan 2026 18:32:21 +0000 Subject: [PATCH] 19:32 --- core/__pycache__/obfuscator.cpython-311.pyc | Bin 31624 -> 32097 bytes core/__pycache__/parser.cpython-311.pyc | Bin 10864 -> 11136 bytes core/obfuscator.py | 17 ++++-- core/parser.py | 14 ++--- verify_syntax.py | 56 ++++++++++++++++++++ 5 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 verify_syntax.py diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index 0913f676008cda5fdb57e5fafc748c9b4169a87d..4e0e9219cb722b3d361da67be5d3e00bcc4b93c4 100644 GIT binary patch delta 6956 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 delta 709 zcmZ{i&ubGw6vy{9yBmzz#ONleCb*j>)g+*;P-v8*)q@fOnwo%Os1OsIq&3-gk_uuG z{{o>t1jQdTCy$~F{y6ohCrQE6;vstTB3tMwpg1onRZt(pXJ)?d&Aj)9xqHdZE6)|h zC2*S_zEivZQmM<(HE+uq5mfWN>nwP^lFJr$pqpX01fb)H@*N_k&yxdZjGt~61#HIy zI2G7qu6o}9Br)xK3JqKx9Ww)aGl2Wl4}SL(M^0D~%gTPr*tfC=Z8Zd5bo(!2&Hq|H z#^q)P*Wy8b**h~GTz94}a4jLSG@sZN4oj|IZ&i)5B^Ftw*@Hq4X4!cPa`b~Nac;R$ zVnv+R{KvDTJ6VVhpCsfttf5BBf;uabP~d1fIrM?C5mIOHo)&eUCf|gk-`q!S3_|!* zdnUSk;V!P}UypPX<8Nb~?Bz~ru2ZRYYV)5e3mc_{&JAOuWOU9g($JUqc&I*7%@>gg zkS9aChV2wCjs{;v+i-A^av6jrN+oho6@wbGxE>3`HS=@q+fca1T|J0ej)u{)q~%7D z-P-P#8TjS!)Z{GP;v-z;NJ#7itxpjcfnI{ma3thEp2NU=JOT`F#$zyVK8{ymH^mI1 z8G4doS>yZW0~}B0G_Q1szQZS diff --git a/core/obfuscator.py b/core/obfuscator.py index ce867d4..8996663 100644 --- a/core/obfuscator.py +++ b/core/obfuscator.py @@ -46,7 +46,7 @@ class LuauVMObfuscator: def minify(self, code): code = re.sub(r'--.*', '', code) code = re.sub(r'\s+', ' ', code) - for op in ['==', '~=', '<=', '>=', '=', r'\+', r'\*', '/', '>', '<', ',', ';', ':']: + for op in ['==', '~=', '<=', '>=', '=', r'\+', r'\*', '/', '>', '<', ',', ';', ':', '-']: code = re.sub(r'\s*' + op + r'\s*', op.replace('\\', ''), code) return code.strip() @@ -81,7 +81,6 @@ class LuauVMObfuscator: "CHARS": self.get_var("chars"), "LOOKUP": self.get_var("lookup"), "GETC": self.get_var("getc") } - # Using triple single quotes to avoid confusion vm_lua = f'''local {v['ENV']}=setmetatable({{}},{{__index=getfenv()}}); local {v['CHARS']}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; local {v['LOOKUP']}={{}}; @@ -137,8 +136,10 @@ local {v['EXEC']}=function() if a then a[{v['REGS']}[{v['B']}] or {v['GETC']}({v['B']})]={v['REGS']}[{v['C']}] end elseif {v['OP']}=={self.opcodes.index('SELF')} then local b={v['REGS']}[{v['B']}]; - {v['REGS']}[{v['A']}+1]=b; - {v['REGS']}[{v['A']}]=b[{v['GETC']}({v['C']})]; + if b then + {v['REGS']}[{v['A']}+1]=b; + {v['REGS']}[{v['A']}]=b[{v['GETC']}({v['C']})]; + end elseif {v['OP']}=={self.opcodes.index('ADD')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)+({v['REGS']}[{v['C']}] or 0) elseif {v['OP']}=={self.opcodes.index('SUB')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)-({v['REGS']}[{v['C']}] or 0) elseif {v['OP']}=={self.opcodes.index('MUL')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)*({v['REGS']}[{v['C']}] or 0) @@ -157,7 +158,7 @@ local {v['EXEC']}=function() elseif {v['OP']}=={self.opcodes.index('RETURN')} then break end; end; end; -{v['SPW']}({v['EXEC']});''' +({v['SPW']})({v['EXEC']});''' return self.minify(vm_lua) def compile_to_bytecode(self, ast): @@ -232,9 +233,15 @@ end; kr = self.next_reg; self.next_reg += 1; gen_expr(t['key'], kr) emit("SETTABLE", br, kr, vr); self.next_reg -= 1 self.next_reg -= 1 + elif t['type'] == 'variable': + emit("SETGLOBAL", vr, add_const(t['name'])) else: emit("SETGLOBAL", vr, add_const(node['name'])) elif node['type'] == 'call': gen_call(node, self.next_reg) elif node['type'] == 'method_call': gen_method_call(node, self.next_reg) + elif node['type'] == 'return': + vr = self.next_reg; self.next_reg += 1; gen_expr(node['value'], vr) + emit("RETURN", vr, 2) + self.next_reg -= 1 emit("RETURN") return {"instructions": instructions, "constants": constants} diff --git a/core/parser.py b/core/parser.py index 2b977fb..6f33e9c 100644 --- a/core/parser.py +++ b/core/parser.py @@ -6,7 +6,6 @@ class Lexer: self.tokens = [] self.pos = 0 LB, RB, DQ, SQ, BS = chr(91), chr(93), chr(34), chr(39), chr(92) - # Added : to OP_LIST OP_LIST = r'==|~=|<=|>=|\.\.\.|\.\.|>>|<<|\+|\-|\*|/|%|\^|#|=|\<|\>|\(|\)|\{|\}|' + BS + LB + '|' + BS + RB + '|;|:|,|\.' self.rules = [ ('COMMENT', re.compile('--' + LB + LB + '.*?' + RB + RB + '|--.*', re.DOTALL)), @@ -44,7 +43,7 @@ class Parser: while self.pos < len(self.tokens): node = self.parse_statement() if node: nodes.append(node) - else: self.pos += 1 # Still skipping, but hopefully parse_statement is better + else: self.pos += 1 return nodes def parse_statement(self): tk = self.peek() @@ -56,6 +55,11 @@ class Parser: self.consume(); return {'type': 'assign', 'name': ident[1], 'value': self.parse_expression(), 'local': True} return {'type': 'assign', 'name': ident[1], 'value': {'type': 'KEYWORD', 'value': 'nil'}, 'local': True} return None + if tk[1] == 'return': + self.consume() + return {'type': 'return', 'value': self.parse_expression()} + if tk[1] == ';': + self.consume(); return None start = self.pos; expr = self.parse_prefix_expression() if expr: if self.peek()[1] == '=': @@ -75,15 +79,13 @@ class Parser: elif nt[1] == ':': self.consume(); m = self.consume('IDENT') if m: - # Method call if self.peek()[1] == '(': self.consume(); args = [] if self.peek()[1] != ')': args.append(self.parse_expression()) while self.peek()[1] == ',': self.consume(); args.append(self.parse_expression()) self.consume('OP', ')'); expr = {'type': 'method_call', 'base': expr, 'method': m[1], 'args': args} - else: # Not a call, just a colon access? (Rare in Lua, usually an error, but let's be safe) - expr = {'type': 'index', 'base': expr, 'key': {'type': 'STRING', 'value': '"'+m[1]+'"'}} + else: expr = {'type': 'index', 'base': expr, 'key': {'type': 'STRING', 'value': '"'+m[1]+'"'}} else: break elif nt[1] == '[': self.consume(); key = self.parse_expression(); self.consume('OP', ']'); expr = {'type': 'index', 'base': expr, 'key': key} @@ -112,4 +114,4 @@ class Parser: if tk[0] in ['STRING', 'NUMBER']: v = tk[1]; self.consume(); return {'type': tk[0], 'value': v} if tk[1] in ['true', 'false', 'nil']: return {'type': 'KEYWORD', 'value': self.consume()[1]} if tk[1] == '(': self.consume(); e = self.parse_expression(); self.consume('OP', ')'); return e - return self.parse_prefix_expression() + return self.parse_prefix_expression() \ No newline at end of file diff --git a/verify_syntax.py b/verify_syntax.py new file mode 100644 index 0000000..88b0289 --- /dev/null +++ b/verify_syntax.py @@ -0,0 +1,56 @@ +from core.obfuscator import obfuscate +import re + +test_cases = [ + """ + local a = 10 + print(a) + """, + """ + game:GetService("Players").LocalPlayer:Kick("Test") + """, + """ + return 123 + """, + """ + x = 5 + x = x + 1 + print(x) + """, + """ + local t = {a = 1} + t.a = 2 + print(t.a) + """ +] + +def check_syntax(lua_code): + # Basic check for balanced quotes and parens in the generated code + # Also check for the specific patterns we fixed + if "''" in lua_code and "(''" not in lua_code: # Check for the fixed inst_b64 part + # Note: ('' is fine for DEC function call if it was meant to be that, but we changed it to (') + pass + + # Check for "task and task.spawn or spawn(" without surrounding parens + # Our fix: (task and task.spawn or spawn)(... + if "task and task.spawn or spawn(" in lua_code: + if "(task and task.spawn or spawn)(" not in lua_code: + return False, "Missing parentheses around SPW" + + # Check for empty string (failed obfuscation) + if not lua_code.strip(): + return False, "Empty output" + + # Check for error comments + if "-- Obfuscation Error" in lua_code: + return False, "Obfuscation Error detected" + + return True, "OK" + +for i, code in enumerate(test_cases): + obfuscated = obfuscate(code) + success, msg = check_syntax(obfuscated) + print(f"Test {i}: {success} - {msg}") + if not success: + print(f"Code: {code}") + print(f"Obfuscated snippet: {obfuscated[:200]}...")