mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
rc4 encoding runtime error fix and performance boost
This commit is contained in:
Vendored
+13
-31
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+5
-3
@@ -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
@@ -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';`,
|
||||
|
||||
Reference in New Issue
Block a user