From 722fa03d5e583e4223a76f318a0335400cd15bf5 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 31 Jan 2026 13:26:16 +0000 Subject: [PATCH] 14:26 --- core/__pycache__/obfuscator.cpython-311.pyc | Bin 9522 -> 9521 bytes core/__pycache__/parser.cpython-311.pyc | Bin 4883 -> 6125 bytes core/obfuscator.py | 4 +- core/parser.py | 68 +++++++++------- fixer.py | 82 ++++++++++++++++++++ parser_b64.txt | 1 + test_obfuscator.py | 10 +++ 7 files changed, 136 insertions(+), 29 deletions(-) create mode 100644 fixer.py create mode 100644 parser_b64.txt create mode 100644 test_obfuscator.py diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index a958fe2c103d6395197778f17dce39157fc770a4..11ea2ea393b0800db5024a92c71364f44e77de98 100644 GIT binary patch delta 34 pcmdnwwb6@rIWI340}#mntIZVH$orFvapPuo?taG2(|Kk~006Zu3bX(K delta 36 rcmdn!waJTjIWI340}y2Yt<4nL$orFvanojY?tVtb_|4OJW=jA7&#wz% diff --git a/core/__pycache__/parser.cpython-311.pyc b/core/__pycache__/parser.cpython-311.pyc index 66e5d0765879b9370a29ee5b90fd234e8dcb5c88..5d032f5382b5869f59af87e9c0483ef21161be55 100644 GIT binary patch literal 6125 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 T=_5g)z2qm{_VaT(R7w8}_PxIZ delta 2146 zcmZuySxj435WV+p-ffm=Fk9lJfN=m53MCs$38V=P7@DO@f{|tMUL6Opo%fuUI(ErN zJ|ZmmOHwaSc+ z#rt}C67TdRx_c76Jqe$Oe&9jIS=RxdhkD>okM$26i?cqp+0Es+$%rK9gji%s4y!pf z8c}n+a%EapL6cME={FP$dB~o}9#X~Cm>GSAF^>vB9&!!*Q;g6eskR&%R31wx35mH> zOw1sfSn@$ul1!3~88)*8k4yX(onT}7EgJX&*^MiNB$wbaIl#x>1Ui=&B)Hz*y8kVc`NM|WP+LGc@!5e2tU;C z!k+ZI)m1u)yN)mL5`P_C5F`OmC$W$ZJ^52VdXOGQ%Yd6HL{AwiO%IKc3aN*>6g9)6kSG-r`#qw-`-mi)1|qjHWfj1RS1DDu~)+77x&?FE2*KTKX;dWN&)vhIV12=78_Xci(`!6s(?PhZvEu^v=6mncZ391{o2c}(BL%}fg z>tVW46Y_5crmx7r(t4te@@o<5MsA@nNFHi|4@q)3mNSOs*_dDJ4dn>cq}`y>n+UoD zR$HT zO>A2i+g8OkDjl95PJ0);DKGg!Y;YM+WzAw}K9rtXn9A%~2yfZR8&Ro!(L8TXTNkV; zE9tiHo_hjaTI6IMwI7*3Fu!kIvSu!?JKQNg>uh?^@J+*N4=_j$u!I$77&ZFny McglPEKLX9yzbE4E<^TWy diff --git a/core/obfuscator.py b/core/obfuscator.py index 9527a5d..04e90f4 100644 --- a/core/obfuscator.py +++ b/core/obfuscator.py @@ -43,7 +43,7 @@ local _D = function(data) data = string.gsub(data, '[^'.._B64..'=]', '') return (data:gsub('.', function(x) if (x == '=') then return '' end - local r,f='',(_B_64:find(x)-1) + local r,f='',(_B64: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) @@ -178,4 +178,4 @@ end) return f"-- Error: {str(e)}" def obfuscate(code): - return LuauVMObfuscator().obfuscate(code) + return LuauVMObfuscator().obfuscate(code) \ No newline at end of file diff --git a/core/parser.py b/core/parser.py index bfcb42d..67f7e63 100644 --- a/core/parser.py +++ b/core/parser.py @@ -5,21 +5,20 @@ class Lexer: self.code = code self.tokens = [] self.pos = 0 + # Correctly formatted rules with escaped backslashes for regex character classes 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+') + ('COMMENT', re.compile(r'--\[\[.*?\].*?|--.*', re.DOTALL)), + ('STRING', re.compile(r'"(?:\\.|[^"\\])*"|\'(?:\\.|[^\\\])*\'|\[\[.*?\].*?\]', re.DOTALL)), + ('NUMBER', re.compile(r'\d+\.?\d*')), + ('KEYWORD', re.compile(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', re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')), + ('OP', re.compile(r'==|~=|<=|>=|\.\.\.|\.|>>|<<|[\+\-\*/%^#=\<>\(\)\{\}\[\];:, ]')) ] def tokenize(self): while self.pos < len(self.code): match = None - for name, pattern in self.rules: - regex = re.compile(pattern, re.DOTALL) + for name, regex in self.rules: match = regex.match(self.code, self.pos) if match: if name != 'SPACE' and name != 'COMMENT': @@ -27,23 +26,24 @@ class Lexer: self.pos = match.end() break if not match: - self.pos += 1 # Skip unknown + # Skip unknown characters + self.pos += 1 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 peek(self, offset=0): + index = self.pos + offset + return self.tokens[index] if index < len(self.tokens) else (None, None) - def consume(self, expected_type=None): + def consume(self, expected_type=None, expected_value=None): token = self.peek() - if expected_type and token[0] != expected_type: - return None + if not token[0]: return None + if expected_type and token[0] != expected_type: return None + if expected_value and token[1] != expected_value: return None self.pos += 1 return token @@ -59,23 +59,37 @@ class Parser: def parse_statement(self): token = self.peek() + if not token[0]: return None + + if token[1] == 'local': + self.consume() + ident = self.consume('IDENT') + if ident and self.peek()[1] == '=': + self.consume() + val = self.parse_expression() + return {'type': 'assign', 'name': ident[1], 'value': val, 'local': True} + return None + if token[0] == 'IDENT': ident = self.consume()[1] next_token = self.peek() if next_token[1] == '(': - # Function call - self.consume() # ( + self.consume() args = [] - while self.peek()[1] != ')': - args.append(self.peek()[1]) # Simplified: only strings/numbers/idents - self.consume() + while self.peek()[1] and self.peek()[1] != ')': + args.append(self.parse_expression()) if self.peek()[1] == ',': self.consume() - self.consume() # ) + self.consume('OP', ')') 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} + self.consume() + val = self.parse_expression() + return {'type': 'assign', 'name': ident, 'value': val, 'local': False} + return None + + def parse_expression(self): + token = self.consume() + if not token: return None + return token[1] \ No newline at end of file diff --git a/fixer.py b/fixer.py new file mode 100644 index 0000000..51caef8 --- /dev/null +++ b/fixer.py @@ -0,0 +1,82 @@ +# fixer.py +content = """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 + return self.tokens + +class Parser: + 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] == '(': + self.consume() + args = [] + while self.peek()[1] != ')': + args.append(self.peek()[1]) + self.consume() + if self.peek()[1] == ',': + self.consume() + self.consume() + return {'type': 'call', 'name': ident, 'args': args} + elif next_token[1] == '=': + self.consume() + value = self.consume()[1] + return {'type': 'assign', 'name': ident, 'value': value} + return None +""" +with open("core/parser.py", "w") as f: + f.write(content) + diff --git a/parser_b64.txt b/parser_b64.txt new file mode 100644 index 0000000..2302f20 --- /dev/null +++ b/parser_b64.txt @@ -0,0 +1 @@ +aW1wb3J0IHJlCgpjbGFzcyBMZXhlcjoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBjb2RlKToKICAgICAgICBzZWxmLmNvZGUgPSBjb2RlCiAgICAgICAgc2VsZi50b2tlbnMgPSBbXQogICAgICAgIHNlbGYucG9zID0gMAogICAgICAgIHNlbGYucnVsZXMgPSBbCiAgICAgICAgICAgICgnQ09NTUVOVCcsIHInLS1cW1xbLio/XF1cXXwtLS4qJyksCiAgICAgICAgICAgICgnU1RSSU5HJywgciciKD86XC58W14iXF0pKiJ8XCcoPzpcLnxbXlwnXF0pKlwnfFxbXFsuKj9cXVxdJyksCiAgICAgICAgICAgICgnTlVNQkVSJywgcidcZCtcLj9cZConKSwKICAgICAgICAgICAgKCdLRVlXT1JEJywgcidcYihhbmR8YnJlYWt8ZG98ZWxzZXxlbHNlaWZ8ZW5kfGZhbHNlfGZvcnxmdW5jdGlvbnxpZnxpbnxsb2NhbHxuaWx8bm90fG9yfHJlcGVhdHxyZXR1cm58dGhlbnx0cnVlfHVudGlsfHdoaWxlKVxiJyksCiAgICAgICAgICAgICgnSURFTlQnLCByJ1thLXpBLVpfXVthLXpBLVowLTlfXSonKSwKICAgICAgICAgICAgKCdPUCcsIHInPT18fj18PD18Pj18XC5cLlwufFwuXC58Pj58PDx8W1wrXC1cKi8lXiM9XDw+XChcKVx7XH1cW1xdOzosXC5dJyksCiAgICAgICAgICAgICgnU1BBQ0UnLCByJ1xzKycpCiAgICAgICAgXQoKICAgIGRlZiB0b2tlbml6ZShzZWxmKToKICAgICAgICB3aGlsZSBzZWxmLnBvcyA8IGxlbihzZWxmLmNvZGUpOgogICAgICAgICAgICBtYXRjaCA9IE5vbmUKICAgICAgICAgICAgZm9yIG5hbWUsIHBhdHRlcm4gaW4gc2VsZi5ydWxlczoKICAgICAgICAgICAgICAgIHJlZ2V4ID0gcmUuY29tcGlsZShwYXR0ZXJuLCByZS5ET1RBTEwpCiAgICAgICAgICAgICAgICBtYXRjaCA9IHJlZ2V4Lm1hdGNoKHNlbGYuY29kZSwgc2VsZi5wb3MpCiAgICAgICAgICAgICAgICBpZiBtYXRjaDoKICAgICAgICAgICAgICAgICAgICBpZiBuYW1lICE9ICdTUEFDRScgYW5kIG5hbWUgIT0gJ0NPTU1FTlQnOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnRva2Vucy5hcHBlbmQoKG5hbWUsIG1hdGNoLmdyb3VwKDApKSkKICAgICAgICAgICAgICAgICAgICBzZWxmLnBvcyA9IG1hdGNoLmVuZCgpCiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgaWYgbm90IG1hdGNoOgogICAgICAgICAgICAgICAgc2VsZi5wb3MgKz0gMQogICAgICAgIHJldHVybiBzZWxmLnRva2VucwoKY2xhc3MgUGFyc2VyOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIHRva2Vucyk6CiAgICAgICAgc2VsZi50b2tlbnMgPSB0b2tlbnMKICAgICAgICBzZWxmLnBvcyA9IDAKCiAgICBkZWYgcGVlayhzZWxmKToKICAgICAgICByZXR1cm4gc2VsZi50b2tlbnNbc2VsZi5wb3NdIGlmIHNlbGYucG9zIDwgbGVuKHNlbGYudG9rZW5zKSBlbHNlIChOb25lLCBOb25lKQoKICAgIGRlZiBjb25zdW1lKHNlbGYsIGV4cGVjdGVkX3R5cGU9Tm9uZSk6CiAgICAgICAgdG9rZW4gPSBzZWxmLnBlZWsoKQogICAgICAgIGlmIGV4cGVjdGVkX3R5cGUgYW5kIHRva2VuWzBdICE9IGV4cGVjdGVkX3R5cGU6CiAgICAgICAgICAgIHJldHVybiBOb25lCiAgICAgICAgc2VsZi5wb3MgKz0gMQogICAgICAgIHJldHVybiB0b2tlbgoKICAgIGRlZiBwYXJzZShzZWxmKToKICAgICAgICBub2RlcyA9IFtdCiAgICAgICAgd2hpbGUgc2VsZi5wb3MgPCBsZW4oc2VsZi50b2tlbnMpOgogICAgICAgICAgICBub2RlID0gc2VsZi5wYXJzZV9zdGF0ZW1lbnQoKQogICAgICAgICAgICBpZiBub2RlOgogICAgICAgICAgICAgICAgbm9kZXMuYXBwZW5kKG5vZGUpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzZWxmLnBvcyArPSAxCiAgICAgICAgcmV0dXJuIG5vZGVzCgogICAgZGVmIHBhcnNlX3N0YXRlbWVudChzZWxmKToKICAgICAgICB0b2tlbiA9IHNlbGYucGVlaygpCiAgICAgICAgaWYgdG9rZW5bMF0gPT0gJ0lERU5UJzoKICAgICAgICAgICAgaWRlbnQgPSBzZWxmLmNvbnN1bWUoKVsxXQogICAgICAgICAgICBuZXh0X3Rva2VuID0gc2VsZi5wZWVrKCkKICAgICAgICAgICAgaWYgbmV4dF90b2tlblsxXSA9PSAnKCc6CiAgICAgICAgICAgICAgICBzZWxmLmNvbnN1bWUoKQogICAgICAgICAgICAgICAgYXJncyA9IFtdCiAgICAgICAgICAgICAgICB3aGlsZSBzZWxmLnBlZWsoKVsxXSAhPSAnKSc6CiAgICAgICAgICAgICAgICAgICAgYXJncy5hcHBlbmQoc2VsZi5wZWVrKClbMV0pCiAgICAgICAgICAgICAgICAgICAgc2VsZi5jb25zdW1lKCkKICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLnBlZWsoKVsxXSA9PSAnLCc6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY29uc3VtZSgpCiAgICAgICAgICAgICAgICBzZWxmLmNvbnN1bWUoKQogICAgICAgICAgICAgICAgcmV0dXJuIHsndHlwZSc6ICdjYWxsJywgJ25hbWUnOiBpZGVudCwgJ2FyZ3MnOiBhcmdzfQogICAgICAgICAgICBlbGlmIG5leHRfdG9rZW5bMV0gPT0gJz0nOgogICAgICAgICAgICAgICAgc2VsZi5jb25zdW1lKCkKICAgICAgICAgICAgICAgIHZhbHVlID0gc2VsZi5jb25zdW1lKClbMV0KICAgICAgICAgICAgICAgIHJldHVybiB7J3R5cGUnOiAnYXNzaWduJywgJ25hbWUnOiBpZGVudCwgJ3ZhbHVlJzogdmFsdWV9CiAgICAgICAgcmV0dXJuIE5vbmUK diff --git a/test_obfuscator.py b/test_obfuscator.py new file mode 100644 index 0000000..832877c --- /dev/null +++ b/test_obfuscator.py @@ -0,0 +1,10 @@ +from core.obfuscator import obfuscate + +test_code = """ +local x = 10 +print(x) +print("Hello, Luau!") +""" + +result = obfuscate(test_code) +print(result)