-
Option name:
"customStringEncodings" -
Option values:
true/false/0-1
Input / Output
This example showcases howCustom String Encodings transforms the code. Try it out by changing the input code and see changes apply in real-time.
Input.js
// Input.js
// Base64 Encoding Demo
var str = 'Hello, World!';
console.log(str); // "Hello, World!"
// Output.js
function szYWALe(szYWALe) {
return atob(szYWALe);
}
function H07Txxp(H07Txxp) {
return szYWALe(LTQD2W[H07Txxp]);
}
var LTQD2W = [
'QTNJUjdUUTQ2Z0s=',
'VFBRYjJLUGluZkFmUXdRaEc4dw==',
'V2ZHaUdkY3NQSHU2VFlCaVlp',
'QXh1S3paUDBJOTllRkVuMDRNTTc4cm9ueW5wN25YcUNhSEtTVG5iRlN0V0FB',
'R0NaWXVCMmFWTUt1bA==',
'R2ZuUzFHMzNtV2hTVUNLdUFuRzkwdXR5OUs=',
'b1BGcEhUS2N5QWltcVNHbGh0alJ5RlhqdEhw',
'R2lzME4zTDZLVUl3ekRhcEhaNGRJemZGZkYzaDE0N3B4WlJKM1htalhoZg==',
'aDVQd2k5d2Z4eHNs',
'SmhzcE4yNFRXY2hXVk4xODhUWk05b0N4bg==',
'NjlMWWpyNkZ0d0UzbFI=',
'RU92TUtxaDdCNDJ6UmxqQW40ZFFHc0E1Y3pENldIM2h0cUs1WEpL',
'UDh5ckd2Wk1RVUhucjBSTHlCaFppblFwN2x1',
'U0swcUJITGxTelZhVTl6OFNx',
'UnZFRzBHZXJyQ0xNVVVxdm1seTU3b0s=',
'UmI4Q1kyU2dUTkpxU2RTbWhkeg==',
'ZklEV3BQbmRtbk5oWXRQazRUQXhSQkJheTk=',
'U05Vc21vZFE4Y2xSRGk=',
'c09qaVk2RTlXUGFoR2hhRDNUOHU2emVvbXhHVmJCTUlzWXpCS0w2dQ==',
'Tmo5RWUwTGUwbVR2UFVHYTFmWjlsY3lNcQ==',
'd0hZQ1FwcUo2M2t2NnJraklTNEUxRTk3VlBwTHQ5SGRKeFhkdHNzT3dXS3pOb3E=',
'TktFMmI=',
'OXhjdjZZUUs2TlduVlNWTnZicEFqeEphenZs',
'V3RCOUdlQmpSVmZjNGdxNkI3TGFWV0dWcWtodUNYRUdFNU02Vng=',
'MHdCNkNtMllFWmFjdEl1a3RtTG1QOHlsc1luaFlvNDN6N29MM2NKa2xIdXV0QQ==',
'c3VpZ3hRU0tNbmxkUGhiTHJoM3hIMXI3eHZFOHRRQmk5U1NmUWxsZ1ZnbzR0',
'MlFTWnFETEJzdWx2aU8=',
'WTF1VzI=',
'aWV5azVzdWpwRjBEU21mZ1ByVWlUWDNYMXNuck9MbXlySg==',
'SVdGVDE1RmE=',
'UGQ1VTFXZkRQVDg4dmRoN3VwUlhVME45REVOYXltYTJIUmNEWQ==',
'bG5DbXZlMmJSSXZ5UUlCcg==',
'UHJaeGpJQUZta0Y4dkVuRVR2VDJhZU9qZVNnUE82cWd3MTV3czU1czlXTUlV',
'dGNnT3QzMEl2Y3JKYWlEcQ==',
'ZTlYR3MxUnhBQW5I',
'bzNlNTFIMzRqV2RDaEM=',
'bEcycUIyNlF4UHE1eHJKbk9HRmdHcllEVG5xenc=',
'YzBJaWNxaUZUMjVQUjA=',
'RnRaQ3I0MmFmY09TaEdZaHA=',
'dzZsU2pITHZLVkE1VWhPWVFadnRpaTBQdVFwRnk1bmI0aWE2U3hOS0o3SkY=',
'eUxnZEZ4Y2M4M1hVU0xzVkoyRFRFS2o0Tzlnd29iRW1pVzNXemRrSkRaTw==',
'TzBkN0Y5bm1pSjZQMFR0NkpKU1pvR0dWMzU=',
'MlI3QnZQOGdnM3hwQlE3Y2cwS044NlRqZ3FUdGdXUTcxeDNS',
'ZTdvenA=',
'SU5XVlJxaDdBd3c3WGlDMmtHUkUyVTRkTTRtQ01BdWJhQWNDUHNBbXRuQnNxQTJBSA==',
'NlQ4V0FhUXBqMU9CdWxRMXpxbzZlSWNJQkZESDRvakRIazg=',
'eDZQYlBzaE41clRLeHRnUU5sMGRua25meHk2WHJNTDF0ME1MWmQ1VUU2RVhKNEFO',
'UTJHVEk0bERsaUR4R3YzYWpIYkJMclowWWtiN0ltcw==',
'd3ZPaGo0eGNNM3NuaDJBc2NVQTJmZ0hsRmQ=',
'd3FXUll3ZTVzRTlYUzEydlQ3',
'dmR3eDhRaTl0ZVkyY3U5Tkha',
'WnZoMDlMYUFsOGhNNDVxZDFFS3RzeQ==',
'c21QeUNBaHJuWjFGQWFHckMwcTRXdDNpQzBLYzdzYThGOHQ=',
'T2p1QWJjSld0UA==',
'VGxEamVFa00=',
'c2hwdDNkaWtYRVk2bFZKTUxGMm1kUXk0',
'UEIybERpUEtmd1pEdWc=',
'TzdRUjR2aEx0OVpwZUtSd3o=',
'QlllUFc5RncwYzhLSTNqNmZzbkE1V1ZUMmVlMlpNU1RNVUZCMVNRRmw0',
'NXZxS3pVS00zSVdUSXRxQVJOdVBOekV3YmdsdUdYeTRYdEV2RWZUNFFkZERrSDBicQ==',
'VFlxaGRnRjc3WEM3Vk5jRA==',
'a2lVckIwekdSU0RxeGQ4Vnkxc0dXcnZ0UGxPZEVGWA==',
'UVVFbWg1QXhNOWtU',
'WXpvYmE4cTNKMVJ6OElpZmY0U0g4SVgzbw==',
'TmlISldKWXBzQzA1RldzWkR2RUxoelU0Y1BReTZUWVI2ZGU=',
'dHVaRE91ZTNCVU1qQ0FPQnB2aHJVZ3JrWkZ3c2FQbWhRV1o5MmlEVDFjc2o=',
'c0ZQd0RYak5WMGZNZTRYeVc2U251UDJBZ0VJNGdZT1hPVlpTQml4a3k=',
'WGs3RDVpUTh5T1R1WHhrTzBx',
'dUNUTmpaM0FCUkQ1UVk2YWJPMDlsRndKVm4=',
'Q3k2UDNDblNFUDJkdDJIb1Y=',
'bzE0eFo0RFdiYmdIRA==',
'NVlJVDJwdUJNRXhaN3dvb0x5QXM=',
'RnZLN2lwZ3dsWHlFZTVWRlVhR2dYdDh0ck5FOTI=',
'OGE1ajNBSmZ3cVdCRjU3ODBuTklJZVBUY0h6Rnh0a2t1',
'NnFCTlVjNllvN3pxckVzSFRDcGpsdlJHRWpGOA==',
'M3pzYjQ=',
'dzNndzFU',
'MTJsZFZQVW5uUmVHTFlrWkhOS2NEYjVV',
'ems3VjlNS3RRWk02VWxKb0c4VA==',
'S3dLMjhiU3plZWhZ',
'Yk92M1JtbTN4RFVKYmNjUWw3TjNxUGk5TWVlMHBQeklPdElpcnlFbzg3QWp3Q2k=',
'VThnR2xKak5XelVOUERH',
'YjduNnNJUWsxd2tiaTBOMzlhUEI5MHptV2lyOXRENnc2YkJTWg==',
'VW1iemZnakJTUWNGT0QyVWh1cEp2Slo4b0w=',
'aDRmYUh4QUJZVzNxeUpTNmNBajlmMjVkdw==',
'UEVrdmtr',
'SGVsbG8sIFdvcmxkIQ==',
'bG9n',
];
function eYeBV9() {
var szYWALe = [
function () {
return globalThis;
},
function () {
return global;
},
function () {
return window;
},
function () {
return new Function('return this')();
},
],
H07Txxp,
LTQD2W = [];
try {
H07Txxp = Object;
LTQD2W.push(''.__proto__.constructor.name);
} catch (e) {}
XxWINV: for (var eYeBV9 = 0; eYeBV9 < szYWALe.length; eYeBV9++)
try {
H07Txxp = szYWALe[eYeBV9]();
for (var ZCGOxn = 0; ZCGOxn < LTQD2W.length; ZCGOxn++)
if (typeof H07Txxp[LTQD2W[ZCGOxn]] === 'undefined') continue XxWINV;
return H07Txxp;
} catch (e) {}
return H07Txxp || this;
}
var ZCGOxn = eYeBV9() || {},
_euU7X = ZCGOxn.TextDecoder,
gdwMU4 = ZCGOxn.Uint8Array,
xYmAxNB = ZCGOxn.Buffer,
RIAq_0O = ZCGOxn.String || String,
D_5Dj_ = ZCGOxn.Array || Array,
iCW0Br2 = (function () {
var szYWALe = new D_5Dj_(128),
H07Txxp = RIAq_0O.fromCodePoint || RIAq_0O.fromCharCode,
LTQD2W = [];
return function (eYeBV9) {
var ZCGOxn,
_euU7X,
gdwMU4 = eYeBV9.length;
LTQD2W.length = 0;
for (var xYmAxNB = 0; xYmAxNB < gdwMU4; ) {
_euU7X = eYeBV9[xYmAxNB++];
_euU7X <= 0x7f
? (ZCGOxn = _euU7X)
: _euU7X <= 0xdf
? (ZCGOxn = ((_euU7X & 0x1f) << 6) | (eYeBV9[xYmAxNB++] & 0x3f))
: _euU7X <= 0xef
? (ZCGOxn =
((_euU7X & 0x0f) << 12) |
((eYeBV9[xYmAxNB++] & 0x3f) << 6) |
(eYeBV9[xYmAxNB++] & 0x3f))
: RIAq_0O.fromCodePoint
? (ZCGOxn =
((_euU7X & 0x07) << 18) |
((eYeBV9[xYmAxNB++] & 0x3f) << 12) |
((eYeBV9[xYmAxNB++] & 0x3f) << 6) |
(eYeBV9[xYmAxNB++] & 0x3f))
: ((ZCGOxn = 63), (xYmAxNB += 3));
LTQD2W.push(szYWALe[ZCGOxn] || (szYWALe[ZCGOxn] = H07Txxp(ZCGOxn)));
}
return LTQD2W.join('');
};
})();
function DYCwdaw(szYWALe) {
return typeof _euU7X !== 'undefined' && _euU7X
? new _euU7X().decode(new gdwMU4(szYWALe))
: typeof xYmAxNB !== 'undefined' && xYmAxNB
? xYmAxNB.from(szYWALe).toString('utf-8')
: iCW0Br2(szYWALe);
}
var f1Pdn4u = H07Txxp(86);
console[H07Txxp(87)](f1Pdn4u);
Custom String Encoding API
The Custom String Encoding API allows you to define your own string encoding/decoding functions. These encodings will be randomly inserted throughout the code.Options.js
module.exports = {
target: "node",
// Should be enabled
stringConcealing: true,
// Simple Base64 Encoding
customStringEncodings: [
{
// This template decoder function will be inserted into the code
code: `
function {fnName}(str){
return atob(str);
}`,
// Tells the obfuscator how to encode the string
encode: (str) => btoa(str),
},
],
};
The properties of the type
Custom String Encoding are:
| Property | Type | Description |
|---|---|---|
code | string | Template decoder code that must contain ''. |
encode | Function | Encoding algorithm. |
decode? | Function | Decoding algorithm. (Optional) |
identity? | string | Distinguishes multiple encodings. (Optional) |
-
The template
codeshould contain the string{fnName}, which the obfuscator can interpolate with the function name. -
The functions
encodeanddecodehave the type:(strValue: string) => string. -
The function
decodeis optional. If provided, the obfuscator will validate each string to ensure it can be decoded. If the string cannot be decoded, the obfuscator will ignore the string.
Advanced Randomized Encoding
The following example implements a custom Base64 encoding that uses a shuffled charset to encode and decode strings.- This encoding algorithm is instantiated multiple times, each with a different shuffled charset. This makes it difficult to reverse-engineer the encoding algorithm.
Options.js
const { Template } = require("js-confuser");
const { stringLiteral } = require("@babel/types");
function shuffle(array) {
// Fisher-Yates shuffle
let currentIndex = array.length,
randomIndex;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
];
}
return array;
}
function createCustomStringEncoding() {
function encode(input, charset) {
const inputBuffer = new TextEncoder().encode(input);
let output = "";
for (let i = 0; i < inputBuffer.length; i += 3) {
const chunk = [inputBuffer[i], inputBuffer[i + 1], inputBuffer[i + 2]];
const binary = (chunk[0] << 16) | (chunk[1] << 8) | (chunk[2] || 0);
output += charset[(binary >> 18) & 0x3f];
output += charset[(binary >> 12) & 0x3f];
output +=
typeof chunk[1] !== "undefined" ? charset[(binary >> 6) & 0x3f] : "=";
output += typeof chunk[2] !== "undefined" ? charset[binary & 0x3f] : "=";
}
return output;
}
const customCharset =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const shuffledCharset = shuffle(customCharset.split("")).join("");
return {
code: new Template(`
// Creates a reverse lookup table from the given charset
function createReverseCharset(charset) {
if (charset.length !== 64) {
throw new Error("Charset must be exactly 64 characters long.");
}
const reverseCharset = {};
for (let i = 0; i < charset.length; i++) {
reverseCharset[charset[i]] = i;
}
return reverseCharset;
}
// Base64 decode using the shuffled charset
function decode(input, charset) {
const reverseCharset = createReverseCharset(charset);
const cleanedInput = input.replace(/=+$/, ''); // Remove padding
const byteArray = [];
let buffer = 0;
let bitsCollected = 0;
for (let i = 0; i < cleanedInput.length; i++) {
buffer = (buffer << 6) | reverseCharset[cleanedInput[i]];
bitsCollected += 6;
if (bitsCollected >= 8) {
bitsCollected -= 8;
byteArray.push((buffer >> bitsCollected) & 0xFF);
}
}
// Convert to string, ensuring no extra characters
return new TextDecoder().decode(Uint8Array.from(byteArray));
}
var {fnName} = (str) => decode(str, {shuffledCharset});
`).setDefaultVariables({
// This simply inserts 'shuffledCharset' (with proper escaping)
shuffledCharset: stringLiteral(shuffledCharset),
}),
encode: (input) => {
// Encode the string
return encode(input, shuffledCharset);
},
// Identity key to help distinguish between different variants
identity: shuffledCharset,
};
}
module.exports = {
target: "node",
stringConcealing: true,
customStringEncodings: [createCustomStringEncoding],
};
Usage Example
The provided code example will obfuscate the fileinput.js and write the output to a file named output.js.
Usage Example
import JSConfuser from "js-confuser";
import {readFileSync, writeFileSync} from "fs";
// Read input code
const sourceCode = readFileSync("input.js", "utf8");
const options = {
target: 'browser',
customStringEncodings: [
{
code: `
function {fnName}(str){
return atob(str)
}
`,
encode: function(str) {
return btoa(str);
},
decode: function(str) {
return atob(str);
},
},
],
stringConcealing: true,
};
JSConfuser.obfuscate(sourceCode, options).then((result)=>{
// Write output code
writeFileSync("output.js", result.code);
}).catch(err=>{
// Error occurred
console.error(err);
});
Enabled In
- High Preset: No
- Medium Preset: No
- Low Preset: No