mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Eval transformer template literal string processing
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -27,6 +27,47 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
|
||||
super(randomGenerator, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Expression | SpreadElement} node
|
||||
* @returns {string | null}
|
||||
*/
|
||||
private static extractEvalStringFromCallExpressionArgument (node: ESTree.Expression | ESTree.SpreadElement): string | null {
|
||||
if (NodeGuards.isLiteralNode(node)) {
|
||||
return EvalCallExpressionToAstTransformer
|
||||
.getEvalStringFromLiteralNode(node);
|
||||
}
|
||||
|
||||
if (NodeGuards.isTemplateLiteralNode(node)) {
|
||||
return EvalCallExpressionToAstTransformer
|
||||
.getEvalStringFromTemplateLiteralNode(node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Literal} node
|
||||
* @returns {string | null}
|
||||
*/
|
||||
private static getEvalStringFromLiteralNode (node: ESTree.Literal): string | null {
|
||||
return typeof node.value === 'string' ? node.value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TemplateLiteral} node
|
||||
* @returns {string | null}
|
||||
*/
|
||||
private static getEvalStringFromTemplateLiteralNode (node: ESTree.TemplateLiteral): string | null {
|
||||
const quasis: ESTree.TemplateElement[] = node.quasis;
|
||||
const allowedQuasisLength: number = 1;
|
||||
|
||||
if (quasis.length !== allowedQuasisLength || node.expressions.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return quasis[0].value.cooked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {IVisitor}
|
||||
*/
|
||||
@@ -53,32 +94,31 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
|
||||
public transformNode (callExpressionNode: ESTree.CallExpression, parentNode: ESTree.Node): ESTree.Node {
|
||||
const callExpressionFirstArgument: ESTree.Expression | ESTree.SpreadElement = callExpressionNode.arguments[0];
|
||||
|
||||
if (
|
||||
!callExpressionFirstArgument
|
||||
|| !NodeGuards.isLiteralNode(callExpressionFirstArgument)
|
||||
|| typeof callExpressionFirstArgument.value !== 'string'
|
||||
) {
|
||||
if (!callExpressionFirstArgument) {
|
||||
return callExpressionNode;
|
||||
}
|
||||
|
||||
const code: string = callExpressionFirstArgument.value;
|
||||
const evalString: string | null = EvalCallExpressionToAstTransformer
|
||||
.extractEvalStringFromCallExpressionArgument(callExpressionFirstArgument);
|
||||
|
||||
if (!evalString) {
|
||||
return callExpressionNode;
|
||||
}
|
||||
|
||||
let ast: TStatement[];
|
||||
|
||||
// wrapping into try-catch to prevent parsing of incorrect `eval` string
|
||||
try {
|
||||
ast = NodeUtils.convertCodeToStructure(code);
|
||||
ast = NodeUtils.convertCodeToStructure(evalString);
|
||||
} catch (e) {
|
||||
return callExpressionNode;
|
||||
}
|
||||
|
||||
const evalRootAstHost: ESTree.FunctionExpression = Nodes.getFunctionExpressionNode(
|
||||
[],
|
||||
Nodes.getBlockStatementNode(<any>ast)
|
||||
);
|
||||
const evalRootAstHostNode: ESTree.FunctionExpression = Nodes
|
||||
.getFunctionExpressionNode([], Nodes.getBlockStatementNode(<any>ast));
|
||||
|
||||
evalRootAstHost.isEvalRoot = true;
|
||||
evalRootAstHostNode.isEvalRoot = true;
|
||||
|
||||
return evalRootAstHost;
|
||||
return evalRootAstHostNode;
|
||||
}
|
||||
}
|
||||
|
||||
+33
-1
@@ -255,7 +255,39 @@ describe('AstToEvalCallExpressionTransformer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('variant #8: integration with control flow flattening', () => {
|
||||
describe('variant #8: template literal inside eval expression', () => {
|
||||
const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6})\)/;
|
||||
const evalExpressionRegExp: RegExp = /eval *\('(_0x(?:[a-f0-9]){4,6});'\);/;
|
||||
|
||||
let functionIdentifierName: string | null,
|
||||
obfuscatedCode: string,
|
||||
variableReferenceIdentifierName: string | null;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/eval-expression-template-literal.js');
|
||||
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}
|
||||
);
|
||||
|
||||
obfuscatedCode = obfuscationResult.getObfuscatedCode();
|
||||
|
||||
functionIdentifierName = getRegExpMatch(obfuscatedCode, functionIdentifierRegExp);
|
||||
variableReferenceIdentifierName = getRegExpMatch(obfuscatedCode, evalExpressionRegExp);
|
||||
});
|
||||
|
||||
it('should obfuscate eval string', () => {
|
||||
assert.match(obfuscatedCode, evalExpressionRegExp);
|
||||
});
|
||||
|
||||
it('should correctly transform function parameter inside eval expression', () => {
|
||||
assert.equal(functionIdentifierName, variableReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('variant #9: integration with control flow flattening', () => {
|
||||
const variableMatch: string = '_0x([a-f0-9]){4,6}';
|
||||
const controlFlowStorageNodeMatch: string = `` +
|
||||
`var *${variableMatch} *= *\\{` +
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
(function(){
|
||||
function foo (bar) {
|
||||
eval(`bar`);
|
||||
}
|
||||
|
||||
foo(1);
|
||||
})();
|
||||
Reference in New Issue
Block a user