How to obfuscate Flutter apps?
Asked Answered
S

8

39

Flutter's wiki mentions obfuscation is an opt-in in release mode.
And yet, the flutter build command has no relevant option - see:
flutter help -v build apk

Am I missing something here?
Did they make obfuscation the default?
Is obfuscation even relevant for flutter?

Any pointers on this would be very appreciated.

Scab answered 26/5, 2018 at 12:28 Comment(10)
Why do you think you need obfuscatiin anyway? Dart is compiled to binary code.Kayseri
@GünterZöchbauer Does this assure me no variable/method/type names are exposed? And that my code is hard enough to reverse-compile? I come from a C# background, excuse my ignorance...Scab
I asked mraleph about why they added the obfuscation funtionality and he mentioned that some things might be recoverable - don't remember details. I'll try to find the disvussion.Kayseri
I haven't found the discussion yet but github.com/dart-lang/sdk/issues/30524 might provide some hints.Kayseri
This was it gitter.im/dart-lang/TALK-general?at=5ab28157bb1018b37a0d549eKayseri
@GünterZöchbauer OK, in gitter mraleph explains there are still function names by default, and that there's support for aot obfuscation. Where's the flag to enable obfuscation? There's no documentation in flutter help -v build aot...Scab
The GitHub issue 30524 mentions some flags.Kayseri
@GünterZöchbauer 30524 talks about Dart. I see no mention of the flutter build command.Scab
@GünterZöchbauer sir do you have any link to your resource that saying the dart is directly compiled to binary code?Jamijamie
flutter.io/docs/resources/…Kayseri
S
33

Obfuscation is needed - a flutter app knows its function names, which can be shown using Dart's StackTrace class. There's under-tested support for obfuscation. To enable it:


For Android:
Add to the file [ProjectRoot]/android/gradle.properties :

extra-gen-snapshot-options=--obfuscate

For iOS:
First, edit [FlutterRoot]/packages/flutter_tools/bin/xcode_backend.sh:
Locate the build aot call, and add a flag to it,

${extra_gen_snapshot_options_or_none}

defined as:

local extra_gen_snapshot_options_or_none=""
if [[ -n "$EXTRA_GEN_SNAPSHOT_OPTIONS" ]]; then
  extra_gen_snapshot_options_or_none="--extra-gen-snapshot-options=$EXTRA_GEN_SNAPSHOT_OPTIONS"
fi

To apply your changes, in [FlutterRoot], run

git commit -am "Enable obfuscation on iOS"  
flutter  

(Running "flutter" after the commit rebuilds flutter tools.)

Next, in your project, add following to [ProjectRoot]/ios/Flutter/Release.xcconfig file:

EXTRA_GEN_SNAPSHOT_OPTIONS=--obfuscate

PS: Haven't tried the --save-obfuscation-map flag mentioned at https://github.com/dart-lang/sdk/issues/30524
Again, obfuscation isn't very well tested, as mentioned by @mraleph.

Scab answered 28/5, 2018 at 16:26 Comment(7)
Does this current obfuscation technique make it hard for reverse engineering the code or is there any additional steps which we can follow to make it difficult for reverse engineering?Cavesson
I can't find xcode_backend.sh where is that file located, /packages doesn't exists on this location too. The only /packages folder is located on /ios/Flutter/App.framework/flutter_assets/packages but it doesn't contain flutter_tools.Botel
@Botel I believe you are looking under your own project by mistake - xcode_backend.sh resides in your Flutter install location. (Either that or Flutter changed since I answered. Either way, please let me know)Scab
thanks man, you're right I was looking the project folder, my mistake.Botel
Where to define this? local extra_gen_snapshot_options_or_none="" if [[ -n "$EXTRA_GEN_SNAPSHOT_OPTIONS" ]]; then extra_gen_snapshot_options_or_none="--extra-gen-snapshot-options=$EXTRA_GEN_SNAPSHOT_OPTIONS" fiSabulous
@JustineMackay before the call to build aot .Scab
Hi, is this the only way to obfuscate an .ipa?Filmore
H
30

AppBundle (recommended):

  • Without splitting:

    flutter build appbundle --obfuscate --split-debug-info=/<directory>
    
  • Splitting:

    flutter build appbundle --target-platform android-arm,android-arm64,android-x64 --obfuscate --split-debug-info=/<directory>
    

APK:

  • Without splitting:
    flutter build apk --obfuscate --split-debug-info=/<directory>
    
  • Splitting:

    flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi --obfuscate --split-debug-info=/<directory>
    

PS: About Splitting:
By default, fat apk contains arm v7, arm v8 and x64 which increases apk size, which you don't want to. So, when you split it, you have separate binaries which you can upload on the store and thus reducing the size of the apk that a user would need to download.

Hydrous answered 29/5, 2020 at 2:6 Comment(3)
What do you mean by "splitting"?Krebs
Thank you, I read it right after asking in the official documentation flutter.dev/docs/deployment/obfuscate, it will still be helpful for people who limit themselves to this page! You may want to edit your answer to add this precision.Krebs
Note that appbundle is recommended as size matters. It can tremendously reduce the size of your app.Krebs
A
17

