目录

Using ArkGuard for Bytecode Obfuscation

To prevent subsequent code modifications from affecting production issue analysis and troubleshooting, you are advised to back up all files in the build/default/cache/default/default@XXXCompileArkTS/esmodule/release/obfuscation directory locally. If possible, you can directly back up the entire release directory.

Enabling Bytecode Obfuscation

[h2]Constraints

Bytecode obfuscation and source code obfuscation cannot be enabled at the same time. After bytecode obfuscation is enabled, source code obfuscation is automatically disabled.

[h2]How to Use

Since API version 20, the bytecode obfuscation capability has been integrated into the system. You can enable it in DevEco Studio as follows:

[h2]Obfuscation Configuration Files

The following table summarizes the differences between these configuration files.

Configuration File Configuration Type Modifiable Affects Obfuscation of This Module Affects Obfuscation of Other Modules
obfuscation-rules.txt Customizable Yes Yes No
consumer-rules.txt Customizable Yes No Yes
obfuscation.txt Compilation product Not applicable (automatically generated during HAR or HSP compilation) Not applicable Yes

[h2]Obfuscation Configuration Guidelines

  1. When -enable-toplevel-obfuscation is configured, access to global variables using globalThis fails. To rectify the fault, use -keep-global-name to retain the global variable name.

  2. After the preceding option is enabled, configure -enable-property-obfuscation.

    1. If the code statically defines properties but dynamically accesses them (or vice versa), use -keep-property-name to retain the property names. Example:

      // file.ts
      // Static definition, dynamic access: The property name is static during object definition, but is accessed by dynamically constructing the property name (usually using string concatenation).
      const obj001 = {
        staticName: 5  // Static definition
      };
      const fieldName = 'static' + 'Name';  // Dynamic construction of the property name
      console.info(obj001[fieldName]);  // Use square bracket notation to dynamically access the property.
      // file.ts
      // Dynamic definition, static access: The property name is determined during object definition through a dynamic expression, but is statically accessed using dot notation (assuming that you know the result of the property name).
      const obj002 = {
        ['dynamic' + 'Name']: 5  // Dynamic definition
      };
      console.info(obj002.dynamicName + '');// Use dot notation to statically access the property.
    2. If the code uses dot notation to access fields not defined in ArkTS/TS/JS code (for example, native so libraries, fixed JSON files, or database fields):

      1. For API calls to so libraries (for example, import testNapi from 'library.so' and testNapi.foo()), use -keep-property-name to retain the property name foo.
      2. For fields in JSON files, use -keep-property-name to retain the JSON field names.
      3. For database-related fields, use -keep-property-name to retain the database field names.
    3. When building a HAR module for use by other modules, use -keep-property-name in the consumer-rules.txt file of the HAR module to retain properties that should not be re-obfuscated. The consumer-rules.txt file generates the obfuscation.txt file during HAR compilation. When the HAR module is depended upon by other modules, DevEco Studio parses the obfuscation.txt file to read the trustlist.

    4. Verify application functionality and identify any missed scenarios. If the application functionality is abnormal, find the code of the error line in the corresponding intermediate products based on the obfuscated error stack, identify the necessary trustlist configurations, and use -keep-property-name to retain them.

  3. After the preceding adaptations are successful, configure -enable-export-obfuscation, and perform adaptation in the following scenarios:

    1. For HSP modules that provide interfaces and properties to other modules, use -keep-global-name to retain the interface names and -keep-property-name to retain the property names in exposed classes/interfaces.
    2. When building HAR modules for use by other modules, use -keep-global-name to retain interface names and -keep-property-name to retain the property names in exposed classes/interfaces in the obfuscation-rules.txt file.
    3. For API calls to so libraries (for example, import { napiA } from 'library.so'), use -keep-global-name to retain the so interface name napiA.
    4. Verify application functionality and interface call functionality when the module is depended upon, and identify any missed scenarios. If the application functionality is abnormal, find the code of the error line in the corresponding intermediate products based on the obfuscated error stack, identify the necessary trustlist configurations, and retain them.
  4. After the preceding adaptations are successful, configure -enable-filename-obfuscation, and perform adaptation in the following scenarios:

    1. If the code contains dynamic import statements (for example, const path = './filePath'; import (path)), use -keep-file-name to retain the file path.
    2. If the application has a routerMap configuration that describes routing information, use -keep-file-name to retain the page's source file path, which is specified by pageSourceFile field in the routing information.
    3. If the code uses ohmUrl for page navigation (for example, router.pushUrl({url: '@bundle:com.example.routerPage/Library/Index'})), use -keep-file-name to retain the path.
    4. Verify application functionality and identify any missed scenarios. If the application function is abnormal and the error stack contains obfuscated paths, you can query the original path in the build/default/[...]/release/obfuscation/nameCache.json file within the module and then locate the source code file. You can also use the hstack plugin to trigger automatic deobfuscation of error stacks. After locating the paths to retain, use -keep-file-name to retain them.

Remarks

Viewing Obfuscation Effects

After obfuscation is complete, intermediate products are generated. You can find the obfuscated intermediate products in the build directory of the compilation output, as well as the name mapping file and system API trustlist files.

Deobfuscating Error Stacks

In applications that have undergone obfuscation, code names are changed, making the error stacks printed during crashes harder to understand because they do not match the source code exactly. You can use the hstack plugin in Command Line Tools of DevEco Studio to deobfuscate the source code stack and analyze issues.

The deobfuscation tool requires the sourceMaps.json file and the obfuscation name mapping file nameCache.json generated during compilation. Be sure to back them up locally. Back up the release directory for fault locating and analysis.