15:27
This commit is contained in:
parent
7699f45ec4
commit
f329f2c77a
Binary file not shown.
@ -16,19 +16,19 @@ class LuauVMObfuscator:
|
||||
"FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG"
|
||||
]
|
||||
|
||||
self.k1 = random.randint(100, 500)
|
||||
self.k2 = random.randint(100, 500)
|
||||
self.k3 = random.randint(100, 500)
|
||||
self.k1 = random.randint(1000, 5000)
|
||||
self.k2 = random.randint(1000, 5000)
|
||||
self.k3 = random.randint(1000, 5000)
|
||||
|
||||
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) % 65536 for name in self.opcodes}
|
||||
|
||||
self.var_map = {}
|
||||
self.used_vars = set()
|
||||
|
||||
def get_var(self, hint="var"):
|
||||
if hint in self.var_map: return self.var_map[hint]
|
||||
chars = "lI"
|
||||
length = random.randint(8, 16) # Shorter vars for single-line efficiency
|
||||
chars = "lI1"
|
||||
length = random.randint(32, 48)
|
||||
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||
while new_var in self.used_vars:
|
||||
new_var = "_" + "".join(random.choice(chars) for _ in range(length))
|
||||
@ -36,19 +36,19 @@ class LuauVMObfuscator:
|
||||
self.var_map[hint] = new_var
|
||||
return new_var
|
||||
|
||||
def to_expr(self, n, depth=0):
|
||||
if depth > 1 or (depth > 0 and random.random() < 0.5):
|
||||
def to_expr(self, n, bit32_var="bit32", depth=0):
|
||||
if depth > 2 or (depth > 0 and random.random() < 0.2):
|
||||
return str(n)
|
||||
|
||||
r = random.randint(1, 50)
|
||||
r = random.randint(1, 1000000)
|
||||
choice = random.choice(['add', 'sub', 'xor'])
|
||||
|
||||
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, bit32_var, depth + 1)} + {self.to_expr(r, bit32_var, depth + 1)})"
|
||||
elif choice == 'sub':
|
||||
return f"({self.to_expr(n + r, depth + 1)} - {self.to_expr(r, depth + 1)})"
|
||||
return f"({self.to_expr(n + r, bit32_var, depth + 1)} - {self.to_expr(r, bit32_var, depth + 1)})"
|
||||
elif choice == 'xor':
|
||||
return f"bit32.bxor({self.to_expr(n ^ r, depth + 1)}, {self.to_expr(r, depth + 1)})"
|
||||
return f"{bit32_var}.bxor({self.to_expr(n ^ r, bit32_var, depth + 1)}, {self.to_expr(r, bit32_var, depth + 1)})"
|
||||
|
||||
return str(n)
|
||||
|
||||
@ -62,18 +62,14 @@ class LuauVMObfuscator:
|
||||
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):
|
||||
raw_instructions = bytecode['instructions']
|
||||
shuffled = []
|
||||
indices = list(range(len(raw_instructions)))
|
||||
random.shuffle(indices)
|
||||
|
||||
@ -95,7 +91,7 @@ class LuauVMObfuscator:
|
||||
inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode()
|
||||
|
||||
encrypted_consts = []
|
||||
salt = random.randint(1000, 9999)
|
||||
salt = random.randint(100000, 999999)
|
||||
for i, c in enumerate(bytecode['constants']):
|
||||
if c['type'] == 'string':
|
||||
key = (i * 149 + salt) % 256
|
||||
@ -109,7 +105,7 @@ class LuauVMObfuscator:
|
||||
|
||||
V_LUA_ENV = self.get_var("lua_env")
|
||||
V_BIT = self.get_var("bit32")
|
||||
V_B64 = self.get_var("b64")
|
||||
V_B64 = self.get_var("b64_alpha")
|
||||
V_D = self.get_var("decode")
|
||||
V_INST = self.get_var("inst_raw")
|
||||
V_CONSTS = self.get_var("consts")
|
||||
@ -127,12 +123,16 @@ class LuauVMObfuscator:
|
||||
V_KEY = self.get_var("key")
|
||||
V_RES = self.get_var("res")
|
||||
V_LAST = self.get_var("last")
|
||||
V_UNPACK = self.get_var("unpack")
|
||||
V_SPAWN = self.get_var("spawn")
|
||||
|
||||
vm_lua = f"""local {V_LUA_ENV}=getfenv()
|
||||
local {V_BIT}=bit32
|
||||
local {V_UNPACK}=unpack or table.unpack
|
||||
local {V_SPAWN}=task and task.spawn or spawn
|
||||
local {V_B64}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
local {V_D}=function(data)
|
||||
data=string.gsub(data,'[^'..{V_B64}..'=]')
|
||||
data=data:gsub('[^'..{V_B64}..'=]','')
|
||||
return(data:gsub('.',function(x)
|
||||
if(x=='=')then return''end
|
||||
local r,f='',({V_B64}:find(x)-1)
|
||||
@ -145,18 +145,18 @@ local {V_D}=function(data)
|
||||
end))
|
||||
end
|
||||
local {V_INST}={V_D}('{inst_b64}')
|
||||
local {V_CONSTS}=game:GetService("HttpService"):JSONDecode('{consts_json}')
|
||||
local {V_SALT}={self.to_expr(salt)}
|
||||
local {V_CONSTS}=game:GetService("HttpService"):JSONDecode([=[{consts_json}]=])
|
||||
local {V_SALT}={self.to_expr(salt, V_BIT)}
|
||||
local function {V_EXEC}()
|
||||
local {V_REGS}={{}}
|
||||
local {V_CURR}={self.to_expr(start_idx)}
|
||||
local {V_CURR}={self.to_expr(start_idx, V_BIT)}
|
||||
local {V_RUN}=true
|
||||
local function {V_GETC}(idx)
|
||||
local c={V_CONSTS}[idx+1]
|
||||
if not c then return nil end
|
||||
if c.t=={self.to_expr(1)} then
|
||||
if c.t=={self.to_expr(1, V_BIT)} then
|
||||
local raw={V_D}(c.v)
|
||||
local {V_KEY}=(idx*{self.to_expr(149)}+{V_SALT})%256
|
||||
local {V_KEY}=(idx*{self.to_expr(149, V_BIT)}+{V_SALT})%256
|
||||
local {V_RES}={{}}
|
||||
local {V_LAST}={V_KEY}%256
|
||||
for i=1,#raw do
|
||||
@ -181,7 +181,7 @@ local function {V_EXEC}()
|
||||
local next_h=string.byte({V_INST},{V_PTR}+6)
|
||||
{V_CURR}=next_l+(next_h*256)
|
||||
local op_raw=op_l+(op_h*256)
|
||||
local {V_OP}=({V_BIT}.bxor(op_raw,{self.to_expr(self.k2)})-{self.to_expr(self.k1)})-{self.to_expr(self.k3)}
|
||||
local {V_OP}=({V_BIT}.bxor(op_raw,{self.to_expr(self.k2, V_BIT)})-{self.to_expr(self.k1, V_BIT)})-{self.to_expr(self.k3, V_BIT)}
|
||||
if {V_OP}=={self.opcodes.index('MOVE')} then
|
||||
{V_REGS}[{V_A}]={V_REGS}[{V_B}]
|
||||
elseif {V_OP}=={self.opcodes.index('LOADK')} then
|
||||
@ -194,14 +194,14 @@ local function {V_EXEC}()
|
||||
local f={V_REGS}[{V_A}]
|
||||
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))}}
|
||||
local res={{f({V_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.opcodes.index('RETURN')} then
|
||||
{V_RUN}=false
|
||||
end
|
||||
end
|
||||
end
|
||||
task.spawn({V_EXEC})"""
|
||||
{V_SPAWN}({V_EXEC})"""
|
||||
return self.minify(vm_lua)
|
||||
|
||||
def compile_to_bytecode(self, ast):
|
||||
@ -267,7 +267,8 @@ task.spawn({V_EXEC})"""
|
||||
bytecode = self.compile_to_bytecode(ast)
|
||||
return self.generate_vm_source(bytecode)
|
||||
except Exception:
|
||||
return "-- Obfuscation Error"
|
||||
import traceback
|
||||
return f"-- Obfuscation Error: {traceback.format_exc()}"
|
||||
|
||||
def obfuscate(code):
|
||||
return LuauVMObfuscator().obfuscate(code)
|
||||
Loading…
x
Reference in New Issue
Block a user