mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge pull request #162 from javascript-obfuscator/improved-string-array-templates
Improved string array templates
This commit is contained in:
@@ -4,6 +4,7 @@ v0.14.0
|
||||
---
|
||||
* **Breaking change:** Now CLI obfuscating directory recursively. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/157
|
||||
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/156
|
||||
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/159
|
||||
|
||||
v0.13.0
|
||||
---
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "0.14.0-beta.1",
|
||||
"version": "0.14.0-beta.2",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
|
||||
@@ -118,29 +118,41 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
|
||||
selfDefendingCode: string = '';
|
||||
|
||||
if (this.options.selfDefending) {
|
||||
selfDefendingCode = format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
|
||||
stringArrayName: this.stringArrayName
|
||||
});
|
||||
selfDefendingCode = format(
|
||||
SelfDefendingTemplate(
|
||||
this.randomGenerator,
|
||||
this.escapeSequenceEncoder
|
||||
),
|
||||
{
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
|
||||
stringArrayName: this.stringArrayName
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
switch (this.options.stringArrayEncoding) {
|
||||
case StringArrayEncoding.Rc4:
|
||||
decodeStringArrayTemplate = format(StringArrayRc4DecodeNodeTemplate(), {
|
||||
atobPolyfill,
|
||||
rc4Polyfill: Rc4Template(),
|
||||
selfDefendingCode,
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
|
||||
});
|
||||
decodeStringArrayTemplate = format(
|
||||
StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
|
||||
{
|
||||
atobPolyfill,
|
||||
rc4Polyfill: Rc4Template(),
|
||||
selfDefendingCode,
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
|
||||
}
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case StringArrayEncoding.Base64:
|
||||
decodeStringArrayTemplate = format(StringArrayBase64DecodeNodeTemplate(), {
|
||||
atobPolyfill,
|
||||
selfDefendingCode,
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
|
||||
});
|
||||
decodeStringArrayTemplate = format(
|
||||
StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
|
||||
{
|
||||
atobPolyfill,
|
||||
selfDefendingCode,
|
||||
stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
|
||||
}
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
+40
-33
@@ -1,59 +1,66 @@
|
||||
import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
|
||||
import { Utils } from '../../../utils/Utils';
|
||||
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
|
||||
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
|
||||
const symTbl: { [key: string]: string } = {
|
||||
'rc4Bytes': Utils.generateIden(),
|
||||
'states': Utils.generateIden(),
|
||||
'newState': Utils.generateIden(),
|
||||
'firstState': Utils.generateIden(),
|
||||
'secondState': Utils.generateIden(),
|
||||
'checkState': Utils.generateIden(),
|
||||
'runState': Utils.generateIden(),
|
||||
'getState': Utils.generateIden(),
|
||||
'stateResult': Utils.generateIden()
|
||||
};
|
||||
export function SelfDefendingTemplate (
|
||||
randomGenerator: IRandomGenerator,
|
||||
escapeSequenceEncoder: IEscapeSequenceEncoder
|
||||
): string {
|
||||
const identifierLength: number = 6;
|
||||
const rc4BytesIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const statesIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const newStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const firstStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const secondStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const checkStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const runStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const getStateIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const stateResultIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
|
||||
return `
|
||||
var StatesClass = function (${symTbl.rc4Bytes}) {
|
||||
this.${symTbl.rc4Bytes} = ${symTbl.rc4Bytes};
|
||||
this.${symTbl.states} = [1, 0, 0];
|
||||
this.${symTbl.newState} = function(){return 'newState';};
|
||||
this.${symTbl.firstState} = '${
|
||||
var StatesClass = function (${rc4BytesIdentifier}) {
|
||||
this.${rc4BytesIdentifier} = ${rc4BytesIdentifier};
|
||||
this.${statesIdentifier} = [1, 0, 0];
|
||||
this.${newStateIdentifier} = function(){return 'newState';};
|
||||
this.${firstStateIdentifier} = '${
|
||||
escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *`, true)
|
||||
}';
|
||||
this.${symTbl.secondState} = '${
|
||||
this.${secondStateIdentifier} = '${
|
||||
escapeSequenceEncoder.encode(`['|"].+['|"];? *}`, true)
|
||||
}';
|
||||
};
|
||||
|
||||
StatesClass.prototype.${symTbl.checkState} = function () {
|
||||
var regExp = new RegExp(this.${symTbl.firstState} + this.${symTbl.secondState});
|
||||
|
||||
return this.${symTbl.runState}(regExp.test(this.${symTbl.newState}.toString()) ? --this.${symTbl.states}[1] : --this.${symTbl.states}[0]);
|
||||
StatesClass.prototype.${checkStateIdentifier} = function () {
|
||||
var regExp = new RegExp(this.${firstStateIdentifier} + this.${secondStateIdentifier});
|
||||
var expression = regExp.test(this.${newStateIdentifier}.toString())
|
||||
? --this.${statesIdentifier}[1]
|
||||
: --this.${statesIdentifier}[0];
|
||||
|
||||
return this.${runStateIdentifier}(expression);
|
||||
};
|
||||
|
||||
StatesClass.prototype.${symTbl.runState} = function (${symTbl.stateResult}) {
|
||||
if (!Boolean(~${symTbl.stateResult})) {
|
||||
return ${symTbl.stateResult};
|
||||
StatesClass.prototype.${runStateIdentifier} = function (${stateResultIdentifier}) {
|
||||
if (!Boolean(~${stateResultIdentifier})) {
|
||||
return ${stateResultIdentifier};
|
||||
}
|
||||
|
||||
return this.${symTbl.getState}(this.${symTbl.rc4Bytes});
|
||||
return this.${getStateIdentifier}(this.${rc4BytesIdentifier});
|
||||
};
|
||||
|
||||
StatesClass.prototype.${symTbl.getState} = function (${symTbl.rc4Bytes}) {
|
||||
for (var i = 0, len = this.${symTbl.states}.length; i < len; i++) {
|
||||
this.${symTbl.states}.push(Math.round(Math.random()));
|
||||
len = this.${symTbl.states}.length;
|
||||
StatesClass.prototype.${getStateIdentifier} = function (${rc4BytesIdentifier}) {
|
||||
for (var i = 0, len = this.${statesIdentifier}.length; i < len; i++) {
|
||||
this.${statesIdentifier}.push(Math.round(Math.random()));
|
||||
len = this.${statesIdentifier}.length;
|
||||
}
|
||||
|
||||
return ${symTbl.rc4Bytes}(this.${symTbl.states}[0]);
|
||||
return ${rc4BytesIdentifier}(this.${statesIdentifier}[0]);
|
||||
};
|
||||
|
||||
new StatesClass({stringArrayCallsWrapperName}).${symTbl.checkState}();
|
||||
new StatesClass({stringArrayCallsWrapperName}).${checkStateIdentifier}();
|
||||
`;
|
||||
}
|
||||
|
||||
+19
-8
@@ -1,12 +1,23 @@
|
||||
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
|
||||
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function StringArrayBase64DecodeNodeTemplate (): string {
|
||||
export function StringArrayBase64DecodeNodeTemplate (
|
||||
randomGenerator: IRandomGenerator
|
||||
): string {
|
||||
const identifierLength: number = 6;
|
||||
const initializedIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const base64DecodeFunctionIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const dataIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
|
||||
return `
|
||||
if ({stringArrayCallsWrapperName}.initialized === undefined) {
|
||||
if ({stringArrayCallsWrapperName}.${initializedIdentifier} === undefined) {
|
||||
{atobPolyfill}
|
||||
|
||||
{stringArrayCallsWrapperName}.base64DecodeUnicode = function (str) {
|
||||
{stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier} = function (str) {
|
||||
var string = atob(str);
|
||||
var newStringChars = [];
|
||||
|
||||
@@ -17,18 +28,18 @@ export function StringArrayBase64DecodeNodeTemplate (): string {
|
||||
return decodeURIComponent(newStringChars);
|
||||
};
|
||||
|
||||
{stringArrayCallsWrapperName}.data = {};
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier} = {};
|
||||
|
||||
{stringArrayCallsWrapperName}.initialized = true;
|
||||
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
|
||||
}
|
||||
|
||||
var cachedValue = {stringArrayCallsWrapperName}.data[index];
|
||||
var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
|
||||
|
||||
if (cachedValue === undefined) {
|
||||
{selfDefendingCode}
|
||||
|
||||
value = {stringArrayCallsWrapperName}.base64DecodeUnicode(value);
|
||||
{stringArrayCallsWrapperName}.data[index] = value;
|
||||
value = {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier}(value);
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
|
||||
} else {
|
||||
value = cachedValue;
|
||||
}
|
||||
|
||||
+20
-17
@@ -1,39 +1,42 @@
|
||||
import { Utils } from '../../../utils/Utils';
|
||||
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
|
||||
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
export function StringArrayRc4DecodeNodeTemplate (): string {
|
||||
const symTbl: { [key: string]: string } = {
|
||||
'initialized': Utils.generateIden(),
|
||||
'rc4': Utils.generateIden(),
|
||||
'data': Utils.generateIden(),
|
||||
'once': Utils.generateIden()
|
||||
};
|
||||
export function StringArrayRc4DecodeNodeTemplate (
|
||||
randomGenerator: IRandomGenerator
|
||||
): string {
|
||||
const identifierLength: number = 6;
|
||||
const initializedIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const rc4Identifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const dataIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
const onceIdentifier: string = randomGenerator.getRandomString(identifierLength);
|
||||
|
||||
return `
|
||||
if ({stringArrayCallsWrapperName}.${symTbl.initialized} === undefined) {
|
||||
if ({stringArrayCallsWrapperName}.${initializedIdentifier} === undefined) {
|
||||
{atobPolyfill}
|
||||
|
||||
{rc4Polyfill}
|
||||
{stringArrayCallsWrapperName}.${symTbl.rc4} = rc4;
|
||||
{stringArrayCallsWrapperName}.${rc4Identifier} = rc4;
|
||||
|
||||
{stringArrayCallsWrapperName}.${symTbl.data} = {};
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier} = {};
|
||||
|
||||
{stringArrayCallsWrapperName}.${symTbl.initialized} = true;
|
||||
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
|
||||
}
|
||||
|
||||
var cachedValue = {stringArrayCallsWrapperName}.${symTbl.data}[index];
|
||||
var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
|
||||
|
||||
if (cachedValue === undefined) {
|
||||
if ({stringArrayCallsWrapperName}.${symTbl.once} === undefined) {
|
||||
if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
|
||||
{selfDefendingCode}
|
||||
|
||||
{stringArrayCallsWrapperName}.${symTbl.once} = true;
|
||||
{stringArrayCallsWrapperName}.${onceIdentifier} = true;
|
||||
}
|
||||
|
||||
value = {stringArrayCallsWrapperName}.${symTbl.rc4}(value, key);
|
||||
{stringArrayCallsWrapperName}.${symTbl.data}[index] = value;
|
||||
value = {stringArrayCallsWrapperName}.${rc4Identifier}(value, key);
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
|
||||
} else {
|
||||
value = cachedValue;
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
export type TObject = {[key: string]: any};
|
||||
export type TObject <T = any> = {[key: string]: T};
|
||||
|
||||
@@ -71,24 +71,4 @@ export class Utils {
|
||||
})
|
||||
.join(' + ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
public static generateIden (): string {
|
||||
let validIden: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_';
|
||||
let ret: string = '';
|
||||
|
||||
const idenIdx: (() => number) = () => Math.floor(Math.random() * validIden.length) % validIden.length;
|
||||
|
||||
ret += validIden[idenIdx()];
|
||||
validIden += '0123456789';
|
||||
|
||||
const len: number = Math.floor((Math.random() * 10) + 3);
|
||||
for (let i: number = 0; i < len; i++) {
|
||||
ret += validIden[idenIdx()];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-18
@@ -1,3 +1,5 @@
|
||||
import 'reflect-metadata';
|
||||
|
||||
import * as format from 'string-template';
|
||||
|
||||
import { assert } from 'chai';
|
||||
@@ -6,6 +8,7 @@ import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifi
|
||||
|
||||
import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils';
|
||||
import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade';
|
||||
import { IRandomGenerator } from '../../../../../src/interfaces/utils/IRandomGenerator';
|
||||
|
||||
import { AtobTemplate } from '../../../../../src/templates/AtobTemplate';
|
||||
import { GlobalVariableTemplate1 } from '../../../../../src/templates/GlobalVariableTemplate1';
|
||||
@@ -20,30 +23,35 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
|
||||
const stringArrayName: string = 'stringArrayName';
|
||||
const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
|
||||
|
||||
let cryptUtils: ICryptUtils;
|
||||
let cryptUtils: ICryptUtils,
|
||||
randomGenerator: IRandomGenerator;
|
||||
|
||||
before(() => {
|
||||
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
|
||||
|
||||
inversifyContainerFacade.load('', {});
|
||||
cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
|
||||
randomGenerator = inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
|
||||
});
|
||||
|
||||
describe('variant #1: `base64` encoding', () => {
|
||||
const atobPolyfill = format(AtobTemplate(), {
|
||||
globalVariableTemplate: GlobalVariableTemplate1()
|
||||
});
|
||||
const atobDecodeNodeTemplate: string = format(StringArrayBase64DecodeNodeTemplate(), {
|
||||
atobPolyfill,
|
||||
selfDefendingCode: '',
|
||||
stringArrayCallsWrapperName
|
||||
});
|
||||
const index: string = '0x0';
|
||||
const expectedDecodedValue: string = 'test1';
|
||||
|
||||
let decodedValue: string;
|
||||
|
||||
before(() => {
|
||||
const atobPolyfill = format(AtobTemplate(), {
|
||||
globalVariableTemplate: GlobalVariableTemplate1()
|
||||
});
|
||||
const atobDecodeNodeTemplate: string = format(
|
||||
StringArrayBase64DecodeNodeTemplate(randomGenerator),
|
||||
{
|
||||
atobPolyfill,
|
||||
selfDefendingCode: '',
|
||||
stringArrayCallsWrapperName
|
||||
}
|
||||
);
|
||||
const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
|
||||
decodeNodeTemplate: atobDecodeNodeTemplate,
|
||||
stringArrayCallsWrapperName,
|
||||
@@ -65,15 +73,6 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
|
||||
});
|
||||
|
||||
describe('variant #2: `rc4` encoding', () => {
|
||||
const atobPolyfill = format(AtobTemplate(), {
|
||||
globalVariableTemplate: GlobalVariableTemplate1()
|
||||
});
|
||||
const rc4DecodeNodeTemplate: string = format(StringArrayRc4DecodeNodeTemplate(), {
|
||||
atobPolyfill,
|
||||
rc4Polyfill: Rc4Template(),
|
||||
selfDefendingCode: '',
|
||||
stringArrayCallsWrapperName
|
||||
});
|
||||
const index: string = '0x0';
|
||||
const key: string = 'key';
|
||||
const expectedDecodedValue: string = 'test1';
|
||||
@@ -81,6 +80,18 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
|
||||
let decodedValue: string;
|
||||
|
||||
before(() => {
|
||||
const atobPolyfill = format(AtobTemplate(), {
|
||||
globalVariableTemplate: GlobalVariableTemplate1()
|
||||
});
|
||||
const rc4DecodeNodeTemplate: string = format(
|
||||
StringArrayRc4DecodeNodeTemplate(randomGenerator),
|
||||
{
|
||||
atobPolyfill,
|
||||
rc4Polyfill: Rc4Template(),
|
||||
selfDefendingCode: '',
|
||||
stringArrayCallsWrapperName
|
||||
}
|
||||
);
|
||||
const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
|
||||
decodeNodeTemplate: rc4DecodeNodeTemplate,
|
||||
stringArrayCallsWrapperName,
|
||||
|
||||
Reference in New Issue
Block a user