obfulox
Version:
Advanced JavaScript code encryptor with multi-layer encryption and obfuscation
301 lines (267 loc) • 9.17 kB
JavaScript
const jsConfuser = require('js-confuser');
const crypto = require('crypto');
const fs = require('fs');
class SingleLineEncryptor {
constructor() {
this.masterKey = crypto.randomBytes(32).toString('hex');
}
generateEncryptionId() {
const timestamp = Date.now();
const random = crypto.randomBytes(8).toString('hex');
return `enc_${timestamp}_${random}`;
}
base64Encode(str) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let result = '';
let i = 0;
while (i < str.length) {
const a = str.charCodeAt(i++);
const b = str.charCodeAt(i++);
const c = str.charCodeAt(i++);
const bitmap = (a << 16) | (b << 8) | c;
result += chars.charAt((bitmap >> 18) & 63);
result += chars.charAt((bitmap >> 12) & 63);
result += chars.charAt((bitmap >> 6) & 63);
result += chars.charAt(bitmap & 63);
}
const padding = str.length % 3;
if (padding === 1) result = result.slice(0, -2) + '==';
else if (padding === 2) result = result.slice(0, -1) + '=';
return result;
}
base64Decode(str) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let result = '';
let bits = 0;
let bitCount = 0;
str = str.replace(/=+$/, '');
for (let i = 0; i < str.length; i++) {
const char = str.charAt(i);
const value = chars.indexOf(char);
if (value === -1) continue;
bits = (bits << 6) | value;
bitCount += 6;
if (bitCount >= 8) {
bitCount -= 8;
result += String.fromCharCode((bits >> bitCount) & 0xFF);
}
}
return result;
}
xorEncrypt(text, key) {
let result = '';
for (let i = 0; i < text.length; i++) {
const keyChar = key.charCodeAt(i % key.length);
const textChar = text.charCodeAt(i);
result += String.fromCharCode(textChar ^ keyChar);
}
return result;
}
xorDecrypt(text, key) {
return this.xorEncrypt(text, key);
}
async encrypt(code) {
const encryptionId = this.generateEncryptionId();
const xorKey = crypto.randomBytes(16).toString('hex');
console.log('🔐 Starting SINGLE LINE encryption...');
const encodedId = this.base64Encode(encryptionId);
console.log('✓ Layer 1: ID Base64 Encoding');
const encryptedCode = this.xorEncrypt(code, xorKey);
console.log('✓ Layer 2: XOR Encryption');
const finalEncoded = this.base64Encode(encryptedCode);
console.log('✓ Layer 3: Code Base64 Encoding');
const singleLineCode = this.buildSingleLineExecutor(finalEncoded, encodedId, xorKey);
console.log('✓ Layer 4: Single Line Generation');
console.log('✓ Layer 5: Final Obfuscation');
try {
const obfuscated = await jsConfuser.obfuscate(singleLineCode, {
target: 'node',
preset: 'high',
compact: true,
controlFlowFlattening: true,
deadCode: true,
stringConcealing: true,
minify: true
});
console.log('SINGLE LINE encryption completed!');
return {
encryptedCode: obfuscated,
encryptionId: encryptionId,
xorKey: xorKey
};
} catch (error) {
console.log('Using raw single line code');
return {
encryptedCode: singleLineCode,
encryptionId: encryptionId,
xorKey: xorKey
};
}
}
buildSingleLineExecutor(encodedData, encodedId, xorKey) {
return `"use strict";(function(){const _0='${encodedId}';const _1='${encodedData}';const _2='${this.base64Encode(xorKey)}';function _3(b){const c='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';let r='';let i=0;b=b.replace(/=+$/,'');while(i<b.length){const a=c.indexOf(b.charAt(i++));const d=c.indexOf(b.charAt(i++));const e=c.indexOf(b.charAt(i++));const f=c.indexOf(b.charAt(i++));const g=(a<<18)|(d<<12)|(e<<6)|f;if(a<0||d<0)break;r+=String.fromCharCode((g>>16)&255);if(e>=0)r+=String.fromCharCode((g>>8)&255);if(f>=0)r+=String.fromCharCode(g&255);}return r;}function _4(t,k){let r='';for(let i=0;i<t.length;i++){r+=String.fromCharCode(t.charCodeAt(i)^k.charCodeAt(i%k.length));}return r;}try{const _5=_3(_0);const _6=_3(_2);const _7=_3(_1);const _8=_4(_7,_6);new Function(_8)();}catch(e){}})();`;
}
extractEncryptionId(encryptedCode) {
try {
const patterns = [
/const _0='([A-Za-z0-9+/=]+)'/,
/_0='([A-Za-z0-9+/=]+)'/,
/'_0','([A-Za-z0-9+/=]+)'/,
/"_0","([A-Za-z0-9+/=]+)"/
];
for (const pattern of patterns) {
const match = encryptedCode.match(pattern);
if (match && match[1]) {
const encodedId = match[1];
const encryptionId = this.base64Decode(encodedId);
if (encryptionId.startsWith('enc_') && encryptionId.length > 20) {
return {
success: true,
encryptionId: encryptionId,
encodedId: encodedId,
foundWith: pattern.toString()
};
}
}
}
return {
success: false,
error: 'No valid encryption ID found'
};
} catch (error) {
return {
success: false,
error: `Extraction failed: ${error.message}`
};
}
}
async decrypt(encryptedCode, encryptionId, xorKey = null) {
try {
console.log('🔓 Starting decryption process...');
let extractedKey = xorKey;
if (!extractedKey) {
console.log('🔍 Extracting XOR key from encrypted code...');
const keyResult = this.extractXorKey(encryptedCode);
if (!keyResult.success) {
throw new Error('XOR key not found and not provided');
}
extractedKey = keyResult.xorKey;
}
console.log('📥 Extracting encoded data...');
const dataResult = this.extractEncodedData(encryptedCode);
if (!dataResult.success) {
throw new Error('Encoded data not found');
}
console.log('🔓 Decoding base64 data...');
const decodedData = this.base64Decode(dataResult.encodedData);
const decodedKey = this.base64Decode(extractedKey);
console.log('🔐 Applying XOR decryption...');
const decryptedCode = this.xorDecrypt(decodedData, decodedKey);
console.log('Decryption completed!');
return {
success: true,
decryptedCode: decryptedCode,
encryptionId: encryptionId,
originalLength: decryptedCode.length
};
} catch (error) {
console.log('Decryption failed:', error.message);
return {
success: false,
error: error.message
};
}
}
extractXorKey(encryptedCode) {
try {
const patterns = [
/const _2='([A-Za-z0-9+/=]+)'/,
/_2='([A-Za-z0-9+/=]+)'/,
/'_2','([A-Za-z0-9+/=]+)'/,
/"_2","([A-Za-z0-9+/=]+)"/
];
for (const pattern of patterns) {
const match = encryptedCode.match(pattern);
if (match && match[1]) {
return {
success: true,
xorKey: match[1]
};
}
}
return {
success: false,
error: 'XOR key not found'
};
} catch (error) {
return {
success: false,
error: `Key extraction failed: ${error.message}`
};
}
}
extractEncodedData(encryptedCode) {
try {
const patterns = [
/const _1='([A-Za-z0-9+/=]+)'/,
/_1='([A-Za-z0-9+/=]+)'/,
/'_1','([A-Za-z0-9+/=]+)'/,
/"_1","([A-Za-z0-9+/=]+)"/
];
for (const pattern of patterns) {
const match = encryptedCode.match(pattern);
if (match && match[1]) {
return {
success: true,
encodedData: match[1]
};
}
}
return {
success: false,
error: 'Encoded data not found'
};
} catch (error) {
return {
success: false,
error: `Data extraction failed: ${error.message}`
};
}
}
verifyEncryption(encryptedCode) {
const idResult = this.extractEncryptionId(encryptedCode);
const keyResult = this.extractXorKey(encryptedCode);
const dataResult = this.extractEncodedData(encryptedCode);
return {
isEncrypted: idResult.success && keyResult.success && dataResult.success,
encryptionId: idResult.success ? idResult.encryptionId : null,
hasXorKey: keyResult.success,
hasEncodedData: dataResult.success,
details: {
id: idResult,
key: keyResult,
data: dataResult
}
};
}
saveToFile(encryptedCode, filename) {
fs.writeFileSync(filename, encryptedCode);
console.log(`💾 Saved to ${filename}`);
}
loadFromFile(filename) {
try {
const code = fs.readFileSync(filename, 'utf8');
const verification = this.verifyEncryption(code);
return {
code: code,
...verification
};
} catch (error) {
return {
error: `Failed to load file: ${error.message}`,
isEncrypted: false
};
}
}
}
module.exports = SingleLineEncryptor;