UNPKG

obfulox

Version:

Advanced JavaScript code encryptor with multi-layer encryption and obfuscation

301 lines (267 loc) 9.17 kB
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;