This commit is contained in:
sanex3339
2016-06-11 12:43:14 +03:00
parent 7d00d7fe5e
commit f7ff0fd853
26 changed files with 367 additions and 306 deletions
+9 -13
View File
@@ -8,11 +8,7 @@ import * as escodegen from 'escodegen';
import { INode } from './interfaces/nodes/INode';
import { IObfuscator } from "./interfaces/IObfuscator";
import { IOptions } from './interfaces/IOptions';
import { DEFAULT_PRESET } from './preset-options/DefaultPreset';
import { Obfuscator } from './Obfuscator';
import { OptionsNormalizer } from "./OptionsNormalizer";
import { IOptionsPreset } from "./interfaces/IOptionsPreset";
export class JavaScriptObfuscator {
/**
@@ -26,10 +22,12 @@ export class JavaScriptObfuscator {
* @param sourceCode
* @param customOptions
*/
public static obfuscate (sourceCode: string, customOptions?: IOptions): string {
public static obfuscate (sourceCode: string, customOptions?: IOptionsPreset): string {
let astTree: INode = esprima.parse(sourceCode),
options: IOptions = OptionsNormalizer.normalize(Object.assign({}, DEFAULT_PRESET, customOptions)),
obfuscator: Obfuscator = kernel.get<IObfuscator>('IObfuscator');
options: IOptions = kernel.get<IOptions>('IOptions'),
obfuscator: IObfuscator = kernel.get<IObfuscator>('IObfuscator');
options.assign(customOptions);
astTree = obfuscator.obfuscateNode(astTree);
@@ -43,11 +41,9 @@ export class JavaScriptObfuscator {
private static generateCode (astTree: INode, options: IOptions): string {
let escodegenParams: escodegen.GenerateOptions = Object.assign({}, JavaScriptObfuscator.escodegenParams);
if (options.hasOwnProperty('compact')) {
escodegenParams.format = {
compact: options.compact
};
}
escodegenParams.format = {
compact: options.getOption('compact')
};
return escodegen.generate(astTree, escodegenParams);
}
+3
View File
@@ -1,11 +1,14 @@
import { IKernel } from "inversify";
import { IObfuscator } from "./interfaces/IObfuscator";
import { IOptions } from "./interfaces/IOptions";
import { Kernel } from "inversify";
import { Obfuscator } from "./Obfuscator";
import { Options } from "./Options";
let kernel: IKernel = new Kernel();
kernel.bind<IOptions>('IOptions').to(Options);
kernel.bind<IObfuscator>('IObfuscator').to(Obfuscator);
export default kernel;
+9 -7
View File
@@ -1,4 +1,4 @@
import { injectable } from "inversify";
import { inject, injectable } from "inversify";
import * as estraverse from 'estraverse';
@@ -61,7 +61,9 @@ export class Obfuscator implements IObfuscator {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (
@inject('IOptions') options: IOptions
) {
this.options = options;
}
@@ -149,22 +151,22 @@ export class Obfuscator implements IObfuscator {
}
private setNewNodes (): void {
if (this.options['selfDefending']) {
if (this.options.getOption('selfDefending')) {
this.setNodesGroup(new SelfDefendingNodesGroup(this.options));
}
if (this.options['disableConsoleOutput']) {
if (this.options.getOption('disableConsoleOutput')) {
this.setNode(
'consoleOutputDisableExpressionNode',
new ConsoleOutputDisableExpressionNode()
new ConsoleOutputDisableExpressionNode(this.options)
);
}
if (this.options['debugProtection']) {
if (this.options.getOption('debugProtection')) {
this.setNodesGroup(new DebugProtectionNodesGroup(this.options));
}
if (this.options['unicodeArray']) {
if (this.options.getOption('unicodeArray')) {
/**
* Important to set this nodes latest to prevent runtime errors caused by `rotateUnicodeArray` option
*/
+114
View File
@@ -0,0 +1,114 @@
import { injectable } from "inversify";
import { IOptions } from "./interfaces/IOptions";
import { IOptionsPreset } from "./interfaces/IOptionsPreset";
import { DEFAULT_PRESET } from "./preset-options/DefaultPreset";
@injectable()
export class Options implements IOptions {
/**
* @type {IOptionsPreset}
*/
private static DISABLED_UNICODE_ARRAY_OPTIONS: IOptionsPreset = {
encodeUnicodeLiterals: false,
rotateUnicodeArray: false,
unicodeArray: false,
unicodeArrayThreshold: 0,
wrapUnicodeArrayCalls: false
};
/**
* @type {IOptionsPreset}
*/
private options: IOptionsPreset;
/**
* @type {IOptionsPreset}
*/
public static SELF_DEFENDING_OPTIONS: IOptionsPreset = {
compact: true,
selfDefending: true
};
/**
* @param options
*/
public assign (options: IOptionsPreset): void {
if (this.options) {
throw new Error('Options can\'t be reassigned!');
}
this.options = Object.assign({}, DEFAULT_PRESET, options);
this.normalizeOptions();
}
/**
* @param optionName
* @returns {any}
*/
public getOption (optionName: string): any {
return this.options[optionName];
}
/**
* @returns {IOptionsPreset}
*/
public getOptions (): IOptionsPreset {
return this.options;
}
private normalizeOptions (): void {
let normalizedOptions: IOptionsPreset = Object.assign({}, this.options);
normalizedOptions = Options.unicodeArrayRule(normalizedOptions);
normalizedOptions = Options.unicodeArrayThresholdRule(normalizedOptions);
normalizedOptions = Options.selfDefendingRule(normalizedOptions);
this.options = Object.freeze(normalizedOptions);
}
/**
* @param options
* @returns {IOptionsPreset}
*/
private static selfDefendingRule (options: IOptionsPreset): IOptionsPreset {
if (options['selfDefending']) {
Object.assign(options, Options.SELF_DEFENDING_OPTIONS);
}
return options;
}
/**
* @param options
* @returns {IOptionsPreset}
*/
private static unicodeArrayRule (options: IOptionsPreset): IOptionsPreset {
if (!options['unicodeArray']) {
Object.assign(options, Options.DISABLED_UNICODE_ARRAY_OPTIONS);
}
return options;
}
/**
* @param options
* @returns {IOptionsPreset}
*/
private static unicodeArrayThresholdRule (options: IOptionsPreset): IOptionsPreset {
const minValue: number = 0,
maxValue: number = 1;
options['unicodeArrayThreshold'] = Math.min(
Math.max(
options['unicodeArrayThreshold'],
minValue
),
maxValue
);
return options;
}
}
-79
View File
@@ -1,79 +0,0 @@
import { IOptions } from "./interfaces/IOptions";
export class OptionsNormalizer {
/**
* @type {IOptions}
*/
public static DISABLED_UNICODE_ARRAY_OPTIONS: IOptions = {
encodeUnicodeLiterals: false,
rotateUnicodeArray: false,
unicodeArray: false,
unicodeArrayThreshold: 0,
wrapUnicodeArrayCalls: false
};
/**
* @type {IOptions}
*/
public static SELF_DEFENDING_OPTIONS: IOptions = {
compact: true,
selfDefending: true
};
/**
* @param options
* @returns {IOptions}
*/
public static normalize (options: IOptions): IOptions {
let normalizedOptions: IOptions = Object.assign({}, options);
normalizedOptions = OptionsNormalizer.unicodeArrayRule(normalizedOptions);
normalizedOptions = OptionsNormalizer.unicodeArrayThresholdRule(normalizedOptions);
normalizedOptions = OptionsNormalizer.selfDefendingRule(normalizedOptions);
return normalizedOptions;
}
/**
* @param options
* @returns {IOptions}
*/
private static selfDefendingRule (options: IOptions): IOptions {
if (options['selfDefending']) {
Object.assign(options, OptionsNormalizer.SELF_DEFENDING_OPTIONS);
}
return options;
}
/**
* @param options
* @returns {IOptions}
*/
private static unicodeArrayRule (options: IOptions): IOptions {
if (!options['unicodeArray']) {
Object.assign(options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
}
return options;
}
/**
* @param options
* @returns {IOptions}
*/
private static unicodeArrayThresholdRule (options: IOptions): IOptions {
const minValue: number = 0,
maxValue: number = 1;
options['unicodeArrayThreshold'] = Math.min(
Math.max(
options['unicodeArrayThreshold'],
minValue
),
maxValue
);
return options;
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ export abstract class Node implements ICustomNode {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
this.options = options;
}
@@ -12,7 +12,7 @@ export class ConsoleOutputDisableExpressionNode extends Node {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
super(options);
this.node = this.getNodeStructure();
@@ -18,7 +18,7 @@ export class DebugProtectionFunctionCallNode extends Node {
* @param debugProtectionFunctionName
* @param options
*/
constructor (debugProtectionFunctionName: string, options: IOptions = {}) {
constructor (debugProtectionFunctionName: string, options: IOptions) {
super(options);
this.debugProtectionFunctionName = debugProtectionFunctionName;
@@ -18,7 +18,7 @@ export class DebugProtectionFunctionIntervalNode extends Node {
* @param debugProtectionFunctionName
* @param options
*/
constructor (debugProtectionFunctionName: string, options: IOptions = {}) {
constructor (debugProtectionFunctionName: string, options: IOptions) {
super(options);
this.debugProtectionFunctionName = debugProtectionFunctionName;
@@ -19,7 +19,7 @@ export class DebugProtectionFunctionNode extends Node {
* @param debugProtectionFunctionName
* @param options
*/
constructor (debugProtectionFunctionName: string, options: IOptions = {}) {
constructor (debugProtectionFunctionName: string, options: IOptions) {
super(options);
this.debugProtectionFunctionName = debugProtectionFunctionName;
@@ -24,7 +24,7 @@ export class SelfDefendingUnicodeNode extends Node {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
super(options);
this.node = this.getNodeStructure();
@@ -42,7 +42,7 @@ export class UnicodeArrayCallsWrapper extends Node {
unicodeArrayCallsWrapperName: string,
unicodeArrayName: string,
unicodeArray: string[],
options: IOptions = {}
options: IOptions
) {
super(options);
@@ -39,7 +39,7 @@ export class UnicodeArrayDecodeNode extends Node {
constructor (
unicodeArrayName: string,
unicodeArray: string[],
options: IOptions = {}
options: IOptions
) {
super(options);
@@ -81,7 +81,7 @@ export class UnicodeArrayDecodeNode extends Node {
let code: string = '',
node: INode;
if (this.options['selfDefending']) {
if (this.options.getOption('selfDefending')) {
code = `
var ${environmentName} = function(){return ${Utils.stringToUnicode('dev')};};
@@ -47,7 +47,7 @@ export class UnicodeArrayNode extends Node {
constructor (
unicodeArrayName: string,
unicodeArrayRotateValue: number = 0,
options: IOptions = {}
options: IOptions
) {
super(options);
@@ -46,7 +46,7 @@ export class UnicodeArrayRotateFunctionNode extends Node {
unicodeArrayName: string,
unicodeArray: string[],
unicodeArrayRotateValue: number,
options: IOptions = {}
options: IOptions
) {
super(options);
@@ -86,7 +86,7 @@ export class UnicodeArrayRotateFunctionNode extends Node {
whileFunctionName: string = Utils.getRandomVariableName(),
node: INode;
if (this.options['selfDefending']) {
if (this.options.getOption('selfDefending')) {
code = JavaScriptObfuscator.obfuscate(`
(function () {
var func = function(){return ${Utils.stringToUnicode('dev')};};
+13 -11
View File
@@ -1,13 +1,15 @@
import { IOptionsPreset } from "./IOptionsPreset";
export interface IOptions {
compact?: boolean;
debugProtection?: boolean;
debugProtectionInterval?: boolean;
disableConsoleOutput?: boolean;
encodeUnicodeLiterals?: boolean;
reservedNames?: string[];
rotateUnicodeArray?: boolean;
selfDefending?: boolean;
unicodeArray?: boolean;
unicodeArrayThreshold?: number;
wrapUnicodeArrayCalls?: boolean;
/**
* @param options
*/
assign (options: IOptionsPreset): void;
/**
* @param optionName
*/
getOption (optionName: string): any;
getOptions (): IOptionsPreset;
}
+13
View File
@@ -0,0 +1,13 @@
export interface IOptionsPreset {
compact?: boolean;
debugProtection?: boolean;
debugProtectionInterval?: boolean;
disableConsoleOutput?: boolean;
encodeUnicodeLiterals?: boolean;
reservedNames?: string[];
rotateUnicodeArray?: boolean;
selfDefending?: boolean;
unicodeArray?: boolean;
unicodeArrayThreshold?: number;
wrapUnicodeArrayCalls?: boolean;
}
+2 -2
View File
@@ -16,7 +16,7 @@ export class DebugProtectionNodesGroup extends NodesGroup {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
super(options);
this.nodes.set(
@@ -28,7 +28,7 @@ export class DebugProtectionNodesGroup extends NodesGroup {
new DebugProtectionFunctionCallNode(this.debugProtectionFunctionIdentifier, this.options)
);
if (this.options['debugProtectionInterval']) {
if (this.options.getOption('debugProtectionInterval')) {
this.nodes.set(
'debugProtectionFunctionIntervalNode',
new DebugProtectionFunctionIntervalNode(this.debugProtectionFunctionIdentifier, this.options)
+1 -1
View File
@@ -14,7 +14,7 @@ export abstract class NodesGroup implements INodesGroup {
*/
protected options: IOptions;
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
this.options = options;
}
+1 -1
View File
@@ -7,7 +7,7 @@ export class SelfDefendingNodesGroup extends NodesGroup {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
super(options);
this.nodes.set(
+5 -5
View File
@@ -26,10 +26,10 @@ export class UnicodeArrayNodesGroup extends NodesGroup {
/**
* @param options
*/
constructor (options: IOptions = {}) {
constructor (options: IOptions) {
super(options);
this.unicodeArrayRotateValue = this.options['rotateUnicodeArray'] ? Utils.getRandomInteger(100, 500) : 0;
this.unicodeArrayRotateValue = this.options.getOption('rotateUnicodeArray') ? Utils.getRandomInteger(100, 500) : 0;
let unicodeArrayNode: UnicodeArrayNode = new UnicodeArrayNode(
this.unicodeArrayName,
@@ -43,7 +43,7 @@ export class UnicodeArrayNodesGroup extends NodesGroup {
unicodeArrayNode
);
if (this.options['wrapUnicodeArrayCalls']) {
if (this.options.getOption('wrapUnicodeArrayCalls')) {
this.nodes.set(
'unicodeArrayCallsWrapper',
new UnicodeArrayCallsWrapper(
@@ -55,7 +55,7 @@ export class UnicodeArrayNodesGroup extends NodesGroup {
);
}
if (this.options['encodeUnicodeLiterals']) {
if (this.options.getOption('encodeUnicodeLiterals')) {
this.nodes.set(
'unicodeArrayDecodeNode',
new UnicodeArrayDecodeNode (
@@ -66,7 +66,7 @@ export class UnicodeArrayNodesGroup extends NodesGroup {
);
}
if (this.options['rotateUnicodeArray']) {
if (this.options.getOption('rotateUnicodeArray')) {
this.nodes.set(
'unicodeArrayRotateFunctionNode',
new UnicodeArrayRotateFunctionNode(
+9 -8
View File
@@ -24,7 +24,7 @@ export abstract class NodeObfuscator implements INodeObfuscator {
* @param nodes
* @param options
*/
constructor(nodes: Map <string, ICustomNode>, options: IOptions = {}) {
constructor(nodes: Map <string, ICustomNode>, options: IOptions) {
this.nodes = nodes;
this.options = options;
}
@@ -40,9 +40,10 @@ export abstract class NodeObfuscator implements INodeObfuscator {
* @returns {boolean}
*/
protected isReservedName (name: string): boolean {
return this.options['reservedNames'].some((reservedName: string) => {
return new RegExp(reservedName, 'g').test(name);
});
return this.options.getOption('reservedNames')
.some((reservedName: string) => {
return new RegExp(reservedName, 'g').test(name);
});
}
/**
@@ -98,15 +99,15 @@ export abstract class NodeObfuscator implements INodeObfuscator {
*/
protected replaceLiteralValueByUnicodeValue (nodeValue: string): string {
let value: string = nodeValue,
replaceByUnicodeArrayFlag: boolean = Math.random() <= this.options['unicodeArrayThreshold'];
replaceByUnicodeArrayFlag: boolean = Math.random() <= this.options.getOption('unicodeArrayThreshold');
if (this.options['encodeUnicodeLiterals'] && replaceByUnicodeArrayFlag) {
if (this.options.getOption('encodeUnicodeLiterals') && replaceByUnicodeArrayFlag) {
value = Utils.btoa(value);
}
value = Utils.stringToUnicode(value);
if (!this.options['unicodeArray'] || !replaceByUnicodeArrayFlag) {
if (!this.options.getOption('unicodeArray') || !replaceByUnicodeArrayFlag) {
return value;
}
@@ -133,7 +134,7 @@ export abstract class NodeObfuscator implements INodeObfuscator {
hexadecimalIndex = this.replaceLiteralNumberByHexadecimalValue(index);
if (this.options['wrapUnicodeArrayCalls']) {
if (this.options.getOption('wrapUnicodeArrayCalls')) {
return `${this.nodes.get('unicodeArrayCallsWrapper').getNodeIdentifier()}('${hexadecimalIndex}')`;
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { IOptions } from "../interfaces/IOptions";
import { IOptionsPreset } from "../interfaces/IOptionsPreset";
export const DEFAULT_PRESET: IOptions = Object.freeze({
export const DEFAULT_PRESET: IOptionsPreset = Object.freeze({
compact: true,
debugProtection: false,
debugProtectionInterval: false,
+2 -2
View File
@@ -1,6 +1,6 @@
import { IOptions } from "../interfaces/IOptions";
import { IOptionsPreset } from "../interfaces/IOptionsPreset";
export const NO_CUSTOM_NODES_PRESET: IOptions = Object.freeze({
export const NO_CUSTOM_NODES_PRESET: IOptionsPreset = Object.freeze({
compact: true,
debugProtection: false,
debugProtectionInterval: false,