All the above answers are correct, but no answer tells you that we need to add a relative path or directory path while generating build.

Example using Relative Path:

flutter build apk --obfuscate --split-debug-info=./ProjectFolderName/debug
                                

Example using Folder Path:

flutter build apk --obfuscate --split-debug-info=/Users/apple/Desktop/items/debug

The above command will generate a build inside the given project directory, it will create a new folder called ProjectFolderName or 'debug' on the respective command, and there you can find the release build.

Abutter answered 6/12, 2020 at 15:35 Comment(1)
Thanks, using the relative path helped. I thought it would do that by default but no.Rile
N
9

For Android the process is pretty clear from the doc at https://flutter.dev/docs/deployment/obfuscate. For Example:

export version=1.0.0
flutter build apk --release --shrink --obfuscate --split-debug-info=misc/mapping/${version}

Several files will be created such as misc/mapping/1.0.0/app.android-arm64.symbols (which you'll likely want to keep in VCS)

For iOS it's a bit less obvious since you often use the Xcode menu: Product > Archive

  1. make an obfuscated build for iOS
flutter build ios --release --obfuscate --split-debug-info=misc/mapping/${version}

it creates file misc/mapping/1.0.0/app.ios-arm64.symbols

  1. This will also modify ios/Flutter/Generated.xcconfig to include
DART_OBFUSCATION=true
SPLIT_DEBUG_INFO=misc/mapping/1.0.0
  1. Use Xcode menu: Product > Archive which will uses Release.xcconfig which includes updated Generated.xcconfig
#include "Generated.xcconfig"

So your uploaded Archive will now be obfuscated (you don't need to make changes to Release.xcconfig)

See also - https://github.com/flutter/flutter/issues/64626#issuecomment-736081173

Nygaard answered 25/6, 2021 at 2:1 Comment(2)
Thanks for the answer! How could I add the *.symbols to google play?Beaverbrook
what about web app?Americanize
E
6

enter image description here https://flutter.dev/docs/deployment/obfuscateRefer this link for more info

Note: Flutter’s code obfuscation, Supported as of Flutter 1.16.2.

Elsyelton answered 19/5, 2020 at 12:34 Comment(0)
F
6

For iOS edit ios/Flutter/Release.xcconfig

This file should contain something like

#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

If you check Generated.xcconfig there is a line DART_OBFUSCATION=false

So add opposite to the end of the Release.xcconfig file to override:

#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

DART_OBFUSCATION=true
SPLIT_DEBUG_INFO=obj_maps

You can optionally add TREE_SHAKE_ICONS=true here to tree-shake icons as well

Fatality answered 27/1, 2021 at 14:44 Comment(2)
Great! I didn't know about the iOS part, but even after adding DART_OBFUSCATION=true in Release.xcconfig file and doing a build, the Generated.xcconfig file still shows DART_OBFUSCATION=false. Am I doing something wrong?Hydrous
@Hydrous Generated.xcconfig doesn't matter, because we reassigning it's value in Release.xcconfig after including generated one. However I didn't found a way to verify that it's actually working)Fatality
G
3

At the moment obfuscation is not directly exposed via the flutter CLI.

You can try to explicitly pass arguements to the gen_snapshot like this:

flutter build --extra-gen-snapshot-options=--obfuscate,--save-obfuscation-map=build/symbols.json --release

Note: that obfuscation support is not very well tested and might not work at the moment.

Guitarist answered 28/5, 2018 at 11:51 Comment(6)
Does not work: Could not find an option named "extra-gen-snapshot-options".Scab
What about flutter build aot --extra-gen-snapshot-options=...?Guitarist
flutter build aot seems to respond to the flag, but where's the apk/ipa?Scab
flutter build aot unfortunately does not build APK, I looked at the code and currently it does not seem like you have a way to build ipk and also pass these flags. You would have to edit flutter_tools sources.Guitarist
@mraleph I managed setting the extra-gen-snapshot-options flag via Gradle's gradle.properties, and got a working & obfuscated apk. What's the equivalent for this in iOS?Scab
I don't know about those parts of Flutter tooling.Guitarist
B
0

To obfuscate Dart code in a Flutter:

Update your pubspec.yaml file to include the flutter_dotenv and flutter_obfuscate packages:

 dependencies:
  flutter_dotenv: ^3.1.0

dev_dependencies:
  flutter_obfuscate: ^1.0.0

Create an .env file in the root of your Flutter project and define the following environment variable:

DART_OBFUSCATION=true

In your main.dart file, import the flutter_dotenv package and modify the main function as follows:

import 'package:flutter_dotenv/flutter_dotenv.dart';

Future<void> main() async {
  await dotenv.load();
  runApp(MyApp());
}

Build the Flutter project using the --release flag to generate a release build: >flutter build apk --release

After the build process completes, run the following command to obfuscate the Dart code: >flutter pub run flutter_obfuscate

The obfuscated code will be placed in the lib_obfuscated directory.

Begorra answered 22/5, 2023 at 16:19 Comment(1)
the package flutter_obfuscate doesn't appear to exist?Termination

© 2022 - 2024 — McMap. All rights reserved.