diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index fc7c4f1..64053a7 100644 Binary files a/core/__pycache__/obfuscator.cpython-311.pyc and b/core/__pycache__/obfuscator.cpython-311.pyc differ diff --git a/core/obfuscator.py b/core/obfuscator.py index 717d755..54e5aa5 100644 --- a/core/obfuscator.py +++ b/core/obfuscator.py @@ -18,9 +18,8 @@ class LuauVMObfuscator: 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) % 65536 for name in self.opcodes} + self.op_to_id = {name: (self.opcodes.index(name) + self.k1) ^ self.k2 for name in self.opcodes} self.var_map = {} self.used_vars = set() @@ -40,7 +39,7 @@ class LuauVMObfuscator: if depth > 2 or (depth > 0 and random.random() < 0.2): return str(n) - r = random.randint(1, 1000000) + r = random.randint(1, 100000) choice = random.choice(['add', 'sub', 'xor']) if choice == 'add': @@ -82,7 +81,7 @@ class LuauVMObfuscator: packed = [ inst[0] & 0xFF, (inst[0] >> 8) & 0xFF, - inst[1], inst[2], inst[3], + inst[1] & 0xFF, inst[2] & 0xFF, inst[3] & 0xFF, next_shuffled & 0xFF, (next_shuffled >> 8) & 0xFF ] final_insts[i] = packed @@ -103,48 +102,52 @@ class LuauVMObfuscator: consts_json = json.dumps(encrypted_consts) start_idx = pos_map[0] - V_LUA_ENV = self.get_var("lua_env") - V_BIT = self.get_var("bit32") - V_B64 = self.get_var("b64_alpha") - V_D = self.get_var("decode") - V_INST = self.get_var("inst_raw") + V_ENV = self.get_var("env") + V_BIT = self.get_var("bit") + V_B64 = self.get_var("b64") + V_DEC = self.get_var("dec") + V_INST = self.get_var("inst") V_CONSTS = self.get_var("consts") V_SALT = self.get_var("salt") - V_EXEC = self.get_var("execute") - V_REGS = self.get_var("registers") - V_CURR = self.get_var("current") - V_RUN = self.get_var("running") - V_GETC = self.get_var("get_const") + V_EXEC = self.get_var("exec") + V_REGS = self.get_var("regs") + V_CURR = self.get_var("curr") + V_RUN = self.get_var("run") + V_GETC = self.get_var("getc") V_PTR = self.get_var("ptr") V_OP = self.get_var("op") V_A = self.get_var("a") V_B = self.get_var("b") V_C = self.get_var("c") + V_UNP = self.get_var("unp") + V_SPW = self.get_var("spw") + V_RAW = self.get_var("raw") 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") + V_LST = self.get_var("lst") - 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 + vm_lua = f"""local {V_BIT}=bit32 +local {V_ENV}=setmetatable({{}},{{__index=getfenv()}}) +local {V_UNP}=unpack or table.unpack +local {V_SPW}=task and task.spawn or spawn local {V_B64}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -local {V_D}=function(data) +local {V_DEC}=function(data) data=data:gsub('[^'..{V_B64}..'=]','') - return(data:gsub('.',function(x) - if(x=='=')then return''end - 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 - return r; - end):gsub('%d%d%d%d%d%d%d%d',function(x) - local r=0 - for i=1,8 do r=r+(x:sub(i,i)=='1'and 2^(8-i)or 0)end - return string.char(r) - end)) + local res,bits={{}},'' + for i=1,#data do + local c=data:sub(i,i) + if c=='=' then break end + local f={V_B64}:find(c)-1 + for j=5,0,-1 do bits=bits..({V_BIT}.extract(f,j,1)) end + end + for i=1,#bits-7,8 do + local b=0 + for j=1,8 do b=b+(bits:sub(i+j-1,i+j-1)=='1' and 2^(8-j) or 0) end + res[#res+1]=string.char(b) + end + return table.concat(res) end -local {V_INST}={V_D}('{inst_b64}') +local {V_INST}={V_DEC}('{inst_b64}') local {V_CONSTS}=game:GetService("HttpService"):JSONDecode([=[{consts_json}]=]) local {V_SALT}={self.to_expr(salt, V_BIT)} local function {V_EXEC}() @@ -152,19 +155,20 @@ local function {V_EXEC}() local {V_CURR}={self.to_expr(start_idx, V_BIT)} local {V_RUN}=true local function {V_GETC}(idx) + if not idx then return nil end local c={V_CONSTS}[idx+1] if not c then return nil end if c.t=={self.to_expr(1, V_BIT)} then - local raw={V_D}(c.v) + local {V_RAW}={V_DEC}(c.v) 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 - local k=({V_KEY}+i+{V_LAST}-1)%256 - local b=string.byte(raw,i) - local char_code={V_BIT}.bxor(b,k) - {V_RES}[i]=string.char(char_code) - {V_LAST}=char_code + local {V_LST}={V_KEY}%256 + for i=1,#{V_RAW} do + local k=({V_KEY}+i+{V_LST}-1)%256 + local b=string.byte({V_RAW},i) + local char={V_BIT}.bxor(b,k) + {V_RES}[i]=string.char(char) + {V_LST}=char end return table.concat({V_RES}) end @@ -172,36 +176,40 @@ local function {V_EXEC}() end while {V_RUN} do local {V_PTR}={V_CURR}*7+1 - local op_l=string.byte({V_INST},{V_PTR}) - local op_h=string.byte({V_INST},{V_PTR}+1) - local {V_A}=string.byte({V_INST},{V_PTR}+2) - local {V_B}=string.byte({V_INST},{V_PTR}+3) - local {V_C}=string.byte({V_INST},{V_PTR}+4) - local next_l=string.byte({V_INST},{V_PTR}+5) - 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, V_BIT)})-{self.to_expr(self.k1, V_BIT)})-{self.to_expr(self.k3, V_BIT)} + local op_l=string.byte({V_INST},{V_PTR}) or 0 + local op_h=string.byte({V_INST},{V_PTR}+1) or 0 + local {V_A}=string.byte({V_INST},{V_PTR}+2) or 0 + local {V_B}=string.byte({V_INST},{V_PTR}+3) or 0 + local {V_C}=string.byte({V_INST},{V_PTR}+4) or 0 + local n_l=string.byte({V_INST},{V_PTR}+5) or 0 + local n_h=string.byte({V_INST},{V_PTR}+6) or 0 + {V_CURR}=n_l+({V_BIT}.lshift(n_h,8)) + local op_raw=op_l+({V_BIT}.lshift(op_h,8)) + local {V_OP}={V_BIT}.bxor(op_raw,{self.to_expr(self.k2, V_BIT)})-{self.to_expr(self.k1, 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 {V_REGS}[{V_A}]={V_GETC}({V_B}) elseif {V_OP}=={self.opcodes.index('GETGLOBAL')} then - {V_REGS}[{V_A}]={V_LUA_ENV}[{V_GETC}({V_B})] + local n={V_GETC}({V_B}) + if n then {V_REGS}[{V_A}]={V_ENV}[n] end elseif {V_OP}=={self.opcodes.index('SETGLOBAL')} then - {V_LUA_ENV}[{V_GETC}({V_B})]={V_REGS}[{V_A}] + local n={V_GETC}({V_B}) + if n then {V_ENV}[n]={V_REGS}[{V_A}] end elseif {V_OP}=={self.opcodes.index('CALL')} then 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({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 + if f then + 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({V_UNP}(args))}} + if {V_C}>1 then for i=1,{V_C}-1 do {V_REGS}[{V_A}+i-1]=res[i] end end + end elseif {V_OP}=={self.opcodes.index('RETURN')} then {V_RUN}=false end end end -{V_SPAWN}({V_EXEC})""" +{V_SPW}({V_EXEC})""" return self.minify(vm_lua) def compile_to_bytecode(self, ast):