From 897e545a676e3604f85af269e446004c0357e932 Mon Sep 17 00:00:00 2001 From: zhangchen Date: Mon, 4 Dec 2023 16:02:47 +0800 Subject: [PATCH] Support obfuscating exported names and properties Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8LMAO Signed-off-by: zhangchen Change-Id: Id1aadd731bcf6fe8abc1121bdfeada21307ba9c5 --- arkguard/package-lock.json | 8 +++ arkguard/package.json | 3 +- arkguard/scripts/execute_result_statistics.js | 47 ++++++++++-- arkguard/src/ArkObfuscator.ts | 2 +- arkguard/src/common/ApiExtractor.ts | 31 +++++--- arkguard/src/common/ApiReader.ts | 43 ++++++----- arkguard/src/common/type.ts | 9 ++- .../src/configs/INameObfuscationOption.ts | 2 +- arkguard/src/configs/IOptions.ts | 3 + .../rename/RenameFileNameTransformer.ts | 40 ++--------- .../rename/RenameIdentifierTransformer.ts | 72 +++++++++++++++---- .../rename/RenamePropertiesTransformer.ts | 4 -- .../rename/ShorthandPropertyTransformer.ts | 3 - arkguard/src/utils/FileUtils.ts | 18 ++++- arkguard/src/utils/NodeUtils.ts | 14 +++- arkguard/src/utils/ScopeAnalyzer.ts | 22 +++++- arkguard/src/utils/TransformUtil.ts | 16 ++++- arkguard/src/utils/TypeUtils.ts | 6 +- .../compact/decoratorAndModifier-expected.txt | 1 - .../compact/decoratorAndModifier_expected.txt | 1 + ...ralsWithTrailingDecimalPoints-expected.txt | 1 - ...ralsWithTrailingDecimalPoints_expected.txt | 1 + .../export_obfuscation_1.ts | 31 ++++++++ .../export_obfuscation_1_expected.txt | 28 ++++++++ .../export_obfuscation_2.ts | 30 ++++++++ .../export_obfuscation_2_expected.txt | 26 +++++++ .../export_obfuscation_3.js | 34 +++++++++ .../export_obfuscation_3_expected.txt | 32 +++++++++ .../export_obfuscation_declaration_1.d.ts | 28 ++++++++ ...ort_obfuscation_declaration_1_expected.txt | 27 +++++++ .../export_obfuscation_declaration_2.d.ets | 30 ++++++++ ...ort_obfuscation_declaration_2_expected.txt | 26 +++++++ .../export_struct_transform_class.ts | 36 ++++++++++ ...export_struct_transform_class_expected.txt | 34 +++++++++ .../import_obfuscation_1.ts | 28 ++++++++ .../import_obfuscation_1_expected.txt | 24 +++++++ .../import_obfuscation_2.ts | 25 +++++++ .../import_obfuscation_2_expected.txt | 20 ++++++ .../grammar/export_obfuscation/obfConfig.json | 21 ++++++ .../oh_modules/export_interface.ts | 24 +++++++ 40 files changed, 744 insertions(+), 107 deletions(-) delete mode 100644 arkguard/test/grammar/compact/decoratorAndModifier-expected.txt create mode 100644 arkguard/test/grammar/compact/decoratorAndModifier_expected.txt delete mode 100644 arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints-expected.txt create mode 100644 arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_1.ts create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_1_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_2.ts create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_2_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_3.js create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_3_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1.d.ts create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2.d.ets create mode 100644 arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/export_struct_transform_class.ts create mode 100644 arkguard/test/grammar/export_obfuscation/export_struct_transform_class_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/import_obfuscation_1.ts create mode 100644 arkguard/test/grammar/export_obfuscation/import_obfuscation_1_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/import_obfuscation_2.ts create mode 100644 arkguard/test/grammar/export_obfuscation/import_obfuscation_2_expected.txt create mode 100644 arkguard/test/grammar/export_obfuscation/obfConfig.json create mode 100644 arkguard/test/grammar/export_obfuscation/oh_modules/export_interface.ts diff --git a/arkguard/package-lock.json b/arkguard/package-lock.json index 1861fe8961..aa554dcef7 100644 --- a/arkguard/package-lock.json +++ b/arkguard/package-lock.json @@ -638,6 +638,14 @@ "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" + }, + "dependencies": { + "diff": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + } } }, "ms": { diff --git a/arkguard/package.json b/arkguard/package.json index 944f9344ae..472905b7e8 100644 --- a/arkguard/package.json +++ b/arkguard/package.json @@ -33,7 +33,8 @@ "@types/node": "18.11.7", "chai": "^4.3.6", "mocha": "^10.0.0", - "ts-node": "^10.9.1" + "ts-node": "^10.9.1", + "diff": "5.0.0" }, "dependencies": { "commander": "^9.3.0", diff --git a/arkguard/scripts/execute_result_statistics.js b/arkguard/scripts/execute_result_statistics.js index d954643c93..455ef20339 100644 --- a/arkguard/scripts/execute_result_statistics.js +++ b/arkguard/scripts/execute_result_statistics.js @@ -15,8 +15,10 @@ const fs = require('fs'); const path = require('path'); +const diff = require('diff'); const { execSync } = require('child_process'); import { Extension } from '../src/common/type'; +import { FileUtils } from '../src/utils/FileUtils'; const testDirectory = path.resolve('./test/local'); @@ -37,20 +39,18 @@ function runTest(filePath) { try { const command = `node ./node_modules/ts-node/dist/bin.js ${filePath}`; execSync(command); - if (compareWithExpected(filePath)) { - return true; - } else { - console.error(`Test case ${filePath} failed: Content does not match`); - return false; - } } catch (error) { console.error(`Test case ${filePath} failed:`, error); return false; } + return true; } let successCount = 0; let failureCount = 0; +let contentcomparationSuccessCount = 0; +let contentcomparationFailureCount = 0; const failedFiles = []; +const contentComparisionFailureFiles = []; function runTestsInDirectory(directoryPath) { const files = fs.readdirSync(directoryPath); @@ -77,6 +77,30 @@ function runTestsInDirectory(directoryPath) { failureCount++; failedFiles.push(filePath); } + compareContent(filePath); + } else if (filePath.endsWith(Extension.DETS) || filePath.endsWith(Extension.DTS)) { + compareContent(filePath); + } + } +} + +function compareContent(filePath) { + const sourcePath = filePath.replace('/test/local/', '/test/grammar/'); + const sourcePathAndExtension = FileUtils.getFileSuffix(sourcePath); + const expectationPath = sourcePathAndExtension.path + '_expected.txt'; + if (fs.existsSync(expectationPath)) { + const actual = fs.readFileSync(filePath).toString(); + const expectation = fs.readFileSync(expectationPath).toString(); + if (actual === expectation) { + contentcomparationSuccessCount++; + } else { + contentcomparationFailureCount++; + contentComparisionFailureFiles.push(filePath); + const differences = diff.diffLines(actual, expectation); + differences.forEach(part => { + const color = part.added ? '\x1b[32m' : part.removed ? '\x1b[31m' : '\x1b[0m'; + console.log(color + part.value + '\x1b[0m'); + }); } } } @@ -87,8 +111,17 @@ console.log('--- Grammar Test Results ---'); console.log(`Success count: ${successCount}`); console.log(`Failure count: ${failureCount}`); if (failureCount > 0) { - console.log('Failed files:'); + console.log('Execution failed files:'); for (const failedFile of failedFiles) { console.log(failedFile); } +} + +console.log(`Content fomparison success count: ${contentcomparationSuccessCount}`); +console.log(`Content fomparison sailure count: ${contentcomparationFailureCount}`); +if (contentcomparationFailureCount > 0) { + console.log('Content comparision failed files:'); + for (const failedFile of contentComparisionFailureFiles) { + console.log(failedFile); + } } \ No newline at end of file diff --git a/arkguard/src/ArkObfuscator.ts b/arkguard/src/ArkObfuscator.ts index ed4795d8c9..1dc113334a 100644 --- a/arkguard/src/ArkObfuscator.ts +++ b/arkguard/src/ArkObfuscator.ts @@ -320,7 +320,7 @@ export class ArkObfuscator { } else { relativePath = sourceFilePath.replace(testCasesRootPath, ''); } - resultPath = path.join(outputDir, relativePath); + resultPath = path.join(this.mCustomProfiles.mOutputDir, relativePath); fs.mkdirSync(path.dirname(resultPath), {recursive: true}); fs.writeFileSync(resultPath, mixedInfo.content); diff --git a/arkguard/src/common/ApiExtractor.ts b/arkguard/src/common/ApiExtractor.ts index c8c9754a69..428eed5a35 100644 --- a/arkguard/src/common/ApiExtractor.ts +++ b/arkguard/src/common/ApiExtractor.ts @@ -53,8 +53,9 @@ import { getObjectProperties, getTypeAliasProperties, } from '../utils/OhsUtil'; -import {scanProjectConfig} from './ApiReader'; -import {stringPropsSet} from '../utils/OhsUtil'; +import { scanProjectConfig } from './ApiReader'; +import { stringPropsSet } from '../utils/OhsUtil'; +import type { IOptions } from '../configs/IOptions'; export namespace ApiExtractor { interface KeywordInfo { @@ -71,6 +72,7 @@ export namespace ApiExtractor { let mCurrentExportNameSet: Set = new Set(); export let mPropertySet: Set = new Set(); + export let mLibExportNameSet: Set = new Set(); /** * filter classes or interfaces with export, default, etc @@ -437,12 +439,11 @@ export namespace ApiExtractor { break; case ApiType.PROJECT_DEPENDS: case ApiType.PROJECT: + mCurrentExportNameSet.clear(); if (fileName.endsWith('.d.ts') || fileName.endsWith('.d.ets')) { forEachChild(sourceFile, visitChildNode); - break; } - mCurrentExportNameSet.clear(); forEachChild(sourceFile, visitProjectExport); forEachChild(sourceFile, visitProjectNode); if (scanProjectConfig.mKeepStringProperty) { @@ -451,6 +452,11 @@ export namespace ApiExtractor { }); stringPropsSet.clear(); } + if (scanProjectConfig.mExportObfuscation) { + mCurrentExportNameSet.forEach((element) => { + mLibExportNameSet.add(element); + }); + } mCurrentExportNameSet.clear(); break; default: @@ -539,7 +545,7 @@ export namespace ApiExtractor { * parse common project or file to extract exported api list * @return reserved api names */ - export function parseCommonProject(projectPath): string[] { + export function parseCommonProject(projectPath: string, customProfiles: IOptions): string[] { mPropertySet.clear(); if (fs.lstatSync(projectPath).isFile()) { @@ -550,7 +556,8 @@ export namespace ApiExtractor { traverseApiFiles(projectPath, ApiType.PROJECT); } - const reservedProperties: string[] = [...mPropertySet]; + const reservedProperties: string[] = customProfiles.mExportObfuscation ? [] : [...mPropertySet]; + mPropertySet.clear(); return reservedProperties; @@ -560,9 +567,9 @@ export namespace ApiExtractor { * parse api of third party libs like libs in node_modules * @param libPath */ - export function parseThirdPartyLibs(libPath): string[] { + export function parseThirdPartyLibs(libPath: string): {reservedProperties: string[]; reservedLibExportNames: string[] | undefined} { mPropertySet.clear(); - + mLibExportNameSet.clear(); if (fs.lstatSync(libPath).isFile()) { if (libPath.endsWith('.ets') || libPath.endsWith('.ts') || libPath.endsWith('.js')) { parseFile(libPath, ApiType.PROJECT_DEPENDS); @@ -573,11 +580,15 @@ export namespace ApiExtractor { traverseApiFiles(path.join(libPath, subPath), ApiType.PROJECT_DEPENDS); } } - + let reservedLibExportNames: string[] = undefined; + if (scanProjectConfig.mExportObfuscation) { + reservedLibExportNames = [...mLibExportNameSet]; + mLibExportNameSet.clear(); + } const reservedProperties: string[] = [...mPropertySet]; mPropertySet.clear(); - return reservedProperties; + return {reservedProperties: reservedProperties, reservedLibExportNames: reservedLibExportNames}; } /** diff --git a/arkguard/src/common/ApiReader.ts b/arkguard/src/common/ApiReader.ts index 3d9aeee44e..26c34bc724 100644 --- a/arkguard/src/common/ApiReader.ts +++ b/arkguard/src/common/ApiReader.ts @@ -19,10 +19,8 @@ import {FileUtils} from '../utils/FileUtils'; import {ApiExtractor} from './ApiExtractor'; import {ListUtil} from '../utils/ListUtil'; import type {IOptions} from '../configs/IOptions'; -import es6Info from '../configs/preset/es6_reserved_properties.json'; - -export const scanProjectConfig: {mKeepStringProperty?: boolean} = {}; +export const scanProjectConfig: {mKeepStringProperty?: boolean, mExportObfuscation?: boolean} = {}; /** * if rename property is not open, api read and extract can be skipped @@ -50,9 +48,10 @@ export function initPlugin(sdkDir: string, outputDir: string): void { * @param customProfiles */ export function needReadApiInfo(customProfiles: IOptions): boolean { - return customProfiles.mNameObfuscation && + return (customProfiles.mNameObfuscation && customProfiles.mNameObfuscation.mEnable && - customProfiles.mNameObfuscation.mRenameProperties; + customProfiles.mNameObfuscation.mRenameProperties) || + customProfiles.mExportObfuscation; } /** @@ -60,23 +59,25 @@ export function needReadApiInfo(customProfiles: IOptions): boolean { * @param projectPaths can be dir or file * @param customProfiles */ -export function readProjectProperties(projectPaths: string[], customProfiles: IOptions, isOHProject?: boolean): string[] { +export function readProjectProperties(projectPaths: string[], customProfiles: IOptions, isOHProject?: boolean): + {projectAndLibsReservedProperties: string[]; libExportNames: string[]} { if (!needReadApiInfo(customProfiles) && !isOHProject) { - return []; + return {projectAndLibsReservedProperties:[], libExportNames: []}; } scanProjectConfig.mKeepStringProperty = customProfiles.mNameObfuscation?.mKeepStringProperty; + scanProjectConfig.mExportObfuscation = customProfiles.mExportObfuscation; for (const projectPath of projectPaths) { if (!fs.existsSync(projectPath)) { console.error(`File ${FileUtils.getFileName(projectPath)} is not found.`); - return []; + return {projectAndLibsReservedProperties:[], libExportNames: []}; } const sourcPath = isOHProject ? path.join(projectPath, 'src', 'main') : projectPath; - const projProperties: string[] = ApiExtractor.parseCommonProject(sourcPath); - const sdkProperties: string[] = readThirdPartyLibProperties(projectPath); - + const projProperties: string[] = ApiExtractor.parseCommonProject(sourcPath, customProfiles); + const libExportNamesAndReservedProps = readThirdPartyLibProperties(projectPath); + const sdkProperties = libExportNamesAndReservedProps?.reservedProperties; // read project code export names customProfiles.mNameObfuscation.mReservedProperties = ListUtil.uniqueMergeList(projProperties, customProfiles.mNameObfuscation.mReservedProperties); @@ -86,12 +87,20 @@ export function readProjectProperties(projectPaths: string[], customProfiles: IO customProfiles.mNameObfuscation.mReservedProperties = ListUtil.uniqueMergeList(sdkProperties, customProfiles.mNameObfuscation.mReservedProperties); } + + if (scanProjectConfig.mExportObfuscation && libExportNamesAndReservedProps?.reservedLibExportNames) { + customProfiles.mNameObfuscation.mReservedNames = ListUtil.uniqueMergeList(libExportNamesAndReservedProps.reservedLibExportNames, + customProfiles.mNameObfuscation.mReservedNames); + } } - return customProfiles.mNameObfuscation.mReservedProperties; + + return { + projectAndLibsReservedProperties: customProfiles.mNameObfuscation.mReservedProperties, + libExportNames: customProfiles.mNameObfuscation.mReservedNames + }; } -function readThirdPartyLibProperties(projectPath: string): string[] { - let reservedProperties: string[] = []; +function readThirdPartyLibProperties(projectPath: string): {reservedProperties: string[]; reservedLibExportNames: string[] | undefined} { if (!fs.lstatSync(projectPath).isDirectory()) { return undefined; @@ -115,9 +124,5 @@ function readThirdPartyLibProperties(projectPath: string): string[] { filePath = path.join(projectPath, 'oh_modules'); } - const properties: string[] = ApiExtractor.parseThirdPartyLibs(filePath); - reservedProperties = [...reservedProperties, ...properties]; - const propertySet: Set = new Set(reservedProperties); - - return Array.from(propertySet); + return ApiExtractor.parseThirdPartyLibs(filePath); } diff --git a/arkguard/src/common/type.ts b/arkguard/src/common/type.ts index 960a83955a..0f1f71b7e8 100644 --- a/arkguard/src/common/type.ts +++ b/arkguard/src/common/type.ts @@ -22,5 +22,12 @@ export const enum Extension { DETS = '.d.ets' } +export interface PathAndExtension { + path: string; + ext: string | undefined; +} + export const supportedRunningExtension: readonly string[] = [Extension.TS, Extension.JS]; -export const supportedDeclarationExtension: readonly string[] = [Extension.DTS, Extension.DETS]; \ No newline at end of file +export const supportedDeclarationExtension: readonly string[] = [Extension.DTS, Extension.DETS]; + +export const fileExtensions: string[] = [Extension.DETS, Extension.ETS, Extension.DTS, Extension.TS, Extension.JS, Extension.JSON]; \ No newline at end of file diff --git a/arkguard/src/configs/INameObfuscationOption.ts b/arkguard/src/configs/INameObfuscationOption.ts index 539b7a0994..d2e0423b6b 100644 --- a/arkguard/src/configs/INameObfuscationOption.ts +++ b/arkguard/src/configs/INameObfuscationOption.ts @@ -23,7 +23,7 @@ export interface INameObfuscationOption { readonly mRenameProperties: boolean; - readonly mReservedNames: string[]; + mReservedNames: string[]; mReservedProperties: string[]; diff --git a/arkguard/src/configs/IOptions.ts b/arkguard/src/configs/IOptions.ts index 3148979eff..0f49047619 100644 --- a/arkguard/src/configs/IOptions.ts +++ b/arkguard/src/configs/IOptions.ts @@ -49,4 +49,7 @@ export interface IOptions { readonly applyReservedNamePath?: string; readonly mRenameFileName?: IFileNameObfuscationOption; + + // Whether to obfuscate the names or properties of the exported content + readonly mExportObfuscation?: boolean; } diff --git a/arkguard/src/transformers/rename/RenameFileNameTransformer.ts b/arkguard/src/transformers/rename/RenameFileNameTransformer.ts index 7e69a42873..1510046451 100644 --- a/arkguard/src/transformers/rename/RenameFileNameTransformer.ts +++ b/arkguard/src/transformers/rename/RenameFileNameTransformer.ts @@ -52,7 +52,9 @@ import type { IFileNameObfuscationOption } from '../../configs/INameObfuscationO import { NameGeneratorType, getNameGenerator } from '../../generator/NameFactory'; import type { INameGenerator, NameGeneratorOptions } from '../../generator/INameGenerator'; import { FileUtils } from '../../utils/FileUtils'; +import { NodeUtils } from '../../utils/NodeUtils'; import { orignalFilePathForSearching } from '../../ArkObfuscator'; +import type { PathAndExtension } from '../../common/type'; namespace secharmony { // global mangled file name table used by all files in a project @@ -91,7 +93,7 @@ namespace secharmony { const directories = FileUtils.splitFilePath(fileNameOrPath); directories.forEach(directory => { tempReservedFileName.push(directory); - const pathOrExtension: PathAndExtension = removeFileSuffix(directory); + const pathOrExtension: PathAndExtension = FileUtils.getFileSuffix(directory); if (pathOrExtension.ext) { tempReservedFileName.push(pathOrExtension.ext); tempReservedFileName.push(pathOrExtension.path); @@ -189,7 +191,7 @@ namespace secharmony { export function getMangleCompletePath(originalCompletePath: string): string { originalCompletePath = toUnixPath(originalCompletePath); - const { path: filePathWithoutSuffix, ext: extension } = removeFileSuffix(originalCompletePath); + const { path: filePathWithoutSuffix, ext: extension } = FileUtils.getFileSuffix(originalCompletePath); const mangleFilePath = manglFileName(filePathWithoutSuffix); return mangleFilePath + extension; } @@ -204,7 +206,7 @@ namespace secharmony { const mangleFilePath = manglFileName(pathAndExtension.path); return mangleFilePath; } else { - const { path: filePathWithoutSuffix, ext: extension } = removeFileSuffix(pathAndExtension.path); + const { path: filePathWithoutSuffix, ext: extension } = FileUtils.getFileSuffix(pathAndExtension.path); const mangleFilePath = manglFileName(filePathWithoutSuffix); return mangleFilePath + extension; } @@ -286,27 +288,10 @@ function tryValidateFileExisting(importPath: string): PathAndExtension | undefin return undefined; } -interface PathAndExtension { - path: string; - ext: string | undefined; -} - -const fileExtensions: string[] = ['.d.ets', '.ets', '.d.ts', '.ts', '.js', '.json']; - -function removeFileSuffix(filePath: string): PathAndExtension { - for (let ext of fileExtensions) { - if (filePath.endsWith(ext)) { - const filePathWithoutSuffix: string = filePath.replace(new RegExp(`${ext}$`), ''); - return { path: filePathWithoutSuffix, ext: ext }; - } - } - return { path: filePath, ext: undefined }; -} - function tryRemoveVirtualConstructor(node: StructDeclaration): StructDeclaration { - const sourceFile = getSourceFileOfNode(node); + const sourceFile = NodeUtils.getSourceFileOfNode(node); const tempStructMembers: ClassElement[] = []; - if (sourceFile && sourceFile.isDeclarationFile && isInETSFile(sourceFile)) { + if (sourceFile && sourceFile.isDeclarationFile && NodeUtils.isInETSFile(sourceFile)) { for (let member of node.members) { // @ts-ignore if (!isConstructorDeclaration(member) || !member.virtual) { @@ -319,17 +304,6 @@ function tryRemoveVirtualConstructor(node: StructDeclaration): StructDeclaration return node; } -function getSourceFileOfNode(node: Node): SourceFile { - while (node && node.kind !== SyntaxKind.SourceFile) { - node = node.parent; - } - return node; -} - -function isInETSFile(node: Node | undefined): boolean { - return !!node && getSourceFileOfNode(node).fileName.endsWith('.ets'); -} - function toUnixPath(data: string): string { if (/^win/.test(require('os').platform())) { const fileTmps: string[] = data.split(path.sep); diff --git a/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts index ab1542457f..dcb507dd9e 100644 --- a/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts +++ b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts @@ -17,17 +17,21 @@ import { factory, forEachChild, isBreakOrContinueStatement, + isConstructorDeclaration, isIdentifier, isLabeledStatement, isSourceFile, + isStructDeclaration, setParentRecursive, visitEachChild, } from 'typescript'; import type { + ClassElement, Identifier, Node, SourceFile, + StructDeclaration, Symbol, TransformationContext, Transformer, @@ -58,7 +62,7 @@ import type {TransformPlugin} from '../TransformPlugin'; import {TransformerOrder} from '../TransformPlugin'; import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory'; import {TypeUtils} from '../../utils/TypeUtils'; -import {collectIdentifiers} from '../../utils/TransformUtil'; +import {collectIdentifiersAndStructs} from '../../utils/TransformUtil'; import {NodeUtils} from '../../utils/NodeUtils'; namespace secharmony { @@ -82,6 +86,7 @@ namespace secharmony { } const openTopLevel: boolean = option?.mTopLevel; + const exportObfuscation: boolean = option?.mExportObfuscation; return renameIdentifierFactory; function renameIdentifierFactory(context: TransformationContext): Transformer { @@ -104,8 +109,10 @@ namespace secharmony { let checker: TypeChecker = undefined; let manager: ScopeManager = createScopeManager(); let shadowIdentifiers: Identifier[] = undefined; + let shadowStructs: StructDeclaration[] = undefined; let identifierIndex: number = 0; + let structIndex: number = 0; return renameTransformer; /** @@ -114,7 +121,7 @@ namespace secharmony { * @param node ast node of a file. */ function renameTransformer(node: Node): Node { - if (!isSourceFile(node) || NodeUtils.isDeclarationFile(node)) { + if (!isSourceFile(node)) { return node; } @@ -122,11 +129,16 @@ namespace secharmony { checker = TypeUtils.createChecker(shadowSourceAst); manager.analyze(shadowSourceAst, checker); - manager.getReservedNames().forEach((name) => { - reservedNames.push(name); - }); + // the reservedNames of manager contain the struct name. + if (!exportObfuscation) { + manager.getReservedNames().forEach((name) => { + reservedNames.push(name); + }); + } // collect all identifiers of shadow sourceFile - shadowIdentifiers = collectIdentifiers(shadowSourceAst, context); + const identifiersAndStructs = collectIdentifiersAndStructs(shadowSourceAst, context); + shadowIdentifiers = identifiersAndStructs.shadowIdentifiers; + shadowStructs = identifiersAndStructs.shadowStructs; if (nameCache === undefined) { nameCache = new Map(); @@ -134,7 +146,9 @@ namespace secharmony { let root: Scope = manager.getRootScope(); renameInScope(root); - return setParentRecursive(visit(node), true); + let ret: Node = visit(node); + ret = tryRemoveVirtualConstructor(ret); + return setParentRecursive(ret, true); } /** @@ -164,13 +178,14 @@ namespace secharmony { return; } - scope.defs.forEach((def) => { - if (scope.importNames.has(def.name)) { - scope.defs.delete(def); - } - }); + if (!exportObfuscation) { + scope.defs.forEach((def) => { + if (scope.importNames.has(def.name)) { + scope.defs.delete(def); + } + }); + } - generator.reset(); renames(scope, scope.defs, generator); } @@ -182,7 +197,7 @@ namespace secharmony { const original: string = def.name; let mangled: string = original; // No allow to rename reserved names. - if (reservedNames.includes(original) || scope.exportNames.has(def.name) || isSkippedGlobal(openTopLevel, scope)) { + if (reservedNames.includes(original) || (!exportObfuscation && scope.exportNames.has(def.name)) || isSkippedGlobal(openTopLevel, scope)) { mangledIdentifierNames.add(mangled); mangledSymbolNames.set(def, mangled); return; @@ -194,7 +209,9 @@ namespace secharmony { const path: string = scope.loc + '#' + original; const historyName: string = historyNameCache?.get(path); - const specifyName: string = historyName ? historyName : nameCache.get(path); + let specifyName: string = historyName ? historyName : nameCache.get(path); + specifyName = specifyName ? specifyName : globalNameCache.get(original); + if (specifyName) { mangled = specifyName; } else { @@ -204,6 +221,7 @@ namespace secharmony { // add new names to name cache nameCache.set(path, mangled); + globalNameCache.set(original, mangled); mangledIdentifierNames.add(mangled); mangledSymbolNames.set(def, mangled); localCache.set(original, mangled); @@ -321,6 +339,29 @@ namespace secharmony { return updateNameNode(node, shadowNode); } + function tryRemoveVirtualConstructor(node: Node): Node { + if (isStructDeclaration(node)) { + const shadowNode: StructDeclaration = shadowStructs[structIndex]; + structIndex++; + const sourceFile = NodeUtils.getSourceFileOfNode(shadowNode); + const tempStructMembers: ClassElement[] = []; + if (sourceFile && sourceFile.isDeclarationFile) { + for (let index = 0; index < node.members.length; index++) { + const member = node.members[index]; + // @ts-ignore + if (isConstructorDeclaration(member) && shadowNode.members[index].virtual) { + continue; + } + tempStructMembers.push(member); + } + const structMembersWithVirtualConstructor = factory.createNodeArray(tempStructMembers); + return factory.updateStructDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, + structMembersWithVirtualConstructor); + } + } + return visitEachChild(node, tryRemoveVirtualConstructor, context); + } + function findNoSymbolIdentifiers(scope: Scope): void { const noSymbolVisit = (targetNode: Node): void => { if (!isIdentifier(targetNode)) { @@ -389,6 +430,7 @@ namespace secharmony { export let nameCache: Map = undefined; export let historyNameCache: Map = undefined; + export let globalNameCache: Map = new Map(); } export = secharmony; \ No newline at end of file diff --git a/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts b/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts index 778338075e..4a37c1b513 100644 --- a/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts +++ b/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts @@ -94,10 +94,6 @@ namespace secharmony { return renamePropertiesTransformer; function renamePropertiesTransformer(node: Node): Node { - if (isSourceFile(node) && NodeUtils.isDeclarationFile(node)) { - return node; - } - collectReservedNames(node); if (globalMangledTable === undefined) { globalMangledTable = new Map(); diff --git a/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts b/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts index 070ea5eb71..66b57dc8de 100644 --- a/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts +++ b/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts @@ -51,9 +51,6 @@ namespace secharmony { return shorthandPropertyTransformer; function shorthandPropertyTransformer(node: Node): Node { - if (isSourceFile(node) && NodeUtils.isDeclarationFile(node)) { - return node; - } return setParentRecursive(transformShortHandProperty(node), true); } diff --git a/arkguard/src/utils/FileUtils.ts b/arkguard/src/utils/FileUtils.ts index aebfc92c01..0f17110203 100644 --- a/arkguard/src/utils/FileUtils.ts +++ b/arkguard/src/utils/FileUtils.ts @@ -13,9 +13,11 @@ * limitations under the License. */ -import {existsSync, readFileSync, writeFileSync} from 'fs'; -import {readJsonSync} from 'fs-extra'; -import type {IOptions} from '../configs/IOptions'; +import { existsSync, readFileSync, writeFileSync } from 'fs'; +import { readJsonSync } from 'fs-extra'; +import type { IOptions } from '../configs/IOptions'; +import { fileExtensions } from '../common/type'; +import type { PathAndExtension } from '../common/type'; export class FileUtils { /** @@ -142,4 +144,14 @@ export class FileUtils { } return false; } + + public static getFileSuffix(filePath: string): PathAndExtension { + for (let ext of fileExtensions) { + if (filePath.endsWith(ext)) { + const filePathWithoutSuffix: string = filePath.replace(new RegExp(`${ext}$`), ''); + return { path: filePathWithoutSuffix, ext: ext }; + } + } + return { path: filePath, ext: undefined }; + } } diff --git a/arkguard/src/utils/NodeUtils.ts b/arkguard/src/utils/NodeUtils.ts index ee63e1ca2d..d3911af8c5 100644 --- a/arkguard/src/utils/NodeUtils.ts +++ b/arkguard/src/utils/NodeUtils.ts @@ -13,9 +13,10 @@ * limitations under the License. */ -import type {Expression, Node, ObjectBindingPattern, SourceFile} from 'typescript'; +import type {ClassElement, Expression, Node, ObjectBindingPattern, SourceFile, StructDeclaration} from 'typescript'; import { SyntaxKind, + factory, getModifiers, isBinaryExpression, isBindingElement, @@ -199,4 +200,15 @@ export class NodeUtils { public static isDeclarationFile(node: SourceFile): boolean { return node.isDeclarationFile; } + + public static getSourceFileOfNode(node: Node): SourceFile { + while (node && node.kind !== SyntaxKind.SourceFile) { + node = node.parent; + } + return node; + } + + public static isInETSFile(node: Node | undefined): boolean { + return !!node && NodeUtils.getSourceFileOfNode(node).fileName.endsWith('.ets'); + } } diff --git a/arkguard/src/utils/ScopeAnalyzer.ts b/arkguard/src/utils/ScopeAnalyzer.ts index 5aec6b812e..c187da60ae 100644 --- a/arkguard/src/utils/ScopeAnalyzer.ts +++ b/arkguard/src/utils/ScopeAnalyzer.ts @@ -18,6 +18,7 @@ import { getModifiers, isClassDeclaration, isConstructorDeclaration, + isExportSpecifier, isFunctionDeclaration, isFunctionLike, isIdentifier, @@ -364,15 +365,24 @@ namespace secharmony { // with export identification, special handling. if (def.exportSymbol) { current.exportNames.add(def.name); + current.addDefinition(def.exportSymbol); } current.addDefinition(def); }); } + function addExportSymbolInScope(node: Node): void { + let defSymbols: Symbol = node?.symbol; + + if (!defSymbols) { + return; + } + current.addDefinition(defSymbols); + } + /** * analyze chain of scopes - * * @param node */ function analyzeScope(node: Node): void { @@ -401,6 +411,7 @@ namespace secharmony { // class like case SyntaxKind.ClassExpression: case SyntaxKind.ClassDeclaration: + case SyntaxKind.StructDeclaration: analyzeClassLike(node as ClassLikeDeclaration); break; @@ -522,6 +533,7 @@ namespace secharmony { function analyzeExportNames(node: ExportSpecifier): void { // get export names. current.exportNames.add(node.name.text); + addExportSymbolInScope(node); forEachChild(node, analyzeScope); } @@ -724,13 +736,17 @@ namespace secharmony { addSymbolInScope(node); // Class members are seen as attribute names, and the reference of external symbols can be renamed as the same node.members?.forEach((elm: ClassElement) => { - if (elm?.symbol) { + // @ts-ignore + if (elm?.symbol && !elm.virtual) { current.addDefinition(elm.symbol); } }); node.members?.forEach((sub: Node) => { - analyzeScope(sub); + // @ts-ignore + if (!sub.virtual) { + analyzeScope(sub); + } }); } catch (e) { console.error(e); diff --git a/arkguard/src/utils/TransformUtil.ts b/arkguard/src/utils/TransformUtil.ts index c951f5f1f1..2698a770fc 100644 --- a/arkguard/src/utils/TransformUtil.ts +++ b/arkguard/src/utils/TransformUtil.ts @@ -19,6 +19,7 @@ import { isCallExpression, isExpressionStatement, isIdentifier, + isStructDeclaration, SyntaxKind, visitEachChild } from 'typescript'; @@ -28,6 +29,7 @@ import type { Identifier, Node, SourceFile, + StructDeclaration, TransformationContext } from 'typescript'; @@ -50,15 +52,25 @@ export function collectExistNames(sourceFile: SourceFile): Set { return identifiers; } +type IdentifiersAndStructs = {shadowIdentifiers: Identifier[], shadowStructs: StructDeclaration[]}; + /** * collect exist identifiers in current source file * @param sourceFile * @param context */ -export function collectIdentifiers(sourceFile: SourceFile, context: TransformationContext): Identifier[] { +export function collectIdentifiersAndStructs(sourceFile: SourceFile, context: TransformationContext): IdentifiersAndStructs { const identifiers: Identifier[] = []; + const structs: StructDeclaration[] = []; let visit = (node: Node): Node => { + if (isStructDeclaration(node)) { + structs.push(node); + } + // @ts-ignore + if (node.virtual) { + return node; + } if (!isIdentifier(node) || !node.parent) { return visitEachChild(node, visit, context); } @@ -68,7 +80,7 @@ export function collectIdentifiers(sourceFile: SourceFile, context: Transformati }; visit(sourceFile); - return identifiers; + return {shadowIdentifiers: identifiers, shadowStructs: structs}; } export enum OhPackType { diff --git a/arkguard/src/utils/TypeUtils.ts b/arkguard/src/utils/TypeUtils.ts index eb47772956..81b1fc8dfc 100644 --- a/arkguard/src/utils/TypeUtils.ts +++ b/arkguard/src/utils/TypeUtils.ts @@ -31,6 +31,9 @@ import type { } from 'typescript'; import path from 'path'; +import { Extension } from '../common/type'; +import type { PathAndExtension } from '../common/type'; +import { FileUtils } from './FileUtils'; export class TypeUtils { /** @@ -42,7 +45,8 @@ export class TypeUtils { let printer: Printer = createPrinter(); let content: string = printer.printFile(oldAst); - const fileSuffix: string = '.ts'; + const pathOrExtension: PathAndExtension = FileUtils.getFileSuffix(oldAst.fileName); + const fileSuffix = pathOrExtension.ext === Extension.DETS ? Extension.DETS : Extension.TS; const { dir, name } = path.parse(oldAst.fileName); const targetName: string = path.join(dir, name) + '__tmp' + fileSuffix; return createSourceFile(targetName, content, ScriptTarget.ES2015, true); diff --git a/arkguard/test/grammar/compact/decoratorAndModifier-expected.txt b/arkguard/test/grammar/compact/decoratorAndModifier-expected.txt deleted file mode 100644 index 91837d05e5..0000000000 --- a/arkguard/test/grammar/compact/decoratorAndModifier-expected.txt +++ /dev/null @@ -1 +0,0 @@ -function a(f: Function) { console.log(`Class name: ${f.name}`); } function b(f: any, g: string) { console.log(`Property name: ${g}`); } function c(f: any, g: string) { console.log(`Property name: ${g}`); } @a class e { @b @c private g: string; @c @b public h: number; @b async i(): Promise { } } function d() { let f = 1; let g = 2; let h = 3; let i = 4; let j = 5; } \ No newline at end of file diff --git a/arkguard/test/grammar/compact/decoratorAndModifier_expected.txt b/arkguard/test/grammar/compact/decoratorAndModifier_expected.txt new file mode 100644 index 0000000000..c1e17c3db5 --- /dev/null +++ b/arkguard/test/grammar/compact/decoratorAndModifier_expected.txt @@ -0,0 +1 @@ + function a(f: Function) { console.log(`Class name: ${f.name}`); } function b(g: any, h: string) { console.log(`Property name: ${h}`); } function c(g: any, h: string) { console.log(`Property name: ${h}`); } @a class e { @b @c private g: string; @c @b public h: number; @b async i(): Promise { } } function d() { let i = 1; let j = 2; let k = 3; let l = 4; let m = 5; } \ No newline at end of file diff --git a/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints-expected.txt b/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints-expected.txt deleted file mode 100644 index 917324371e..0000000000 --- a/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints-expected.txt +++ /dev/null @@ -1 +0,0 @@ -1..toString(); 1.0.toString(); 1. + 2.0 + 3.; var a: number = 1; var b = a.toString(); var c = 3..toString(); var d = 3..toString(); var e = 3..toString(); var f = 3.['toString'](); var g = 3 .toString(); var h = new Number(4).toString(); var i = 3. + 3.; var j = 0 .toString(); var k = 3. .toString(); var l = 3 .toString(); var m = 3 .toString(); var n = 3 .toString(); var o = 3. .toString(); var p = 3 .toString(); var q = 3. .toString(); var r = 3 .toString(); var s = 3. .toString(); \ No newline at end of file diff --git a/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints_expected.txt b/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints_expected.txt new file mode 100644 index 0000000000..711dbb2bd6 --- /dev/null +++ b/arkguard/test/grammar/compact/numericLiteralsWithTrailingDecimalPoints_expected.txt @@ -0,0 +1 @@ + 1..toString(); 1.0.toString(); 1. + 2.0 + 3.; var n: number = 1; var o = n.toString(); var p = 3..toString(); var q = 3..toString(); var r = 3..toString(); var s = 3.['toString'](); var t = 3 .toString(); var u = new Number(4).toString(); var v = 3. + 3.; var w = 0 .toString(); var x = 3. .toString(); var y = 3 .toString(); var z = 3 .toString(); var a1 = 3 .toString(); var b1 = 3. .toString(); var c1 = 3 .toString(); var d1 = 3. .toString(); var e1 = 3 .toString(); var f1 = 3. .toString(); \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_1.ts b/arkguard/test/grammar/export_obfuscation/export_obfuscation_1.ts new file mode 100644 index 0000000000..3fa18df6a0 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_1.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class PersonClass01 { + name:string; + age:number; +} + +export function foo01(para01: number, para02: number) { + const v1 = 1; + const v2 = 2; + return para01 + para02 + v1 + v2; +} + +function foo02(para03: string, para04: number){ + const v1 = 4; + const v2 = 5; + return para03 + para04.toString(); +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_1_expected.txt b/arkguard/test/grammar/export_obfuscation/export_obfuscation_1_expected.txt new file mode 100644 index 0000000000..4ea80a7e5f --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_1_expected.txt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class c { + name: string; + g: number; +} +export function a(d: number, e: number) { + const f = 1; + const g = 2; + return d + e + f + g; +} +function b(h: string, i: number) { + const f = 4; + const g = 5; + return h + i.toString(); +} diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_2.ts b/arkguard/test/grammar/export_obfuscation/export_obfuscation_2.ts new file mode 100644 index 0000000000..6edf3b3722 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_2.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Human01 { + gender01: string; + color01: string; + country01: string; +} + +export const value01: number = 100; + +interface Human02 { + gender02: string; + color02: string; + country02: string; +} + +const value02: number = 200; \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_2_expected.txt b/arkguard/test/grammar/export_obfuscation/export_obfuscation_2_expected.txt new file mode 100644 index 0000000000..eb08f36dca --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_2_expected.txt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface j { + h: string; + i: string; + j: string; +} +export const k: number = 100; +interface l { + k: string; + l: string; + m: string; +} +const m: number = 200; diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_3.js b/arkguard/test/grammar/export_obfuscation/export_obfuscation_3.js new file mode 100644 index 0000000000..dad8a2bf9e --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_3.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class SortMethod { + constructor() { + this.head = false; + } + compare(leftIndex, rightIndex) { + if (!this.head) { + throw new Error('List is empty'); + } + return leftIndex > rightIndex; + } + swap(leftIndex, rightIndex) { + const leftHand = rightIndex; + rightIndex = leftIndex; + } +} + +function plus01(n1, n2) { + return n1 + n2; +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_3_expected.txt b/arkguard/test/grammar/export_obfuscation/export_obfuscation_3_expected.txt new file mode 100644 index 0000000000..200530a7a4 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_3_expected.txt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class o { + constructor() { + this.head = false; + } + compare(p, q) { + if (!this.head) { + throw new Error('List is empty'); + } + return p > q; + } + o(p, q) { + const r = q; + q = p; + } +} +function n(s, t) { + return s + t; +} diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1.d.ts b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1.d.ts new file mode 100644 index 0000000000..641400322b --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1.d.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export declare class PersonClass01 { + name01: string | undefined; + age01: number; + addr01: string; + constructor(namePara?: PersonClass02); +} +export declare function foo01(para1: number, para2: number): number; +declare class PersonClass02 { + name02: string; + age02: number; + addr02: string; +} +export {}; \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1_expected.txt b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1_expected.txt new file mode 100644 index 0000000000..0b4b1c76f7 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_1_expected.txt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export declare class c { + p: string | undefined; + q: number; + t: string; + constructor(v?: u); +} +export declare function a(w: number, x: number): number; +declare class u { + u: string; + v: number; + a1: string; +} +export {}; diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2.d.ets b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2.d.ets new file mode 100644 index 0000000000..e1d350042e --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2.d.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export declare struct IndexUI1 { + param1: string; + message1: string; + method1(): void; +} + +export declare function foo01(para3, para4); + +export declare const value04; + +export declare struct IndexUI2 { + param2: string; + message2: string; + method2(): void; +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2_expected.txt b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2_expected.txt new file mode 100644 index 0000000000..0ca9d97f65 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_obfuscation_declaration_2_expected.txt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export declare struct y { + b1: string; + c1: string; + d1(): void; +} +export declare function a(c1, d1); +export declare const z; +export declare struct a1 { + e1: string; + f1: string; + g1(): void; +} diff --git a/arkguard/test/grammar/export_obfuscation/export_struct_transform_class.ts b/arkguard/test/grammar/export_obfuscation/export_struct_transform_class.ts new file mode 100644 index 0000000000..69fe833f71 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_struct_transform_class.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class ViewPU { + +} + +export class Retransmission1 extends ViewPU { + constructor() { + super(); + } + scroller1: string; + controller1: number; + callMethod1(): void {}; +} + +class Retransmission2 extends ViewPU { + constructor() { + super(); + } + scroller2: string; + controller2: number; + callMethod2(): void {}; +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/export_struct_transform_class_expected.txt b/arkguard/test/grammar/export_obfuscation/export_struct_transform_class_expected.txt new file mode 100644 index 0000000000..6f1fb18f01 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/export_struct_transform_class_expected.txt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class e1 { +} +export class f1 extends e1 { + constructor() { + super(); + } + scroller1: string; + controller1: number; + callMethod1(): void { } + ; +} +class g1 extends e1 { + constructor() { + super(); + } + scroller2: string; + controller2: number; + callMethod2(): void { } + ; +} diff --git a/arkguard/test/grammar/export_obfuscation/import_obfuscation_1.ts b/arkguard/test/grammar/export_obfuscation/import_obfuscation_1.ts new file mode 100644 index 0000000000..af9907e2b1 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/import_obfuscation_1.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PersonClass01, foo01 } from './export_obfuscation_1'; + +let instance01 = new PersonClass01(); +const getedName: string = instance01.name +foo01(1, 2); + +export function actionBarProp1(): void { + return; +} + +export function actionBarProp2():void { + return; +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/import_obfuscation_1_expected.txt b/arkguard/test/grammar/export_obfuscation/import_obfuscation_1_expected.txt new file mode 100644 index 0000000000..28e450daa4 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/import_obfuscation_1_expected.txt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { c, a } from './export_obfuscation_1'; +let j1 = new c(); +const k1: string = j1.name; +a(1, 2); +export function h1(): void { + return; +} +export function i1(): void { + return; +} diff --git a/arkguard/test/grammar/export_obfuscation/import_obfuscation_2.ts b/arkguard/test/grammar/export_obfuscation/import_obfuscation_2.ts new file mode 100644 index 0000000000..f9ddce93ee --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/import_obfuscation_2.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Human01, value01} from './export_obfuscation_2'; + +type alis01 = Human01; +let newValue = value01 + 1; + + +export { actionBarProp1, actionBarProp2 } from './import_obfuscation_1'; + +function publicFoo1(): void{} +function publicFoo2(): void{} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/import_obfuscation_2_expected.txt b/arkguard/test/grammar/export_obfuscation/import_obfuscation_2_expected.txt new file mode 100644 index 0000000000..f69bdd1ed7 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/import_obfuscation_2_expected.txt @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { j, k } from './export_obfuscation_2'; +type l1 = j; +let m1 = k + 1; +export { h1, i1 } from './import_obfuscation_1'; +function publicFoo1(): void { } +function publicFoo2(): void { } diff --git a/arkguard/test/grammar/export_obfuscation/obfConfig.json b/arkguard/test/grammar/export_obfuscation/obfConfig.json new file mode 100644 index 0000000000..12cc599e72 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/obfConfig.json @@ -0,0 +1,21 @@ +{ + "mCompact": false, + "mRemoveComments": false, + "mOutputDir": "../../local", + "mDisableHilog": false, + "mDisableConsole": false, + "mSimplify": false, + "mNameObfuscation": { + "mEnable": true, + "mNameGeneratorType": 1, + "mDictionaryList": [], + "mReservedNames": [], + "mRenameProperties": true, + "mReservedProperties": [], + "mKeepStringProperty": false + }, + "mEnableSourceMap": false, + "mEnableNameCache": true, + "mTopLevel": true, + "mExportObfuscation": true +} \ No newline at end of file diff --git a/arkguard/test/grammar/export_obfuscation/oh_modules/export_interface.ts b/arkguard/test/grammar/export_obfuscation/oh_modules/export_interface.ts new file mode 100644 index 0000000000..a07fdc98b5 --- /dev/null +++ b/arkguard/test/grammar/export_obfuscation/oh_modules/export_interface.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function publicFoo1(): void { + return; +} + +function publicFoo2(): void { + return; +} + +export {publicFoo2}; \ No newline at end of file -- Gitee