UNPKG

@xbibzlibrary/obfuscator

Version:

Advanced polymorphic obfuscation library for JavaScript, JSON and CSS with multi-layer encryption and browser compatibility

451 lines (382 loc) 14.1 kB
/** * Multi-Layer Obfuscation System * Applies multiple obfuscation techniques in layers * @version 1.0.0 * @author Xbibz Official */ class ObfuscationLayers { constructor() { this.layers = [ 'stringEncryption', 'controlFlow', 'variableTransformation', 'functionObfuscation', 'dataEncoding', 'antiDebug', 'environmentDetection', 'selfModifyingCode', 'polymorphicGeneration', 'metamorphicMutation' ]; this.layerConfig = new Map(); this.initializeLayers(); } initializeLayers() { this.layers.forEach(layer => { this.layerConfig.set(layer, { enabled: true, intensity: 1.0, iterations: 1, customOptions: {} }); }); } setLayerConfig(layer, config) { if (this.layerConfig.has(layer)) { this.layerConfig.set(layer, { ...this.layerConfig.get(layer), ...config }); } } applyStringEncryptionLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Multiple string encryption methods const methods = [ this.base64EncodeStrings, this.hexEncodeStrings, this.rot13EncodeStrings, this.xorEncodeStrings, this.multiLayerEncodeStrings ]; methods.forEach((method, index) => { if (Math.random() < intensity) { transformed = method.call(this, transformed, intensity); } }); return transformed; } base64EncodeStrings(code) { return code.replace(/"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/g, (match) => { if (match.length < 3) return match; const content = match.slice(1, -1); const encoded = btoa(unescape(encodeURIComponent(content))); return `atob("${encoded}")`; }); } hexEncodeStrings(code) { return code.replace(/"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/g, (match) => { if (match.length < 3) return match; const content = match.slice(1, -1); const hex = Array.from(content).map(c => '0x' + c.charCodeAt(0).toString(16) ).join(','); return `String.fromCharCode(${hex})`; }); } rot13EncodeStrings(code) { return code.replace(/"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/g, (match) => { if (match.length < 3) return match; const content = match.slice(1, -1); const rot13 = content.replace(/[a-zA-Z]/g, c => String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26) ); return `"${rot13}".replace(/[a-zA-Z]/g,c=>String.fromCharCode((c<='Z'?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26))`; }); } xorEncodeStrings(code) { return code.replace(/"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/g, (match) => { if (match.length < 3) return match; const content = match.slice(1, -1); const key = Math.floor(Math.random() * 256); const encoded = Array.from(content).map(c => c.charCodeAt(0) ^ key ).join(','); return `String.fromCharCode(...[${encoded}].map(c=>c^${key}))`; }); } multiLayerEncodeStrings(code) { return code.replace(/"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/g, (match) => { if (match.length < 3) return match; const content = match.slice(1, -1); // Multiple encoding layers const base64 = btoa(unescape(encodeURIComponent(content))); const hex = Array.from(base64).map(c => '0x' + c.charCodeAt(0).toString(16) ).join(','); const key = Math.floor(Math.random() * 256); const xor = Array.from(base64).map(c => c.charCodeAt(0) ^ key ).join(','); return `(function(){var k=${key},h=[${hex}],x=[${xor}],b=String.fromCharCode(...x.map(c=>c^k)),d=atob(b);return d;})()`; }); } applyControlFlowLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Control flow obfuscation techniques const techniques = [ this.flattenControlFlow, this.insertJunkCode, this.obfuscateLoops, this.transformConditions, this.addRedundantOperations ]; techniques.forEach(technique => { if (Math.random() < intensity) { transformed = technique.call(this, transformed, intensity); } }); return transformed; } flattenControlFlow(code) { // Convert linear code to state machine const lines = code.split(';').filter(line => line.trim()); if (lines.length < 3) return code; const states = []; const stateCount = Math.min(10, lines.length); for (let i = 0; i < stateCount; i++) { states.push(i); } let flattened = ` (function(){ var _s=0,_r; var _st=[${states.join(',')}]; while(_s!==-1){ switch(_st[_s]){ `; lines.forEach((line, index) => { const state = states[index % stateCount]; const nextState = states[(index + 1) % stateCount]; flattened += ` case ${state}: ${line}; _s = ${index === lines.length - 1 ? -1 : nextState}; break; `; }); flattened += ` } } return _r; })() `; return flattened; } insertJunkCode(code) { const junkPatterns = [ 'if(Math.random()<0){var _=Date.now();}', 'try{throw new Error(""}catch(e){}', 'do{break;}while(Math.random()<0);', 'switch(0){case 1:break;}', 'var _t=setTimeout(function(){},1);clearTimeout(_t);' ]; const lines = code.split('\n'); const newLines = []; lines.forEach(line => { newLines.push(line); if (line.trim() && Math.random() < 0.3) { const junk = junkPatterns[Math.floor(Math.random() * junkPatterns.length)]; newLines.push(junk); } }); return newLines.join('\n'); } applyVariableTransformationLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Variable transformation techniques const techniques = [ this.mangleVariableNames, this.splitVariableDeclarations, this.mergeVariables, this.obfuscateVariableAccess, this.addProxyVariables ]; techniques.forEach(technique => { if (Math.random() < intensity) { transformed = technique.call(this, transformed, intensity); } }); return transformed; } mangleVariableNames(code) { const variables = this.extractAllVariables(code); const mangledMap = new Map(); const usedNames = new Set(); variables.forEach(variable => { if (variable.length > 2 && !variable.startsWith('_')) { let mangled; do { mangled = this.generateMangledName(); } while (usedNames.has(mangled)); mangledMap.set(variable, mangled); usedNames.add(mangled); } }); let mangledCode = code; mangledMap.forEach((mangled, original) => { const regex = new RegExp(`\\b${original}\\b`, 'g'); mangledCode = mangledCode.replace(regex, mangled); }); return mangledCode; } extractAllVariables(code) { const patterns = [ /\b(var|let|const)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g, /function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g, /function\s*\(([^)]*)\)/g, /\.([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/g ]; const variables = new Set(); patterns.forEach(pattern => { let match; while ((match = pattern.exec(code)) !== null) { if (pattern === patterns[2]) { // Function parameters match[1].split(',').forEach(param => { const trimmed = param.trim(); if (trimmed) variables.add(trimmed); }); } else { variables.add(match[2] || match[1]); } } }); return Array.from(variables); } generateMangledName() { const prefixes = ['_', '$', '__', '_0', '_1', '___']; const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let name = prefixes[Math.floor(Math.random() * prefixes.length)]; const length = 4 + Math.floor(Math.random() * 8); for (let i = 0; i < length; i++) { name += chars[Math.floor(Math.random() * chars.length)]; } return name; } applyFunctionObfuscationLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Function obfuscation techniques const techniques = [ this.wrapFunctions, this.convertToIIFE, this.obfuscateFunctionCalls, this.splitFunctions, this.addFunctionProxies ]; techniques.forEach(technique => { if (Math.random() < intensity) { transformed = technique.call(this, transformed, intensity); } }); return transformed; } wrapFunctions(code) { return code.replace(/function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(([^)]*)\)\s*{/g, (match, name, params) => { const wrapperName = this.generateMangledName(); return ` var ${wrapperName} = (function(){ function ${name}(${params}) { var _args = arguments; `.trim(); } ).replace(/}\s*$/g, ` return ${name}.apply(this, _args); } return ${name}; })(); `); } applyDataEncodingLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Data encoding techniques const techniques = [ this.encodeNumbers, this.obfuscateArrays, this.transformObjects, this.encodeBooleans, this.obfuscateNullUndefined ]; techniques.forEach(technique => { if (Math.random() < intensity) { transformed = technique.call(this, transformed, intensity); } }); return transformed; } encodeNumbers(code) { return code.replace(/\b(\d+)\b/g, (match, num) => { const methods = [ () => `0x${Number(num).toString(16)}`, () => `0b${Number(num).toString(2)}`, () => `0o${Number(num).toString(8)}`, () => `parseInt("${num}",10)`, () => `Math.pow(${Math.floor(Math.sqrt(num))},2)+${num - Math.pow(Math.floor(Math.sqrt(num)),2)}`, () => `${num}*1`, () => `${num}+0`, () => `~~${num}` ]; const method = methods[Math.floor(Math.random() * methods.length)]; return method(); }); } applyAntiDebugLayer(code, config) { const intensity = config.intensity || 1.0; let transformed = code; // Anti-debug techniques const antiDebugCode = ` (function(){ var _d = false; var _s = Date.now(); function _c(){if(Date.now()-_s>1000){_d=true;}} setInterval(_c,500); if(_d){while(true){}} // Debugger detection var _db = false; function _dd(){debugger;_db=true;} try{_dd();}catch(e){} if(_db){for(;;){}} })(); `; if (Math.random() < intensity) { transformed = antiDebugCode + '\n' + transformed; } return transformed; } applyAllLayers(code, customConfig = {}) { let obfuscated = code; this.layers.forEach(layer => { const config = { ...this.layerConfig.get(layer), ...customConfig[layer] }; if (config.enabled) { try { const layerMethod = this[`apply${layer.charAt(0).toUpperCase() + layer.slice(1)}Layer`]; if (typeof layerMethod === 'function') { for (let i = 0; i < config.iterations; i++) { obfuscated = layerMethod.call(this, obfuscated, config); } } } catch (error) { console.warn(`Layer ${layer} failed:`, error); } } }); return obfuscated; } generateLayerReport() { const report = {}; this.layers.forEach(layer => { report[layer] = this.layerConfig.get(layer); }); return report; } } module.exports = ObfuscationLayers;