15:18
This commit is contained in:
parent
eda9b65091
commit
7699f45ec4
Binary file not shown.
@ -3,11 +3,11 @@ import string
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import re
|
||||||
from .parser import Lexer, Parser
|
from .parser import Lexer, Parser
|
||||||
|
|
||||||
class LuauVMObfuscator:
|
class LuauVMObfuscator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Full Luau-style Opcode list
|
|
||||||
self.opcodes = [
|
self.opcodes = [
|
||||||
"MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETGLOBAL", "SETGLOBAL",
|
"MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETGLOBAL", "SETGLOBAL",
|
||||||
"GETTABLE", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL",
|
"GETTABLE", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL",
|
||||||
@ -16,38 +16,32 @@ class LuauVMObfuscator:
|
|||||||
"FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG"
|
"FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG"
|
||||||
]
|
]
|
||||||
|
|
||||||
# Arithmetic keys for opcode decoding
|
self.k1 = random.randint(100, 500)
|
||||||
self.k1 = random.randint(100, 1000)
|
self.k2 = random.randint(100, 500)
|
||||||
self.k2 = random.randint(100, 1000)
|
self.k3 = random.randint(100, 500)
|
||||||
self.k3 = random.randint(100, 1000)
|
|
||||||
|
|
||||||
# Opcode to encoded ID: ((real_index + k1) ^ k2) + k3
|
|
||||||
self.op_to_id = {name: (((self.opcodes.index(name) + self.k1) ^ self.k2) + self.k3) % 4096 for name in self.opcodes}
|
self.op_to_id = {name: (((self.opcodes.index(name) + self.k1) ^ self.k2) + self.k3) % 4096 for name in self.opcodes}
|
||||||
|
|
||||||
# Variable Renaming Map
|
|
||||||
self.var_map = {}
|
self.var_map = {}
|
||||||
self.used_vars = set()
|
self.used_vars = set()
|
||||||
|
|
||||||
def get_var(self, hint="var"):
|
def get_var(self, hint="var"):
|
||||||
if hint in self.var_map:
|
if hint in self.var_map: return self.var_map[hint]
|
||||||
return self.var_map[hint]
|
chars = "lI"
|
||||||
|
length = random.randint(8, 16) # Shorter vars for single-line efficiency
|
||||||
chars = "lI1"
|
|
||||||
length = random.randint(32, 64)
|
|
||||||
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||||
while new_var in self.used_vars:
|
while new_var in self.used_vars:
|
||||||
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||||
|
|
||||||
self.used_vars.add(new_var)
|
self.used_vars.add(new_var)
|
||||||
self.var_map[hint] = new_var
|
self.var_map[hint] = new_var
|
||||||
return new_var
|
return new_var
|
||||||
|
|
||||||
def to_expr(self, n, depth=0):
|
def to_expr(self, n, depth=0):
|
||||||
if depth > 3 or (depth > 0 and random.random() < 0.15):
|
if depth > 1 or (depth > 0 and random.random() < 0.5):
|
||||||
return str(n)
|
return str(n)
|
||||||
|
|
||||||
r = random.randint(1, 2000)
|
r = random.randint(1, 50)
|
||||||
choice = random.choice(['add', 'sub', 'xor', 'mul', 'shl', 'shr', 'not'])
|
choice = random.choice(['add', 'sub', 'xor'])
|
||||||
|
|
||||||
if choice == 'add':
|
if choice == 'add':
|
||||||
return f"({self.to_expr(n - r, depth + 1)} + {self.to_expr(r, depth + 1)})"
|
return f"({self.to_expr(n - r, depth + 1)} + {self.to_expr(r, depth + 1)})"
|
||||||
@ -55,35 +49,9 @@ class LuauVMObfuscator:
|
|||||||
return f"({self.to_expr(n + r, depth + 1)} - {self.to_expr(r, depth + 1)})"
|
return f"({self.to_expr(n + r, depth + 1)} - {self.to_expr(r, depth + 1)})"
|
||||||
elif choice == 'xor':
|
elif choice == 'xor':
|
||||||
return f"bit32.bxor({self.to_expr(n ^ r, depth + 1)}, {self.to_expr(r, depth + 1)})"
|
return f"bit32.bxor({self.to_expr(n ^ r, depth + 1)}, {self.to_expr(r, depth + 1)})"
|
||||||
elif choice == 'mul':
|
|
||||||
if n != 0 and n % 2 == 0:
|
|
||||||
return f"({self.to_expr(n // 2, depth + 1)} * {self.to_expr(2, depth + 1)})"
|
|
||||||
return f"({self.to_expr(n, depth + 1)})"
|
|
||||||
elif choice == 'shl':
|
|
||||||
# n = (n >> 1) << 1 + (n & 1)
|
|
||||||
return f"bit32.bor(bit32.lshift({self.to_expr(n >> 1, depth + 1)}, {self.to_expr(1, depth + 1)}), {self.to_expr(n & 1, depth + 1)})"
|
|
||||||
elif choice == 'shr':
|
|
||||||
return f"bit32.rshift({self.to_expr(n << 1, depth + 1)}, {self.to_expr(1, depth + 1)})"
|
|
||||||
elif choice == 'not':
|
|
||||||
return f"bit32.bnot(bit32.bnot({self.to_expr(n, depth + 1)}))"
|
|
||||||
|
|
||||||
return str(n)
|
return str(n)
|
||||||
|
|
||||||
def opaque_predicate(self):
|
|
||||||
v1 = random.randint(100, 1000)
|
|
||||||
v2 = random.randint(100, 1000)
|
|
||||||
preds = [
|
|
||||||
f"({self.to_expr(v1)} == {self.to_expr(v1)})",
|
|
||||||
f"({self.to_expr(v1)} + {self.to_expr(v2)} > {self.to_expr(v1)})",
|
|
||||||
f"(math.floor(math.pi) == {self.to_expr(3)})",
|
|
||||||
f"(string.len('SUPREME') == {self.to_expr(7)})",
|
|
||||||
f"(bit32.bor({v1}, {v1}) == {v1})",
|
|
||||||
f"(bit32.band({v1}, {v1}) == {v1})",
|
|
||||||
f"(bit32.bxor({v1}, 0) == {v1})",
|
|
||||||
f"({self.to_expr(v2)} * 0 == 0)"
|
|
||||||
]
|
|
||||||
return random.choice(preds)
|
|
||||||
|
|
||||||
def encrypt_string(self, s, key):
|
def encrypt_string(self, s, key):
|
||||||
res = []
|
res = []
|
||||||
last = key % 256
|
last = key % 256
|
||||||
@ -93,6 +61,16 @@ class LuauVMObfuscator:
|
|||||||
res.append(chr(ord(c) ^ k))
|
res.append(chr(ord(c) ^ k))
|
||||||
return "".join(res)
|
return "".join(res)
|
||||||
|
|
||||||
|
def minify(self, code):
|
||||||
|
# Remove comments (though we don't add them, just in case)
|
||||||
|
code = re.sub(r'--.*', '', code)
|
||||||
|
# Replace multiple spaces with single space
|
||||||
|
code = re.sub(r'\s+', ' ', code)
|
||||||
|
# Remove spaces around operators and delimiters where safe
|
||||||
|
for op in ['==', '~=', '<=', '>=', '=', r'\+', '-', r'\*', '/', '>', '<', r'\(', r'\)', r'\{', r'\}', r'\[', r'\]', ',', ';', ':']:
|
||||||
|
code = re.sub(r'\s*' + op + r'\s*', op.replace('\\', ''), code)
|
||||||
|
return code.strip()
|
||||||
|
|
||||||
def generate_vm_source(self, bytecode):
|
def generate_vm_source(self, bytecode):
|
||||||
raw_instructions = bytecode['instructions']
|
raw_instructions = bytecode['instructions']
|
||||||
shuffled = []
|
shuffled = []
|
||||||
@ -104,12 +82,7 @@ class LuauVMObfuscator:
|
|||||||
final_insts = [None] * len(raw_instructions)
|
final_insts = [None] * len(raw_instructions)
|
||||||
for i, orig_idx in enumerate(indices):
|
for i, orig_idx in enumerate(indices):
|
||||||
inst = raw_instructions[orig_idx]
|
inst = raw_instructions[orig_idx]
|
||||||
|
next_shuffled = pos_map[orig_idx + 1] if orig_idx + 1 < len(raw_instructions) else 0
|
||||||
if orig_idx + 1 < len(raw_instructions):
|
|
||||||
next_orig = orig_idx + 1
|
|
||||||
next_shuffled = pos_map[next_orig]
|
|
||||||
else:
|
|
||||||
next_shuffled = 0
|
|
||||||
|
|
||||||
packed = [
|
packed = [
|
||||||
inst[0] & 0xFF, (inst[0] >> 8) & 0xFF,
|
inst[0] & 0xFF, (inst[0] >> 8) & 0xFF,
|
||||||
@ -121,11 +94,8 @@ class LuauVMObfuscator:
|
|||||||
inst_str = "".join(chr(i) for inst in final_insts 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()
|
inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode()
|
||||||
|
|
||||||
# Bytecode Checksum for Integrity
|
|
||||||
checksum = hashlib.md5(inst_str.encode('latin-1')).hexdigest()
|
|
||||||
|
|
||||||
encrypted_consts = []
|
encrypted_consts = []
|
||||||
salt = random.randint(10000, 99999)
|
salt = random.randint(1000, 9999)
|
||||||
for i, c in enumerate(bytecode['constants']):
|
for i, c in enumerate(bytecode['constants']):
|
||||||
if c['type'] == 'string':
|
if c['type'] == 'string':
|
||||||
key = (i * 149 + salt) % 256
|
key = (i * 149 + salt) % 256
|
||||||
@ -137,8 +107,8 @@ class LuauVMObfuscator:
|
|||||||
consts_json = json.dumps(encrypted_consts)
|
consts_json = json.dumps(encrypted_consts)
|
||||||
start_idx = pos_map[0]
|
start_idx = pos_map[0]
|
||||||
|
|
||||||
# Obfuscated Variable Names
|
V_LUA_ENV = self.get_var("lua_env")
|
||||||
V_ENV = self.get_var("env")
|
V_BIT = self.get_var("bit32")
|
||||||
V_B64 = self.get_var("b64")
|
V_B64 = self.get_var("b64")
|
||||||
V_D = self.get_var("decode")
|
V_D = self.get_var("decode")
|
||||||
V_INST = self.get_var("inst_raw")
|
V_INST = self.get_var("inst_raw")
|
||||||
@ -154,137 +124,85 @@ class LuauVMObfuscator:
|
|||||||
V_A = self.get_var("a")
|
V_A = self.get_var("a")
|
||||||
V_B = self.get_var("b")
|
V_B = self.get_var("b")
|
||||||
V_C = self.get_var("c")
|
V_C = self.get_var("c")
|
||||||
V_BIT = self.get_var("bit32")
|
V_KEY = self.get_var("key")
|
||||||
V_GS = self.get_var("getservice")
|
V_RES = self.get_var("res")
|
||||||
V_TRAP = self.get_var("trap")
|
V_LAST = self.get_var("last")
|
||||||
V_CHECK = self.get_var("check")
|
|
||||||
V_IS_HOOKED = self.get_var("is_hooked")
|
|
||||||
V_PROTECT = self.get_var("protect")
|
|
||||||
V_METH = self.get_var("meth")
|
|
||||||
V_LUA_ENV = self.get_var("lua_env")
|
|
||||||
|
|
||||||
vm_lua = f"""local {V_LUA_ENV} = getfenv()
|
vm_lua = f"""local {V_LUA_ENV}=getfenv()
|
||||||
local {V_BIT} = bit32
|
local {V_BIT}=bit32
|
||||||
local {V_GS} = game.GetService
|
local {V_B64}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
local {V_B64} = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
local {V_D}=function(data)
|
||||||
local {V_D} = function(data)
|
data=string.gsub(data,'[^'..{V_B64}..'=]')
|
||||||
if not ({self.opaque_predicate()}) then return "" end
|
return(data:gsub('.',function(x)
|
||||||
data = string.gsub(data, '[^'..{V_B64}..'=]', '')
|
if(x=='=')then return''end
|
||||||
return (data:gsub('.', function(x)
|
|
||||||
if (x == '=') then return '' end
|
|
||||||
local r,f='',({V_B64}:find(x)-1)
|
local r,f='',({V_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
|
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and'1'or'0')end
|
||||||
return r;
|
return r;
|
||||||
end):gsub('%d%d%d%d%d%d%d%d', function(x)
|
end):gsub('%d%d%d%d%d%d%d%d',function(x)
|
||||||
local r=0
|
local r=0
|
||||||
for i=1,8 do r=r+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
for i=1,8 do r=r+(x:sub(i,i)=='1'and 2^(8-i)or 0)end
|
||||||
return string.char(r)
|
return string.char(r)
|
||||||
end))
|
end))
|
||||||
end
|
end
|
||||||
|
local {V_INST}={V_D}('{inst_b64}')
|
||||||
local function {V_IS_HOOKED}(f)
|
local {V_CONSTS}=game:GetService("HttpService"):JSONDecode('{consts_json}')
|
||||||
if type(f) ~= "function" then return false end
|
local {V_SALT}={self.to_expr(salt)}
|
||||||
local s = tostring(f)
|
|
||||||
if string.find(s, "hook") or string.find(s, "proxy") then return true end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function {V_TRAP}()
|
|
||||||
local _ = function() while true do end end
|
|
||||||
task.spawn(_)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function {V_CHECK}()
|
|
||||||
local d = {{ "getgenv", "getrenv", "getreg", "debug", "Drawing", "hookfunction", "setreadonly", "make_writeable" }}
|
|
||||||
for _, v in ipairs(d) do
|
|
||||||
if {V_LUA_ENV}[v] then
|
|
||||||
if {V_IS_HOOKED}({V_LUA_ENV}[v]) then return false end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not {V_LUA_ENV}["game"] or not {V_LUA_ENV}["task"] then return false end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local {V_INST} = {V_D}('{inst_b64}')
|
|
||||||
local {V_CONSTS} = {V_GS}(game, "HttpService"):JSONDecode('{consts_json}')
|
|
||||||
local {V_SALT} = {self.to_expr(salt)}
|
|
||||||
|
|
||||||
local function {V_EXEC}()
|
local function {V_EXEC}()
|
||||||
if not {V_CHECK}() then {V_TRAP}() return end
|
local {V_REGS}={{}}
|
||||||
|
local {V_CURR}={self.to_expr(start_idx)}
|
||||||
local {V_REGS} = {{}}
|
local {V_RUN}=true
|
||||||
local {V_CURR} = {self.to_expr(start_idx)}
|
|
||||||
local {V_RUN} = true
|
|
||||||
|
|
||||||
local {V_PROTECT} = {{}}
|
|
||||||
setmetatable({V_PROTECT}, {{
|
|
||||||
__index = {V_LUA_ENV},
|
|
||||||
__newindex = function(_, k, v) {V_LUA_ENV}[k] = v end,
|
|
||||||
__metatable = "Locked"
|
|
||||||
}})
|
|
||||||
|
|
||||||
local function {V_GETC}(idx)
|
local function {V_GETC}(idx)
|
||||||
local c = {V_CONSTS}[idx + 1]
|
local c={V_CONSTS}[idx+1]
|
||||||
if not c then return nil end
|
if not c then return nil end
|
||||||
if c.t == {self.to_expr(1)} then
|
if c.t=={self.to_expr(1)} then
|
||||||
local raw = {V_D}(c.v)
|
local raw={V_D}(c.v)
|
||||||
local key = (idx * {self.to_expr(149)} + {V_SALT}) % {self.to_expr(256)}
|
local {V_KEY}=(idx*{self.to_expr(149)}+{V_SALT})%256
|
||||||
local res = ""
|
local {V_RES}={{}}
|
||||||
local last = key % 256
|
local {V_LAST}={V_KEY}%256
|
||||||
for i=1, #raw do
|
for i=1,#raw do
|
||||||
local k = (key + i + last - 1) % 256
|
local k=({V_KEY}+i+{V_LAST}-1)%256
|
||||||
local b = string.byte(raw, i)
|
local b=string.byte(raw,i)
|
||||||
local char_code = {V_BIT}.bxor(b, k)
|
local char_code={V_BIT}.bxor(b,k)
|
||||||
res = res .. string.char(char_code)
|
{V_RES}[i]=string.char(char_code)
|
||||||
last = char_code
|
{V_LAST}=char_code
|
||||||
end
|
end
|
||||||
return res
|
return table.concat({V_RES})
|
||||||
end
|
end
|
||||||
return c.v
|
return c.v
|
||||||
end
|
end
|
||||||
|
|
||||||
while {V_RUN} do
|
while {V_RUN} do
|
||||||
if not ({self.opaque_predicate()}) then break end
|
local {V_PTR}={V_CURR}*7+1
|
||||||
local {V_PTR} = {V_CURR} * {self.to_expr(7)} + 1
|
local op_l=string.byte({V_INST},{V_PTR})
|
||||||
if {V_PTR} > #{V_INST} then break end
|
local op_h=string.byte({V_INST},{V_PTR}+1)
|
||||||
|
local {V_A}=string.byte({V_INST},{V_PTR}+2)
|
||||||
local op_l = string.byte({V_INST}, {V_PTR})
|
local {V_B}=string.byte({V_INST},{V_PTR}+3)
|
||||||
local op_h = string.byte({V_INST}, {V_PTR} + 1)
|
local {V_C}=string.byte({V_INST},{V_PTR}+4)
|
||||||
local {V_A} = string.byte({V_INST}, {V_PTR} + 2)
|
local next_l=string.byte({V_INST},{V_PTR}+5)
|
||||||
local {V_B} = string.byte({V_INST}, {V_PTR} + 3)
|
local next_h=string.byte({V_INST},{V_PTR}+6)
|
||||||
local {V_C} = string.byte({V_INST}, {V_PTR} + 4)
|
{V_CURR}=next_l+(next_h*256)
|
||||||
local next_l = string.byte({V_INST}, {V_PTR} + 5)
|
local op_raw=op_l+(op_h*256)
|
||||||
local next_h = string.byte({V_INST}, {V_PTR} + 6)
|
local {V_OP}=({V_BIT}.bxor(op_raw,{self.to_expr(self.k2)})-{self.to_expr(self.k1)})-{self.to_expr(self.k3)}
|
||||||
|
if {V_OP}=={self.opcodes.index('MOVE')} then
|
||||||
{V_CURR} = next_l + (next_h * {self.to_expr(256)})
|
{V_REGS}[{V_A}]={V_REGS}[{V_B}]
|
||||||
|
elseif {V_OP}=={self.opcodes.index('LOADK')} then
|
||||||
local op_raw = op_l + (op_h * 256)
|
{V_REGS}[{V_A}]={V_GETC}({V_B})
|
||||||
local {V_OP} = ({V_BIT}.bxor(op_raw, {self.to_expr(self.k2)}) - {self.to_expr(self.k1)}) - {self.to_expr(self.k3)}
|
elseif {V_OP}=={self.opcodes.index('GETGLOBAL')} then
|
||||||
|
{V_REGS}[{V_A}]={V_LUA_ENV}[{V_GETC}({V_B})]
|
||||||
if {V_OP} == {self.to_expr(self.opcodes.index('MOVE'))} then
|
elseif {V_OP}=={self.opcodes.index('SETGLOBAL')} then
|
||||||
{V_REGS}[{V_A}] = {V_REGS}[{V_B}]
|
{V_LUA_ENV}[{V_GETC}({V_B})]={V_REGS}[{V_A}]
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('LOADK'))} then
|
elseif {V_OP}=={self.opcodes.index('CALL')} then
|
||||||
{V_REGS}[{V_A}] = {V_GETC}({V_B})
|
local f={V_REGS}[{V_A}]
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('GETGLOBAL'))} then
|
local args={{}}
|
||||||
{V_REGS}[{V_A}] = {V_PROTECT}[{V_GETC}({V_B})]
|
if {V_B}>1 then for i=1,{V_B}-1 do args[i]={V_REGS}[{V_A}+i] end end
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('SETGLOBAL'))} then
|
local res={{f(unpack(args))}}
|
||||||
{V_PROTECT}[{V_GETC}({V_B})] = {V_REGS}[{V_A}]
|
if {V_C}>1 then for i=1,{V_C}-1 do {V_REGS}[{V_A}+i-1]=res[i] end end
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('CALL'))} then
|
elseif {V_OP}=={self.opcodes.index('RETURN')} then
|
||||||
local f = {V_REGS}[{V_A}]
|
{V_RUN}=false
|
||||||
local args = {{}}
|
|
||||||
if {V_B} > 1 then for i=1, {V_B}-1 do args[i] = {V_REGS}[{V_A}+i] end end
|
|
||||||
local res = {{f(unpack(args))}}
|
|
||||||
if {V_C} > 1 then for i=1, {V_C}-1 do {V_REGS}[{V_A}+i-1] = res[i] end end
|
|
||||||
elseif {V_OP} == {self.to_expr(self.opcodes.index('RETURN'))} then
|
|
||||||
{V_RUN} = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not ({self.opaque_predicate()}) then {V_RUN} = false end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task.spawn({V_EXEC})"""
|
task.spawn({V_EXEC})"""
|
||||||
return vm_lua
|
return self.minify(vm_lua)
|
||||||
|
|
||||||
def compile_to_bytecode(self, ast):
|
def compile_to_bytecode(self, ast):
|
||||||
constants = []
|
constants = []
|
||||||
@ -294,14 +212,11 @@ task.spawn({V_EXEC})"""
|
|||||||
|
|
||||||
def add_const(val):
|
def add_const(val):
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
s_q = chr(39)
|
s_q = chr(39); d_q = chr(34)
|
||||||
d_q = chr(34)
|
|
||||||
if (val.startswith(s_q) and val.endswith(s_q)) or (val.startswith(d_q) and val.endswith(d_q)):
|
if (val.startswith(s_q) and val.endswith(s_q)) or (val.startswith(d_q) and val.endswith(d_q)):
|
||||||
val = val[1:-1]
|
val = val[1:-1]
|
||||||
|
|
||||||
for i, c in enumerate(constants):
|
for i, c in enumerate(constants):
|
||||||
if c['value'] == val: return i
|
if c['value'] == val: return i
|
||||||
|
|
||||||
t = 'string' if isinstance(val, str) else 'number'
|
t = 'string' if isinstance(val, str) else 'number'
|
||||||
constants.append({'type': t, 'value': val})
|
constants.append({'type': t, 'value': val})
|
||||||
return len(constants) - 1
|
return len(constants) - 1
|
||||||
@ -326,16 +241,12 @@ task.spawn({V_EXEC})"""
|
|||||||
instructions.append([self.op_to_id["MOVE"], func_reg, locals_map[node['name']], 0])
|
instructions.append([self.op_to_id["MOVE"], func_reg, locals_map[node['name']], 0])
|
||||||
else:
|
else:
|
||||||
instructions.append([self.op_to_id["GETGLOBAL"], func_reg, add_const(node['name']), 0])
|
instructions.append([self.op_to_id["GETGLOBAL"], func_reg, add_const(node['name']), 0])
|
||||||
|
|
||||||
for i, arg_expr in enumerate(node['args']):
|
for i, arg_expr in enumerate(node['args']):
|
||||||
load_expr_to_reg(arg_expr, func_reg + 1 + i)
|
load_expr_to_reg(arg_expr, func_reg + 1 + i)
|
||||||
|
|
||||||
instructions.append([self.op_to_id["CALL"], func_reg, len(node['args']) + 1, 1])
|
instructions.append([self.op_to_id["CALL"], func_reg, len(node['args']) + 1, 1])
|
||||||
|
|
||||||
elif node['type'] == 'assign':
|
elif node['type'] == 'assign':
|
||||||
val_reg = next_reg
|
val_reg = next_reg
|
||||||
load_expr_to_reg(node['value'], val_reg)
|
load_expr_to_reg(node['value'], val_reg)
|
||||||
|
|
||||||
if node.get('local'):
|
if node.get('local'):
|
||||||
locals_map[node['name']] = val_reg
|
locals_map[node['name']] = val_reg
|
||||||
next_reg += 1
|
next_reg += 1
|
||||||
@ -356,7 +267,7 @@ task.spawn({V_EXEC})"""
|
|||||||
bytecode = self.compile_to_bytecode(ast)
|
bytecode = self.compile_to_bytecode(ast)
|
||||||
return self.generate_vm_source(bytecode)
|
return self.generate_vm_source(bytecode)
|
||||||
except Exception:
|
except Exception:
|
||||||
return ""
|
return "-- Obfuscation Error"
|
||||||
|
|
||||||
def obfuscate(code):
|
def obfuscate(code):
|
||||||
return LuauVMObfuscator().obfuscate(code)
|
return LuauVMObfuscator().obfuscate(code)
|
||||||
Loading…
x
Reference in New Issue
Block a user