Merge pull request #162 from javascript-obfuscator/improved-string-array-templates

Improved string array templates
This commit is contained in:
Timofey Kachalov
2018-01-01 18:01:50 +03:00
committed by GitHub
10 changed files with 139 additions and 114 deletions
+1
View File
@@ -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
---
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -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;
}
@@ -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}();
`;
}
@@ -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;
}
@@ -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;
}
+1 -1
View File
@@ -1 +1 @@
export type TObject = {[key: string]: any};
export type TObject <T = any> = {[key: string]: T};
-20
View File
@@ -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;
}
}
@@ -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,