混淆 Dart 代码
如何从 Dart 二进制文件中移除函数和类名称。
什么是代码混淆?
#代码混淆 是修改应用二进制文件以使其难以被人理解的过程。混淆会隐藏编译后的 Dart 代码中的函数和类名,用其他符号替换每个符号,从而使攻击者难以对你的专属应用进行逆向工程。
局限性与警告
#Flutter 的代码混淆仅适用于 发布构建 (release build)。
代码混淆不会加密资源,也不能防止逆向工程。它只是用更晦涩的名称重命名了符号。
Web 应用不支持混淆。Web 应用可以进行压缩 (minification),这能达到类似的效果。当你构建 Flutter Web 应用的发布版本时,Web 编译器会自动压缩应用。欲了解更多信息,请参阅 构建并发布 Web 应用。
支持的目标平台
#以下构建目标支持本页面介绍的混淆过程:
aarapkappbundleiosios-frameworkipalinuxmacosmacos-frameworkwindows
有关特定构建目标可用命令行选项的详细信息,请运行以下命令。输出中应列出 --obfuscate 和 --split-debug-info 选项。如果没有显示,你需要安装较新版本的 Flutter 才能混淆代码。
flutter build <build-target> -h
-
<build-target>:构建目标。例如apk。
混淆你的应用
#要混淆应用并创建符号映射表,请在发布模式下使用 flutter build 命令,并带上 --obfuscate 和 --split-debug-info 选项。如果你将来需要调试混淆后的应用,则必须保留该符号映射表。
-
运行以下命令以混淆你的应用并生成符号 (SYMBOLS) 文件:
flutter build <build-target> \ --obfuscate \ --split-debug-info=/<symbols-directory>-
<build-target>:构建目标。例如apk。 -
<symbols-directory>:存放符号文件的目录。例如out/android。
-
-
一旦混淆了二进制文件,请备份符号文件。如果你丢失了原始的符号文件,又想对堆栈跟踪进行反混淆,你将会需要它。
解读混淆后的堆栈跟踪
#要调试由混淆后的应用生成的堆栈跟踪,请按照以下步骤将其转换为可读格式:
-
找到匹配的符号文件。例如,来自 Android arm64 设备的崩溃日志需要使用
app.android-arm64.symbols。 -
将堆栈跟踪文件(存储在文件中)和符号文件一同提供给
flutter symbolize命令。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>:存放符号的目录。例如out/android -
<obfuscation-map-file>:应放置 JSON 混淆映射的文件路径。例如out/android/map.json
注意事项
#在编写最终会成为混淆二进制文件的应用时,请注意以下事项:
-
依赖匹配特定类名、函数名或库名的代码将会失败。例如,以下对
expect()的调用在混淆后的二进制文件中将无法工作:dartexpect(foo.runtimeType.toString(), equals('Foo')); 枚举 (Enum) 名称目前不会被混淆。