rc4 encoding runtime error fix and performance boost

This commit is contained in:
sanex3339
2017-01-03 18:49:31 +03:00
parent 8e14a3e90a
commit 8c5d323752
8 changed files with 74 additions and 125 deletions
+13 -31
View File
@@ -2435,7 +2435,9 @@ var Obfuscator = Obfuscator_1 = function () {
if (this.options.controlFlowFlattening) {
astTree = this.transformAstTree(astTree, VisitorDirection_1.VisitorDirection.leave, this.nodeTransformersFactory(Obfuscator_1.nodeControlFlowTransformersMap));
}
console.time();
astTree = this.transformAstTree(astTree, VisitorDirection_1.VisitorDirection.enter, this.nodeTransformersFactory(Obfuscator_1.nodeObfuscatorsMap));
console.timeEnd();
this.obfuscationEventEmitter.emit(ObfuscationEvents_1.ObfuscationEvents.AfterObfuscation, astTree, stackTraceData);
return astTree;
}
@@ -5757,7 +5759,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
var tslib_1 = __webpack_require__(3);
var inversify_1 = __webpack_require__(2);
var ServiceIdentifiers_1 = __webpack_require__(4);
var escodegen = __webpack_require__(26);
var NodeObfuscatorsReplacers_1 = __webpack_require__(20);
var NodeType_1 = __webpack_require__(15);
var AbstractNodeTransformer_1 = __webpack_require__(18);
@@ -5777,9 +5778,7 @@ var MemberExpressionObfuscator = function (_AbstractNodeTransfor) {
(0, _createClass3.default)(MemberExpressionObfuscator, [{
key: "transformNode",
value: function transformNode(memberExpressionNode) {
if (Node_1.Node.isLiteralNode(memberExpressionNode.property)) {
memberExpressionNode.property = this.obfuscateLiteralProperty(memberExpressionNode.property);
} else if (Node_1.Node.isIdentifierNode(memberExpressionNode.property)) {
if (Node_1.Node.isIdentifierNode(memberExpressionNode.property)) {
if (memberExpressionNode.computed) {
return memberExpressionNode;
}
@@ -5794,24 +5793,9 @@ var MemberExpressionObfuscator = function (_AbstractNodeTransfor) {
return {
type: NodeType_1.NodeType.Literal,
value: node.name,
raw: "'" + node.name + "'",
'x-verbatim-property': {
content: this.stringLiteralReplacer.replace(node.name),
precedence: escodegen.Precedence.Primary
}
raw: "'" + node.name + "'"
};
}
}, {
key: "obfuscateLiteralProperty",
value: function obfuscateLiteralProperty(node) {
if (typeof node.value === 'string' && !node['x-verbatim-property']) {
node['x-verbatim-property'] = {
content: this.stringLiteralReplacer.replace(node.value),
precedence: escodegen.Precedence.Primary
};
}
return node;
}
}]);
return MemberExpressionObfuscator;
}(AbstractNodeTransformer_1.AbstractNodeTransformer);
@@ -5851,6 +5835,7 @@ var tslib_1 = __webpack_require__(3);
var inversify_1 = __webpack_require__(2);
var ServiceIdentifiers_1 = __webpack_require__(4);
var NodeObfuscatorsReplacers_1 = __webpack_require__(20);
var NodeType_1 = __webpack_require__(15);
var AbstractNodeTransformer_1 = __webpack_require__(18);
var Node_1 = __webpack_require__(12);
var MethodDefinitionObfuscator = MethodDefinitionObfuscator_1 = function (_AbstractNodeTransfor) {
@@ -5876,8 +5861,11 @@ var MethodDefinitionObfuscator = MethodDefinitionObfuscator_1 = function (_Abstr
value: function replaceMethodName(methodDefinitionNode) {
if (Node_1.Node.isIdentifierNode(methodDefinitionNode.key) && !MethodDefinitionObfuscator_1.ignoredNames.includes(methodDefinitionNode.key.name) && methodDefinitionNode.computed === false) {
methodDefinitionNode.computed = true;
methodDefinitionNode.key.name = this.stringLiteralReplacer.replace(methodDefinitionNode.key.name);
return;
methodDefinitionNode.key = {
type: NodeType_1.NodeType.Literal,
value: methodDefinitionNode.key.name,
raw: "'" + methodDefinitionNode.key.name + "'"
};
}
}
}]);
@@ -6402,15 +6390,9 @@ var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplace
if (this.stringLiteralHexadecimalIndexCache.has(value)) {
return this.stringLiteralHexadecimalIndexCache.get(value);
}
var indexOfExistingValue = this.stringArrayStorage.getKeyOf(value);
var indexOfValue = void 0;
if (indexOfExistingValue >= 0) {
indexOfValue = indexOfExistingValue;
} else {
indexOfValue = this.stringArrayStorage.getLength();
this.stringArrayStorage.set(null, value);
}
var indexOfValue = this.stringArrayStorage.getLength();
var hexadecimalIndex = "" + Utils_1.Utils.hexadecimalPrefix + Utils_1.Utils.decToHex(indexOfValue);
this.stringArrayStorage.set(null, value);
this.stringLiteralHexadecimalIndexCache.set(value, hexadecimalIndex);
return hexadecimalIndex;
}
@@ -7651,7 +7633,7 @@ exports.StringArrayCallsWrapperTemplate = StringArrayCallsWrapperTemplate;
function StringArrayRc4DecodeNodeTemplate() {
return "\n if (!{stringArrayCallsWrapperName}.atobPolyfillAppended) { \n {atobPolyfill}\n \n {stringArrayCallsWrapperName}.atobPolyfillAppended = true;\n }\n \n if (!{stringArrayCallsWrapperName}.rc4) { \n {rc4Polyfill}\n \n {stringArrayCallsWrapperName}.rc4 = rc4;\n }\n \n if (!{stringArrayCallsWrapperName}.data) {\n {stringArrayCallsWrapperName}.data = {};\n }\n\n if ({stringArrayCallsWrapperName}.data[index] === undefined) {\n if (!{stringArrayCallsWrapperName}.once) {\n {selfDefendingCode}\n \n {stringArrayCallsWrapperName}.once = true;\n }\n \n value = {stringArrayCallsWrapperName}.rc4(value, key);\n {stringArrayCallsWrapperName}.data[index] = value;\n } else {\n value = {stringArrayCallsWrapperName}.data[index];\n }\n ";
return "\n if (!{stringArrayCallsWrapperName}.atobPolyfillAppended) { \n {atobPolyfill}\n \n {stringArrayCallsWrapperName}.atobPolyfillAppended = true;\n }\n \n if (!{stringArrayCallsWrapperName}.rc4) { \n {rc4Polyfill}\n \n {stringArrayCallsWrapperName}.rc4 = rc4;\n }\n \n if (!{stringArrayCallsWrapperName}.data) {\n {stringArrayCallsWrapperName}.data = {};\n }\n\n var cacheKey = index + key;\n\n if ({stringArrayCallsWrapperName}.data[cacheKey] === undefined) {\n if (!{stringArrayCallsWrapperName}.once) {\n {selfDefendingCode}\n \n {stringArrayCallsWrapperName}.once = true;\n }\n \n value = {stringArrayCallsWrapperName}.rc4(value, key);\n {stringArrayCallsWrapperName}.data[cacheKey] = value;\n } else {\n value = {stringArrayCallsWrapperName}.data[cacheKey];\n }\n ";
}
exports.StringArrayRc4DecodeNodeTemplate = StringArrayRc4DecodeNodeTemplate;
+2
View File
@@ -137,11 +137,13 @@ export class Obfuscator implements IObfuscator {
}
// second pass: nodes obfuscation
console.time();
astTree = this.transformAstTree(
astTree,
VisitorDirection.enter,
this.nodeTransformersFactory(Obfuscator.nodeObfuscatorsMap)
);
console.timeEnd();
this.obfuscationEventEmitter.emit(ObfuscationEvents.AfterObfuscation, astTree, stackTraceData);
@@ -1,7 +1,6 @@
import { injectable, inject } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
import { IOptions } from '../../interfaces/options/IOptions';
@@ -38,9 +37,7 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
* @returns {ESTree.Node}
*/
public transformNode (memberExpressionNode: ESTree.MemberExpression): ESTree.Node {
if (Node.isLiteralNode(memberExpressionNode.property)) {
memberExpressionNode.property = this.obfuscateLiteralProperty(memberExpressionNode.property);
} else if (Node.isIdentifierNode(memberExpressionNode.property)) {
if (Node.isIdentifierNode(memberExpressionNode.property)) {
if (memberExpressionNode.computed) {
return memberExpressionNode;
}
@@ -57,11 +54,13 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
* object.identifier = 1;
*
* on:
* object[_0x23d45[25]] = 1;
* object['identifier'] = 1;
*
* and skip:
* object[identifier] = 1;
*
* Literal node will be obfuscated by LiteralObfuscator
*
* @param node
* @returns {ESTree.Literal}
*/
@@ -69,32 +68,7 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
return {
type: NodeType.Literal,
value: node.name,
raw: `'${node.name}'`,
'x-verbatim-property': {
content: this.stringLiteralReplacer.replace(node.name),
precedence: escodegen.Precedence.Primary
}
raw: `'${node.name}'`
};
}
/**
* replaces:
* object['literal'] = 1;
*
* on:
* object[_0x23d45[25]] = 1;
*
* @param node
* @returns {ESTree.Literal}
*/
private obfuscateLiteralProperty (node: ESTree.Literal): ESTree.Literal {
if (typeof node.value === 'string' && !node['x-verbatim-property']) {
node['x-verbatim-property'] = {
content: this.stringLiteralReplacer.replace(node.value),
precedence: escodegen.Precedence.Primary
};
}
return node;
}
}
@@ -7,6 +7,7 @@ import { IOptions } from '../../interfaces/options/IOptions';
import { IObfuscatorReplacer } from '../../interfaces/node-transformers/IObfuscatorReplacer';
import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscatorsReplacers';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { Node } from '../../node/Node';
@@ -16,7 +17,9 @@ import { Node } from '../../node/Node';
* foo () { //... };
*
* on:
* [_0x9a4e('0x0')] { //... };
* ['foo'] { //... };
*
* Literal node will be obfuscated by LiteralObfuscator
*/
@injectable()
export class MethodDefinitionObfuscator extends AbstractNodeTransformer {
@@ -55,17 +58,30 @@ export class MethodDefinitionObfuscator extends AbstractNodeTransformer {
}
/**
* replaces:
* object.identifier = 1;
*
* on:
* object['identifier'] = 1;
*
* and skip:
* object[identifier] = 1;
* Literal node will be obfuscated by LiteralObfuscator
*
* @param methodDefinitionNode
*/
private replaceMethodName (methodDefinitionNode: ESTree.MethodDefinition): void {
if (
Node.isIdentifierNode(methodDefinitionNode.key) && !MethodDefinitionObfuscator.ignoredNames.includes(methodDefinitionNode.key.name) &&
Node.isIdentifierNode(methodDefinitionNode.key) &&
!MethodDefinitionObfuscator.ignoredNames.includes(methodDefinitionNode.key.name) &&
methodDefinitionNode.computed === false
) {
methodDefinitionNode.computed = true;
methodDefinitionNode.key.name = this.stringLiteralReplacer.replace(methodDefinitionNode.key.name);
return;
methodDefinitionNode.key = {
type: NodeType.Literal,
value: methodDefinitionNode.key.name,
raw: `'${methodDefinitionNode.key.name}'`
};
}
}
}
@@ -100,19 +100,10 @@ export class StringLiteralReplacer extends AbstractReplacer {
return <string>this.stringLiteralHexadecimalIndexCache.get(value);
}
const indexOfExistingValue: number = <number>this.stringArrayStorage.getKeyOf(value);
let indexOfValue: number;
if (indexOfExistingValue >= 0) {
indexOfValue = indexOfExistingValue;
} else {
indexOfValue = this.stringArrayStorage.getLength();
this.stringArrayStorage.set(null, value);
}
const indexOfValue: number = this.stringArrayStorage.getLength();
const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${Utils.decToHex(indexOfValue)}`;
this.stringArrayStorage.set(null, value);
this.stringLiteralHexadecimalIndexCache.set(value, hexadecimalIndex);
return hexadecimalIndex;
@@ -19,7 +19,9 @@ export function StringArrayRc4DecodeNodeTemplate (): string {
{stringArrayCallsWrapperName}.data = {};
}
if ({stringArrayCallsWrapperName}.data[index] === undefined) {
var cacheKey = index + key;
if ({stringArrayCallsWrapperName}.data[cacheKey] === undefined) {
if (!{stringArrayCallsWrapperName}.once) {
{selfDefendingCode}
@@ -27,9 +29,9 @@ export function StringArrayRc4DecodeNodeTemplate (): string {
}
value = {stringArrayCallsWrapperName}.rc4(value, key);
{stringArrayCallsWrapperName}.data[index] = value;
{stringArrayCallsWrapperName}.data[cacheKey] = value;
} else {
value = {stringArrayCallsWrapperName}.data[index];
value = {stringArrayCallsWrapperName}.data[cacheKey];
}
`;
}
+5 -44
View File
@@ -1,4 +1,5 @@
'use strict';
import { NO_CUSTOM_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
if (!(<any>global)._babelPolyfill) {
require('babel-polyfill');
@@ -9,53 +10,13 @@ if (!(<any>global)._babelPolyfill) {
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
(function(){
var result = 1,
term1 = 0,
term2 = 1,
i = 1;
while(i < 10)
{
var test = 10;
result = term1 + term2;
console.log(result);
term1 = term2;
term2 = result;
i++;
}
console.log(test);
var test = function (test) {
console.log(test);
if (true) {
var test = 5
}
return test;
}
console.log(test(1));
function test2 (abc) {
function test1 () {
console.log('inside', abc.item);
}
console.log('тест', abc);
var abc = {};
return abc.item = 15, test1();
};
})();
var test = console.log;
`,
{
...NO_CUSTOM_NODES_PRESET,
compact: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
disableConsoleOutput: false
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
@@ -38,6 +38,27 @@ describe('LiteralObfuscator', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
});
it('should create only one item in string array for same literal node values', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`
var test = 'test';
var test = 'test';
object.test();
`,
{
...NO_CUSTOM_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/^var *_0x([a-z0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
});
it('should replace literal node value with raw value from string array if `unicodeEscapeSequence` is disabled', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,