@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
JavaScript
/**
* 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;