123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import { inject, injectable, postConstruct } from 'inversify';
- import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
- import * as ESTree from 'estree';
- import { IInitializable } from '../../../../interfaces/IInitializable';
- import { IOptions } from '../../../../interfaces/options/IOptions';
- import { IStringArrayStorage } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorage';
- import { IStringArrayStorageAnalyzer } from '../../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
- import { IStringArrayStorageItemData } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
- import { initializable } from '../../../../decorators/Initializable';
- import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
- import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
- import { NodeMetadata } from '../../../../node/NodeMetadata';
- import { NodeFactory } from '../../../../node/NodeFactory';
- import { NumberUtils } from '../../../../utils/NumberUtils';
- import { Utils } from '../../../../utils/Utils';
- @injectable()
- export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer implements IInitializable {
- /**
- * @type {Map<string, ESTree.Node>}
- */
- private readonly nodesCache: Map <string, ESTree.Node> = new Map();
- /**
- * @type {IStringArrayStorage}
- */
- private readonly stringArrayStorage: IStringArrayStorage;
- /**
- * @type {IStringArrayStorageAnalyzer}
- */
- private readonly stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer;
- /**
- * @type {string}
- */
- @initializable()
- private stringArrayStorageCallsWrapperName!: string;
- /**
- * @param {IStringArrayStorage} stringArrayStorage
- * @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
- * @param {IOptions} options
- */
- public constructor (
- @inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
- @inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
- @inject(ServiceIdentifiers.IOptions) options: IOptions
- ) {
- super(options);
- this.stringArrayStorage = stringArrayStorage;
- this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
- }
- /**
- * @param {string} hexadecimalIndex
- * @returns {Literal}
- */
- private static getHexadecimalLiteralNode (hexadecimalIndex: string): ESTree.Literal {
- const hexadecimalLiteralNode: ESTree.Literal = NodeFactory.literalNode(hexadecimalIndex);
- NodeMetadata.set(hexadecimalLiteralNode, { replacedLiteral: true });
- return hexadecimalLiteralNode;
- }
- /**
- * @param {string} literalValue
- * @returns {Literal}
- */
- private static getRc4KeyLiteralNode (literalValue: string): ESTree.Literal {
- const rc4KeyLiteralNode: ESTree.Literal = NodeFactory.literalNode(literalValue);
- NodeMetadata.set(rc4KeyLiteralNode, { replacedLiteral: true });
- return rc4KeyLiteralNode;
- }
- @postConstruct()
- public initialize (): void {
- this.stringArrayStorageCallsWrapperName = this.stringArrayStorage.getStorageCallsWrapperName();
- if (this.options.shuffleStringArray) {
- this.stringArrayStorage.shuffleStorage();
- }
- if (this.options.rotateStringArray) {
- this.stringArrayStorage.rotateStorage();
- }
- }
- /**
- * @param {SimpleLiteral} literalNode
- * @returns {Node}
- */
- public replace (literalNode: ESTree.SimpleLiteral): ESTree.Node {
- const literalValue: ESTree.SimpleLiteral['value'] = literalNode.value;
- if (typeof literalValue !== 'string') {
- throw new Error('`StringLiteralObfuscatingReplacer` should accept only literals with `string` value');
- }
- const stringArrayStorageItemData: IStringArrayStorageItemData | undefined = this.stringArrayStorageAnalyzer
- .getItemDataForLiteralNode(literalNode);
- const cacheKey: string = `${literalValue}-${Boolean(stringArrayStorageItemData)}`;
- const useCachedValue: boolean = this.nodesCache.has(cacheKey) && this.options.stringArrayEncoding !== StringArrayEncoding.Rc4;
- if (useCachedValue) {
- return <ESTree.Node>this.nodesCache.get(cacheKey);
- }
- const resultNode: ESTree.Node = stringArrayStorageItemData
- ? this.replaceWithStringArrayCallNode(stringArrayStorageItemData)
- : this.replaceWithLiteralNode(literalValue);
- this.nodesCache.set(cacheKey, resultNode);
- return resultNode;
- }
- /**
- * @param {string} value
- * @returns {Node}
- */
- private replaceWithLiteralNode (value: string): ESTree.Node {
- return NodeFactory.literalNode(value);
- }
- /**
- * @param {IStringArrayStorageItemData} stringArrayStorageItemData
- * @returns {Node}
- */
- private replaceWithStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Node {
- const { index, decodeKey } = stringArrayStorageItemData;
- const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${NumberUtils.toHex(index)}`;
- const callExpressionArgs: (ESTree.Expression | ESTree.SpreadElement)[] = [
- StringLiteralObfuscatingReplacer.getHexadecimalLiteralNode(hexadecimalIndex)
- ];
- if (decodeKey) {
- callExpressionArgs.push(StringLiteralObfuscatingReplacer.getRc4KeyLiteralNode(decodeKey));
- }
- const stringArrayIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(this.stringArrayStorageCallsWrapperName);
- return NodeFactory.callExpressionNode(
- stringArrayIdentifierNode,
- callExpressionArgs
- );
- }
- }
|