{"id":13845501,"url":"https://github.com/ptswarm/reFlutter","last_synced_at":"2025-07-12T02:31:40.103Z","repository":{"id":149319674,"uuid":"411806026","full_name":"ptswarm/reFlutter","owner":"ptswarm","description":"Flutter Reverse Engineering Framework","archived":true,"fork":false,"pushed_at":"2022-04-11T10:45:21.000Z","size":336,"stargazers_count":1270,"open_issues_count":79,"forks_count":176,"subscribers_count":16,"default_branch":"main","last_synced_at":"2024-09-27T04:02:13.386Z","etag":null,"topics":["bugbounty","mobile-security","reverse-engineering","ssl-pinning"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ptswarm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-09-29T19:35:16.000Z","updated_at":"2024-09-24T05:56:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"a04dfb64-a867-415c-a2c5-cce499852569","html_url":"https://github.com/ptswarm/reFlutter","commit_stats":null,"previous_names":[],"tags_count":118,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptswarm%2FreFlutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptswarm%2FreFlutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptswarm%2FreFlutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptswarm%2FreFlutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ptswarm","download_url":"https://codeload.github.com/ptswarm/reFlutter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225784675,"owners_count":17523690,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bugbounty","mobile-security","reverse-engineering","ssl-pinning"],"created_at":"2024-08-04T17:03:26.447Z","updated_at":"2024-11-21T18:32:03.594Z","avatar_url":"https://github.com/ptswarm.png","language":"Python","readme":"[![Twitter](https://img.shields.io/twitter/follow/lmpact_l.svg?logo=twitter)](https://twitter.com/lmpact_l)\n\n[![stars](https://img.shields.io/github/stars/ptswarm/reFlutter)](https://github.com/ptswarm/reFlutter/stargazers) [![workflow](https://img.shields.io/github/workflow/status/ptswarm/reFlutter/Build)](https://github.com/ptswarm/reFlutter/actions)\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/87244850/135659542-22bb8496-bf26-4e25-b7c1-ffd8fc0cea10.png\" width=\"75%\"/\u003e\u003c/p\u003e\n\n#\nThis 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.\n\nKey features:\n- `socket.cc` is patched for traffic monitoring and interception;\n- `dart.cc` is modified to print classes, functions and some fields;\n- contains minor changes for successfull compilation;\n- if you would like to implement your own patches, there is manual Flutter code change is supported using specially crafted `Dockerfile`\n### Supported engines\n- Android: arm64, arm32;\n- iOS: arm64;\n- Release: Stable, Beta\n### Install\n```\n# Linux, Windows, MacOS\npip3 install reflutter\n```\n### Usage\n```console\nimpact@f:~$ reflutter main.apk\n\nPlease enter your Burp Suite IP: \u003cinput_ip\u003e\n\nSnapshotHash: 8ee4ef7a67df9845fba331734198a953\nThe resulting apk file: ./release.RE.apk\nPlease sign the apk file\n\nConfigure Burp Suite proxy server to listen on *:8083\nProxy Tab -\u003e Options -\u003e Proxy Listeners -\u003e Edit -\u003e Binding Tab\n\nThen enable invisible proxying in Request Handling Tab\nSupport Invisible Proxying -\u003e true\n\nimpact@f:~$ reflutter main.ipa\n```\n### Traffic interception\nYou 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 -\u003e Listener Proxy -\u003e Options tab`\n- Add port: `8083`\n- Bind to address: `All interfaces`\n- Request handling: Support invisible proxying = `True`\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/87244850/135753172-20489ef9-0759-432f-b2fa-220607e896b8.png\" width=\"84%\"/\u003e\u003c/p\u003e\n\nYou 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.\n### Usage on Android\nThe resulting apk must be aligned and signed. I use [uber-apk-signer](https://github.com/patrickfav/uber-apk-signer/releases/tag/v1.2.1)\n```java -jar uber-apk-signer.jar --allowResign -a release.RE.apk```.\nTo see which code is loaded through DartVM, you need to run the application on the device. Note that you must manually find what `_kDartIsolateSnapshotInstructions` (ex. 0xB000 ) equals to using a binary search. reFlutter writes the dump to the root folder of the application and sets `777` permissions to the file and folder. You can pull the file with adb command\n```console\nimpact@f:~$ adb -d shell \"cat /data/data/\u003cPACKAGE_NAME\u003e/dump.dart\" \u003e dump.dart\n```\n\u003cdetails\u003e\n\u003csummary\u003efile contents\u003c/summary\u003e\n\n  \n```dart\nLibrary:'package:anyapp/navigation/DeepLinkImpl.dart' Class: Navigation extends Object {  \n\nString* DeepUrl = anyapp://evil.com/ ;\n\n Function 'Navigation.': constructor. (dynamic, dynamic, dynamic, dynamic) =\u003e NavigationInteractor { \n  \n              Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000009270\n  \n                   }\n    \n Function 'initDeepLinkHandle':. (dynamic) =\u003e Future\u003cvoid\u003e* { \n  \n              Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000412fe8\n  \n                   }\n    \n Function '_navigateDeepLink@547106886':. (dynamic, dynamic, {dynamic navigator}) =\u003e void { \n  \n              Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002638\n  \n                   }\n \n       }\n \nLibrary:'package:anyapp/auth/navigation/AuthAccount.dart' Class: AuthAccount extends Account {\n\nPlainNotificationToken* _instance = sentinel;\n \n Function 'getAuthToken':. (dynamic, dynamic, dynamic, dynamic) =\u003e Future\u003cAccessToken*\u003e* { \n  \n               Code Offset: _kDartIsolateSnapshotInstructions + 0x00000000003ee548\n  \n                   }\n  \n Function 'checkEmail':. (dynamic, dynamic) =\u003e Future\u003cbool*\u003e* { \n  \n               Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000448a08\n   \n                   }\n\n Function 'validateRestoreCode':. (dynamic, dynamic, dynamic) =\u003e Future\u003cbool*\u003e* { \n  \n               Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000412c34\n   \n                   }\n\n Function 'sendSmsRestorePassword':. (dynamic, dynamic) =\u003e Future\u003cbool*\u003e* { \n  \n               Code Offset: _kDartIsolateSnapshotInstructions + 0x00000000003efb88\n  \n                   }\n       }\n```\n\u003c/details\u003e\n\n### Usage on iOS\nUse 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.\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/87244850/135860648-a13ba3fd-93d2-4eab-bd38-9aa775c3178f.png\" width=\"100%\"/\u003e\u003c/p\u003e\n\n### To Do\n- [x] Display absolute code offset for functions;\n- [ ] Extract more strings and fields;\n- [x] Add socket patch;\n- [ ] Extend engine support to Debug using Fork and Github Actions;\n- [ ] Improve detection of `App.framework` and `libapp.so` inside zip archive\n  \n### Build Engine\nThe 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).\nThe hash of the snapshot is extracted from ```storage.googleapis.com/flutter_infra_release/flutter/\u003chash\u003e/android-arm64-release/linux-x64.zip```\n\u003cdetails\u003e\n\u003csummary\u003erelease\u003c/summary\u003e\n  \n[![gif](https://user-images.githubusercontent.com/87244850/135758767-47b7d51f-8b6c-40b5-85aa-a13c5a94423a.gif)](https://github.com/ptswarm/reFlutter/actions)\n  \n\u003c/details\u003e\n\n### Custom Build\nIf 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)\n\n```sudo docker pull ptswarm/reflutter```\n```\n# Linux, Windows\nEXAMPLE BUILD ANDROID ARM64:\n    sudo docker run -e WAIT=300 -e x64=0 -e arm=0 -e HASH_PATCH=\u003cSnapshot_Hash\u003e -e COMMIT=\u003cEngine_commit\u003e --rm -iv${PWD}:/t ptswarm/reflutter\n\nFLAGS:\n    -e x64=0                         \u003cdisables building for x64 archiitechture, use to reduce building time\u003e\n    -e arm=0                         \u003cdisables building for arm archiitechture, use to reduce building time\u003e\n    -e WAIT=300                      \u003cthe amount of time in seconds you need to edit source code\u003e\n    -e HASH_PATCH=[Snapshot_Hash]    \u003chere 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\u003e\n    -e COMMIT=[Engine_commit]        \u003chere you specify commit for your engine version, take it from enginehash.csv table or from flutter/engine repo\u003e\n```\n","funding_links":[],"categories":["Endpoint","Python","Reverse Engineering"],"sub_categories":["Mobile / Android / iOS","Malware Articles and Sources"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fptswarm%2FreFlutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fptswarm%2FreFlutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fptswarm%2FreFlutter/lists"}