Flutter Reverse Engineering Framework https://github.com/ptswarm/reFlutter.git

lqg 15873f6cde 0 2 years ago
.github 8cc8217148 add project 2 years ago
src 15873f6cde 0 2 years ago
.gitignore 8cc8217148 add project 2 years ago
LICENSE 8cc8217148 add project 2 years ago
README.md bf977f98f8 replace githubusercontent 2 years ago
SNAPSHOT_HASH 15873f6cde 0 2 years ago
enginehash.csv 8cc8217148 add project 2 years ago
setup.py 8cc8217148 add project 2 years ago

README.md

reflutter

This framework helps with Flutter apps reverse engineering using the patched version of the Flutter library which is already compiled and ready for app repacking. This library has snapshot deserialization process modified to allow you perform dynamic analysis in a convenient way.

Key features:

  • socket.cc is patched for traffic monitoring and interception;
  • dart.cc is modified to print classes, functions and some fields;
  • contains minor changes for successfull compilation;
  • if you would like to implement your own patches, there is manual Flutter code change is supported using specially crafted Dockerfile

    Supported engines

  • Android: arm64, arm32;

  • iOS: arm64;

  • Release: Stable, Beta

    Install

    # Linux, Windows, MacOS
    pip3 install reflutter
    

    Usage

    impact@f:~$ reflutter main.apk
    
    Please enter your Burp Suite IP: <input_ip>
    
    SnapshotHash: 8ee4ef7a67df9845fba331734198a953
    The resulting apk file: ./release.RE.apk
    Please sign the apk file
    
    Configure Burp Suite proxy server to listen on *:8083
    Proxy Tab -> Options -> Proxy Listeners -> Edit -> Binding Tab
    
    Then enable invisible proxying in Request Handling Tab
    Support Invisible Proxying -> true
    
    impact@f:~$ reflutter main.ipa
    

Traffic interception

You need to specify the IP of your Burp Suite Proxy Server located in the same network where the device with the flutter application is. Next, you should configure the Proxy in BurpSuite -> Listener Proxy -> Options tab

  • Add port: 8083
  • Bind to address: All interfaces
  • Request handling: Support invisible proxying = True

You don't need to install any certificates. On an Android device, you don't need root access as well. reFlutter also allows to bypass some of the flutter certificate pinning implementations.

Usage on Android

The resulting apk must be aligned and signed. I use uber-apk-signer

To see which code is loaded through DartVM, you need to run the application on the device. reFlutter prints its output in logcat with the `reflutter` tag

impact@f:~$ adb logcat -e reflutter | sed 's/.*DartVM//' >> reflutter.txt

<details>
<summary>code output</summary>

  

dart Library:'package:anyapp/navigation/DeepLinkImpl.dart' Class: Navigation extends Object {

String* DeepUrl = anyapp://evil.com/ ;

Function 'Navigation.': constructor. (dynamic, dynamic, dynamic, dynamic) => NavigationInteractor {

               }

Function 'initDeepLinkHandle':. (dynamic) => Future* {

               }

Function '_navigateDeepLink@547106886':. (dynamic, dynamic, {dynamic navigator}) => void {

               }

   }

Library:'package:anyapp/auth/navigation/AuthAccount.dart' Class: AuthAccount extends Account {

PlainNotificationToken* _instance = sentinel;

Function 'getAuthToken':. (dynamic, dynamic, dynamic, dynamic) => Future* {

               }

Function 'checkEmail':. (dynamic, dynamic) => Future* {

               }

Function 'validateRestoreCode':. (dynamic, dynamic, dynamic) => Future* {

               }

Function 'sendSmsRestorePassword':. (dynamic, dynamic) => Future* {

               }
   }
</details>

### Usage on iOS
Use the IPA file created after the execution of `reflutter main.ipa` command. To see which code is loaded through DartVM, you need to run the application on the device. reFlutter prints its output in console logs in XCode with the `reflutter` tag.
<p align="center"><img src="https://user-images.githubusercontent.com/87244850/135860648-a13ba3fd-93d2-4eab-bd38-9aa775c3178f.png" width="100%"/></p>

### To Do
- [x] Display absolute code offset for functions;
- [ ] Extract more strings and fields;
- [x] Add socket patch;
- [ ] Extend engine support to Debug using Fork and Github Actions;
- [ ] Improve detection of `App.framework` and `libapp.so` inside zip archive
  
### Build Engine
The engines are built using [reFlutter](https://github.com/ptswarm/reFlutter/blob/main/.github/workflows/main.yml) in [Github Actions](https://github.com/ptswarm/reFlutter/actions) to build the desired version, commits and snapshot hashes are used from this [table](https://github.com/ptswarm/reFlutter/blob/main/enginehash.csv).
The hash of the snapshot is extracted from ```storage.googleapis.com/flutter_infra_release/flutter/<hash>/android-arm64-release/linux-x64.zip```
<details>
<summary>release</summary>
  
[![gif](https://user-images.githubusercontent.com/87244850/135758767-47b7d51f-8b6c-40b5-85aa-a13c5a94423a.gif)](https://github.com/ptswarm/reFlutter/actions)
  
</details>

### Custom Build
If you would like to implement your own patches, manual Flutter code change is supported using specially crafted [Docker](https://hub.docker.com/r/ptswarm/reflutter)

sudo docker pull ptswarm/reflutter```

# Linux, Windows
EXAMPLE BUILD ANDROID ARM64:
    sudo docker run -e WAIT=300 -e x64=0 -e arm=0 -e HASH_PATCH=<Snapshot_Hash> -e COMMIT=<Engine_commit> --rm -iv${PWD}:/t ptswarm/reflutter

FLAGS:
    -e x64=0                         <disables building for x64 archiitechture, use to reduce building time>
    -e arm=0                         <disables building for arm archiitechture, use to reduce building time>
    -e WAIT=300                      <the amount of time in seconds you need to edit source code>
    -e HASH_PATCH=[Snapshot_Hash]    <here you need to specify snapshot hash which matches the engine_commit line of enginehash.csv table best. It is used for proper patch search in reFlutter and for successfull compilation>
    -e COMMIT=[Engine_commit]        <here you specify commit for your engine version, take it from enginehash.csv table or from flutter/engine repo>
    

### flutter抓包

flutter app和firefox一样,使用自带的ssl验证,所以普通抓包方法都是无效的。

(1)root手机 + frida

在安卓系统底层,添加钩子,跳过 flutter app 在 C++代码(libflutter.so文件)中的ssl验证。

(2)reflutter项目

reflutter项目提供修改后的 libflutter.so 文件下载,并使用签名对齐工具重新打包。

git clone https://github.com/ptswarm/reFlutter.git

#替换 http://s.yoqi.me/enginehash.csv 链接

python setup.py install

reflutter main.apk reflutter main.ipa

#https://github.com/patrickfav/uber-apk-signer/releases/tag/v1.2.1 java -jar uber-apk-signer.jar --allowResign -a release.RE.apk

#查看dart adb logcat -e reflutter | sed 's/.*DartVM//' >> reflutter.txt ```

配合burp suite抓包