混淆 Dart 代码
什么是代码混淆?
#代码混淆 是一种将应用程序二进制文件转换为功能上等价,但人类难于阅读和理解的行为。在编译 Dart 代码时,混淆会隐藏函数和类的名称,并用其他符号替代每个符号,从而使攻击者难以进行逆向工程。
局限性和警告
#Flutter 的代码混淆功能仅在 生产构建 上生效。
混淆你的代码并 不会 加密资源,也不能防止逆向工程。它只是用更晦涩的名称重命名这些符号。
Web 应用不支持混淆。但 Web 应用支持 代码压缩,这提供了类似的效果。在构建 Flutter Web 应用的发布 (release) 版本时, Web 编译器会对应用进行代码压缩。请参阅 构建和发布为 Web 应用,来了解更多信息。
支持的构建目标
#以下构建目标支持本篇介绍的混淆过程:
aar
apk
appbundle
ios
ios-framework
ipa
linux
macos
macos-framework
windows
构建目标可以使用命令行选项来了解更详细的信息,请运行以下命令。输出的命令行帮助信息应该会列出 --obfuscate
和 --split-debug-info
选项。如果没有这些选项,你需要安装最新版本的 Flutter 来混淆代码。
flutter build <build-target> -h
-
<build-target>
:构建目标,例如apk
。
混淆你的应用
#要混淆你的应用并创建符号表 (symbol),请在 release 模式下使用 flutter build
命令以及
--obfuscate
和 --split-debug-info
选项。在以后需要调试经过混淆处理的应用的时候,就需要符号表 (symbol)。
-
运行以下命令来混淆应用并生成 SYMBOLS 文件:
flutter build <build-target> \ --obfuscate \ --split-debug-info=/<symbols-directory>
-
<build-target>
:构建目标,例如apk
。 -
<symbols-directory>
:存放 SYMBOLS 文件的目录。例如,out/android
。
-
-
混淆二进制文件后,请 备份符号表 SYMBOLS 文件。这是为了避免你丢失原始 SYMBOLS 文件,而你又想解析混淆后的堆栈跟踪,这个时候你就需要使用备份的 SYMBOLS 文件。
如果输出中没有列出这些标志,请运行 flutter --version
命令,检查你的 Flutter 版本。
读取混淆的堆栈跟踪
#如果你需要调试被混淆的应用程序创建的堆栈跟踪,请遵循以下步骤将其解析为人类可读的内容:
-
找到与应用程序匹配的 SYMBOLS 符号文件。例如,在 Android arm64 设备崩溃时,需要
app.android-arm64.symbols
文件。 -
向
flutter symbolize
命令提供堆栈跟踪(存储在文件中)和 SYMBOLS 符号文件。例如:flutter symbolize \ -i <stack-trace-file> \ -d <obfuscated-symbols-file>
-
<stack-trace-file>
:堆栈跟踪的文件路径。例如,???
。 -
<obfuscated-symbols-file>
:包含混淆符号的符号表文件路径。例如,out/android/app.android-arm64.symbols
。
关于
symbolize
命令的更多信息,请运行flutter symbolize -h
命令。 -
读取混淆的名称
#你可以生成一个包含混淆表的 JSON 文件。混淆表是一个 JSON 数组,包含成对的原始名称和混淆名称。例如,["MaterialApp", "ex", "Scaffold", "ey"]
中的 ex
是 MaterialApp
的混淆名称。
你可以使用以下命令,来生成混淆表:
flutter build <build-target> \
--obfuscate \
--split-debug-info=/<symbols-directory> \
--extra-gen-snapshot-options=--save-obfuscation-map=/<obfuscation-map-file>
-
<build-target>
:构建目标。例如,apk
。 -
<symbols-directory>
:存放 SYMBOLS 符号的目录。例如,out/android
。 -
<obfuscation-map-file>
:存放 JSON 混淆表的目录。例如,out/android/map.json
。
注意事项
#当你打算将二进制的应用程序进行混淆时,需要注意以下内容:
-
使用匹配特定的类、函数或库名的代码将会失效。例如,以下在混淆的二进制文件中对
expect()
的调用就不会工作:dartexpect(foo.runtimeType.toString(), equals('Foo'));
-
目前,枚举 (Enum) 名称未被混淆。
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2025-02-13。 查看文档源码 或者 为本页面内容提出建议。