From 6eb4a6e0d6a931c89e17673a4054782e4546d373 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 25 Jan 2026 15:34:00 +0000 Subject: [PATCH] Newest 16:33 --- backend/src/services/obfuscator.js | 262 +++++++++++++++++++++++------ 1 file changed, 211 insertions(+), 51 deletions(-) diff --git a/backend/src/services/obfuscator.js b/backend/src/services/obfuscator.js index f145c9b..1c7e6d5 100644 --- a/backend/src/services/obfuscator.js +++ b/backend/src/services/obfuscator.js @@ -13,7 +13,7 @@ class ObfuscatorService { let i = 0; while (i < code.length) { let c = code[i]; - if (/\\s/.test(c)) { i++; continue; } + if (/\s/.test(c)) { i++; continue; } if (c === '-' && code[i + 1] === '-') { i += 2; if (code[i] === '[' && code[i + 1] === '[') { @@ -28,15 +28,15 @@ class ObfuscatorService { if (c === '"' || c === "'") { const q = c; let s = ""; i++; while (i < code.length && code[i] !== q) { - if (code[i] === '\\') { s += code[i] + (code[i + 1] || ""); i += 2; } + if (code[i] === '\\') { s += code[i] + (code[i + 1] || ""); i += 2; } else { s += code[i]; i++; } } tokens.push({ type: 'string', value: s }); i++; continue; } - if (/\\d/.test(c)) { + if (/\d/.test(c)) { let n = ""; - while (i < code.length && /[\\d\.xX]/.test(code[i])) { n += code[i]; i++; } + while (i < code.length && /[\d\.\xX]/.test(code[i])) { n += code[i]; i++; } tokens.push({ type: 'number', value: parseFloat(n) }); continue; } @@ -51,6 +51,32 @@ class ObfuscatorService { return tokens; } + static numberToExpression(n) { + if (typeof n !== 'number') return n; + const ops = ['+', '-', '*']; + let current = Math.floor(Math.random() * 200) - 100; + let expr = `(${current})`; + + for (let i = 0; i < 4; i++) { + const op = ops[Math.floor(Math.random() * ops.length)]; + const val = Math.floor(Math.random() * 100) + 1; + if (op === '+') { current += val; expr = `(${expr} + ${val})`; } + else if (op === '-') { current -= val; expr = `(${expr} - ${val})`; } + else if (op === '*') { + if (Math.abs(current * val) < 1000000) { + current *= val; expr = `(${expr} * ${val})`; + } + } + } + + const diff = n - current; + if (diff >= 0) expr = `(${expr} + ${diff})`; + else expr = `(${expr} - ${Math.abs(diff)})`; + + const noise = Math.floor(Math.random() * 255); + return `bit32.bxor(bit32.bxor(${expr}, ${noise}), ${noise})`; + } + static compile(tokens) { const constants = []; const getC = (v) => { @@ -58,65 +84,119 @@ class ObfuscatorService { if (idx === -1) { idx = constants.length; constants.push({ value: v, type: typeof v }); } return idx; }; - const ops = {LOADK:0, GETG:1, SETG:2, CALL:3, RET:4, GETT:5, GETS:6}; + const ops = { + LOADK: 0, GETG: 1, SETG: 2, CALL: 3, RET: 4, GETT: 5, GETS: 6, + NEWTABLE: 7, SETTABLE: 8, GETLOCAL: 9, SETLOCAL: 10 + }; const bc = []; let ti = 0; - const pExpr = (reg) => { - let t = tokens[ti]; if (!t) return; + const locals = {}; + let nextLocal = 0; + + const peek = () => tokens[ti]; + const consume = () => tokens[ti++]; + + const parseExpr = (reg) => { + let t = peek(); if (!t) return; if (t.type === 'number' || t.type === 'string') { - bc.push(ops.LOADK, reg, getC(t.value)); ti++; + bc.push(ops.LOADK, reg, getC(consume().value)); } else if (t.type === 'identifier') { - const name = t.value; ti++; - if (tokens[ti]?.value === '(') { ti--; pCall(reg); } - else if (tokens[ti]?.value === ':') { - ti++; const m = tokens[ti].value; ti++; - bc.push(ops.GETG, reg, getC(name)); - bc.push(ops.GETS, reg, reg, getC(m)); - pArgs(reg, true); - } else if (tokens[ti]?.value === '.') { - bc.push(ops.GETG, reg, getC(name)); - while (tokens[ti]?.value === '.') { - ti++; const k = tokens[ti].value; ti++; - bc.push(ops.GETT, reg, reg, getC(k)); + let name = consume().value; + if (peek()?.value === '(') { + ti--; parseCall(reg); + } else { + emitGet(reg, name); + while (peek()?.value === '.' || peek()?.value === ':') { + let op = consume().value; + let key = consume().value; + if (op === ':') { + bc.push(ops.GETS, reg, reg, getC(key)); + parseArgs(reg, true); + } else { + bc.push(ops.GETT, reg, reg, getC(key)); + if (peek()?.value === '(') parseArgs(reg); + } } - } else { bc.push(ops.GETG, reg, getC(name)); } + } + } else if (t.value === '{') { + parseTable(reg); } }; - const pArgs = (reg, isM) => { - if (tokens[ti]?.value !== '(') return; - ti++; let ac = isM ? 1 : 0; - while (ti < tokens.length && tokens[ti].value !== ')') { - if (tokens[ti].value === ',') { ti++; continue; } - ac++; pExpr(reg + ac); + + const parseTable = (reg) => { + bc.push(ops.NEWTABLE, reg); consume(); // { + while (ti < tokens.length && peek().value !== '}') { + if (peek().value === ',') { consume(); continue; } + let t = peek(); + if (tokens[ti+1]?.value === '=') { + let key = consume().value; consume(); // = + parseExpr(reg + 1); + bc.push(ops.SETTABLE, reg, getC(key), reg + 1); + } else { + parseExpr(reg + 1); + } + if (peek()?.value === ',') consume(); + } + if (peek()?.value === '}') consume(); + }; + + const emitGet = (reg, name) => { + if (locals[name] !== undefined) bc.push(ops.GETLOCAL, reg, locals[name]); + else bc.push(ops.GETG, reg, getC(name)); + }; + + const parseArgs = (reg, isM) => { + if (peek()?.value !== '(') return; + consume(); let ac = isM ? 1 : 0; + while (ti < tokens.length && peek().value !== ')') { + if (peek().value === ',') { consume(); continue; } + ac++; parseExpr(reg + ac); } bc.push(ops.CALL, reg, ac + 1, 1); - if (tokens[ti]?.value === ')') ti++; + if (peek()?.value === ')') consume(); }; - const pCall = (reg) => { - const fn = tokens[ti].value; ti++; - bc.push(ops.GETG, reg, getC(fn)); pArgs(reg); + + const parseCall = (reg) => { + let fn = consume().value; + emitGet(reg, fn); + parseArgs(reg); }; + while (ti < tokens.length) { - let t = tokens[ti]; - if (t.type === 'identifier' && tokens[ti+1]?.value === '=') { - const vn = t.value; ti += 2; pExpr(0); - bc.push(ops.SETG, 0, getC(vn)); continue; + let t = peek(); + if (t.value === 'local') { + consume(); + let name = consume().value; + if (peek()?.value === '=') { + consume(); parseExpr(nextLocal); + locals[name] = nextLocal++; + } else { + locals[name] = nextLocal++; + } + } else if (t.type === 'identifier' && tokens[ti+1]?.value === '=') { + let vn = consume().value; consume(); + parseExpr(nextLocal); + if (locals[vn] !== undefined) bc.push(ops.SETLOCAL, locals[vn], nextLocal); + else bc.push(ops.SETG, nextLocal, getC(vn)); + } else if (t.type === 'identifier' && (tokens[ti+1]?.value === '(' || tokens[ti+1]?.value === ':')) { + parseExpr(nextLocal); + } else { + ti++; } - if (t.type === 'identifier' && (tokens[ti+1]?.value === '(' || tokens[ti+1]?.value === ':')) { - pExpr(0); continue; - } - ti++; } bc.push(ops.RET, 0, 1); return { bc, constants, ops }; } static generateVM(bc, constants, ops, seed) { - const r = () => "_" + Math.random().toString(36).substring(7); - const nL = r(), nC = r(), nR = r(), nPC = r(), nK = r(), nD = r(), nDS = r(); + const r = () => "_" + Math.random().toString(36).substring(7) + "_" + Math.floor(Math.random() * 10000); + const nL = r(), nC = r(), nR = r(), nPC = r(), nK = r(), nD = r(), nDS = r(), nLOC = r(); + const nENV = r(), nTIME = r(), nX = r(), nY = r(); + const encC = constants.map(c => { if (c.type === 'string') { - const e = Buffer.from(c.value).map(b => b ^ (seed & 0xFF)).toString('base64'); + const key = seed & 0xFF; + const e = Buffer.from(c.value).map(b => b ^ key).toString('base64'); return `{t=1,v="${e}"}`; } if (c.type === 'number') { @@ -125,7 +205,33 @@ class ObfuscatorService { } return `{t=0}`; }).join(','); + + const xorKey = seed % 255; + const antiTamper = ` + local ${nENV} = getfenv and getfenv() or _G + local ${nTIME} = tick() + local function check() + if ${nENV}.debug and ${nENV}.debug.getinfo then + local i = ${nENV}.debug.getinfo(check) + if i.what ~= "Lua" then while true do end end + end + local s = tick() + for i=1,1000 do end + if tick() - s > 1 then while true do end end + end + check() + task.spawn(function() + while true do + if tick() - ${nTIME} > 4 then + local ${nX} = nil; ${nX}.crash() + end + ${nTIME} = tick() + task.wait(3) + end + end) + `; + const d = []; d[ops.LOADK] = `function() ${nR}[${nL}[${nPC}]] = ${nD}(${nL}[${nPC}+1]); ${nPC}=${nPC}+2 end`; d[ops.GETG] = `function() ${nR}[${nL}[${nPC}]] = _G[${nD}(${nL}[${nPC}+1])]; ${nPC}=${nPC}+2 end`; @@ -134,21 +240,49 @@ class ObfuscatorService { d[ops.GETS] = `function() local r,t,k = ${nL}[${nPC}],${nL}[${nPC}+1],${nL}[${nPC}+2]; ${nPC}=${nPC}+3; ${nR}[r+1] = ${nR}[t]; ${nR}[r] = ${nR}[t][${nD}(k)] end`; d[ops.CALL] = `function() local r,na,nr = ${nL}[${nPC}],${nL}[${nPC}+1],${nL}[${nPC}+2]; ${nPC}=${nPC}+3; local a={}; for i=1,na-1 do a[i]=${nR}[r+i] end; ${nR}[r]=${nR}[r](table.unpack(a)) end`; d[ops.RET] = `function() return "EXIT" end`; + d[ops.NEWTABLE] = `function() ${nR}[${nL}[${nPC}]] = {}; ${nPC}=${nPC}+1 end`; + d[ops.SETTABLE] = `function() local t,k,v = ${nL}[${nPC}],${nL}[${nPC}+1],${nL}[${nPC}+2]; ${nPC}=${nPC}+3; ${nR}[t][${nD}(k)] = ${nR}[v] end`; + d[ops.GETLOCAL] = `function() ${nR}[${nL}[${nPC}]] = ${nLOC}[${nL}[${nPC}+1]+1]; ${nPC}=${nPC}+2 end`; + d[ops.SETLOCAL] = `function() ${nLOC}[${nL}[${nPC}]+1] = ${nR}[${nL}[${nPC}+1]]; ${nPC}=${nPC}+2 end`; - const xorKey = seed % 255; + const argCounts = { + [ops.LOADK]: 2, [ops.GETG]: 2, [ops.SETG]: 2, [ops.GETT]: 3, + [ops.GETS]: 3, [ops.CALL]: 3, [ops.RET]: 2, [ops.NEWTABLE]: 1, + [ops.SETTABLE]: 3, [ops.GETLOCAL]: 2, [ops.SETLOCAL]: 2 + }; - return `local function VM(...) - local ${nL} = {${bc.join(',')}} + const shuffled = Object.keys(ops).sort(() => Math.random() - 0.5); + const opMap = {}; + shuffled.forEach((k, i) => opMap[ops[k]] = i); + + const finalBC = []; + for (let i = 0; i < bc.length; ) { + const op = bc[i]; + finalBC.push(opMap[op]); + i++; + const count = argCounts[op] || 0; + for (let j = 0; j < count; j++) { + finalBC.push(bc[i] || 0); + i++; + } + } + + const dispatchFunctions = shuffled.map(k => d[ops[k]] || "function() end").join(','); + + const vmCode = `local function VM(...) + ${antiTamper} + local ${nL} = {${finalBC.join(',')}} local ${nC} = {${encC}} + local ${nLOC} = {} local ${nR} = setmetatable({}, { __index = function(t, k) return rawget(t, bit32.bxor(k, ${xorKey})) end, __newindex = function(t, k, v) rawset(t, bit32.bxor(k, ${xorKey}), v) end }) - local ${nPC} = 1; local ${nK} = ${seed} + local ${nPC} = ${this.numberToExpression(1)}; local ${nK} = ${this.numberToExpression(seed)} local function ${nD}(i) local c = ${nC}[i+1]; if not c then return end if c.t == 1 then - local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; local s = c.v:gsub("[^"..b.."=]", ""); local res = "" for j=1,#s,4 do local v = 0 @@ -158,13 +292,39 @@ class ObfuscatorService { return res elseif c.t == 2 then return bit32.bxor(c.v, bit32.band(${nK}, 65535)) - c.o end end - local ${nDS} = {${d.join(',')}} - while ${nL}[${nPC}] do - local op = ${nL}[${nPC}]; ${nPC} = ${nPC} + 1 + local ${nDS} = {${dispatchFunctions}} + while true do + local op = ${nL}[${nPC}]; if not op then break end + ${nPC} = ${nPC} + 1 local f = ${nDS}[op+1] if f then if f() == "EXIT" then break end else break end end - end; VM(...)` + end; VM(...)`; + + const wrapLayers = (code, layers) => { + let current = code; + for (let i = 0; i < layers; i++) { + const layerSeed = crypto.randomBytes(4).readUInt32BE(0); + const encoded = Buffer.from(current).map(b => b ^ (layerSeed & 0xFF)).toString('base64'); + current = `local _v = "${encoded}" + local _s = ${this.numberToExpression(layerSeed)} + local function _d(s) + local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + local res = "" + for j=1,#s,4 do + local v = 0 + for k=0,3 do local char = s:sub(j+k,j+k); v = v*64 + (char=="=" and 0 or (b:find(char,1,true)-1)) end + for k=2,0,-1 do if j+3-k<=#s and s:sub(j+3-k,j+3-k)~="=" then res = res..string.char(bit32.bxor(bit32.extract(v,k*8,8),bit32.band(_s,255))) end end + end + return res + end + local _f = loadstring(_d(_v)) + if _f then _f() end`; + } + return current; + }; + + return wrapLayers(vmCode, 2); } } module.exports = ObfuscatorService; \ No newline at end of file