Flutter RASP
A comprehensive RASP (Runtime Application Self-Protection) plugin for Flutter. Protect your app against reverse engineering, tampering, and runtime attacks with zero external SDK dependencies.
Features
| Threat | Android | iOS | Description |
|---|---|---|---|
| Root / Jailbreak | :white_check_mark: | :white_check_mark: | Detects rooted devices, su binaries, Cydia, sandbox escape |
| Emulator / Simulator | :white_check_mark: | :white_check_mark: | Identifies emulators via build properties and environment |
| Debugger | :white_check_mark: | :white_check_mark: | Detects attached debuggers (JDWP, ptrace) |
| Hooks (Frida/Xposed) | :white_check_mark: | :white_check_mark: | Scans for Frida, Xposed, Cycript, Substrate |
| Repackaging | :white_check_mark: | :white_check_mark: | Verifies signing certificates, bundle ID, team ID |
| Trusted Install | :white_check_mark: | :white_check_mark: | Detects sideloaded apps and untrusted installation sources |
| VPN | :white_check_mark: | :white_check_mark: | Detects active VPN connections |
| Developer Mode | :white_check_mark: | :x: | Checks if developer options or ADB are enabled |
| Device Passcode | :white_check_mark: | :white_check_mark: | Detects devices without screen lock |
| Secure Hardware | :white_check_mark: | :white_check_mark: | Detects missing hardware-backed keystore (TEE/StrongBox, Secure Enclave) |
| Obfuscation | :white_check_mark: | :x: | Detects unobfuscated binaries with readable class/symbol names |
| Time Spoofing | :white_check_mark: | :x: | Detects disabled automatic time synchronization |
| Location Spoofing | :white_check_mark: | :x: | Detects mock location apps and settings |
| Multi-Instance | :white_check_mark: | :x: | Detects cloned/dual-app environments |
| Screen Capture | :white_check_mark: | :white_check_mark: | Blocks screenshots and screen recording |
Getting Started
dependencies:
flutter_rasp: ^2.0.1
| Platform | Minimum Version |
|---|---|
| Android | API 24 (Android 7.0) |
| iOS | 13.0 |
No additional permissions required. Zero external SDK dependencies.
Usage
Initialization
import 'package:flutter_rasp/flutter_rasp.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterRasp.instance.initialize(
config: const RaspConfig(
policy: ThreatPolicy.high,
monitoringInterval: Duration(seconds: 10),
androidConfig: AndroidRaspConfig(
signingCertHashes: ['AKoRuyLMM91E7lX/Zqp3u4jMmd0A7hH/Iqozu0TMVd0='],
),
iosConfig: IosRaspConfig(
teamId: 'A1B2C3D4E5',
bundleIds: ['com.yourcompany.yourapp'],
),
),
onThreatDetected: (threats) => debugPrint('$threats'),
threatCallback: ThreatCallback(
onRoot: () => navigateToBlockedScreen(),
onVpn: () => showVpnWarning(),
),
);
runApp(const MyApp());
}
Note: At least one of
onThreatDetectedorthreatCallbackmust be provided.
Platform Configuration
Android — signingCertHashes expects your signing certificate fingerprint in Base64 format.
-
Get the SHA-256 fingerprint from
keytool, Google Play Console (App signing section), or Firebase Console. You will end up with a hex string like this:A1:2B:3C:4D:5E:6F:70:81:92:A3:B4:C5:D6:E7:F8:09:1A:2B:3C:4D:5E:6F:70:81:92:A3:B4:C5:D6:E7:F8:09 -
Convert it to Base64. You can get it directly from terminal:
keytool -list -v -keystore your-keystore.jks -alias your-alias 2>/dev/null \ | grep SHA256 | awk '{print $2}' | tr -d ':' | xxd -r -p | base64Or use the built-in utility:
final base64Hash = hashConverter.fromSha256toBase64( 'A1:2B:3C:4D:5E:6F:70:81:92:A3:B4:C5:D6:E7:F8:09:1A:2B:3C:4D:5E:6F:70:81:92:A3:B4:C5:D6:E7:F8:09', );
iOS — Find your Team ID at Apple Developer Account → Membership Details.
Supported Stores / Distribution Methods
The supportedStores parameter in AndroidRaspConfig controls which install sources are considered trusted.
| Store / Distribution method | Package name | Notes |
|---|---|---|
| App Store (iOS) | Included by default, no action needed | |
| TestFlight (iOS) | Included by default, no action needed | |
| Google Play | com.android.vending |
Included by default, no action needed |
| Huawei AppGallery | com.huawei.appmarket |
Included by default, no action needed |
| Amazon Appstore | com.amazon.venezia |
Included by default, no action needed |
| Samsung Galaxy Store | com.sec.android.app.samsungapps |
Included by default, no action needed |
| Firebase App Distribution | dev.firebase.appdistribution |
|
| Vivo App Store | com.vivo.appstore |
Common on Vivo devices |
| HeyTap | com.heytap.market |
Common on Realme and Oppo devices |
| Oppo App Market | com.oppo.market |
Common on Oppo devices |
| GetApps | com.xiaomi.mipicks |
Common on Xiaomi, Redmi and POCO devices |
To support additional stores, add their package names:
AndroidRaspConfig(
signingCertHashes: ['...'],
supportedStores: [
...AndroidRaspConfig().supportedStores,
'dev.firebase.appdistribution', // Firebase App Distribution
'com.vivo.appstore', // Vivo App Store
'com.heytap.market', // HeyTap (Realme, Oppo)
'com.oppo.market', // Oppo App Market
'com.xiaomi.mipicks', // GetApps (Xiaomi, Redmi, POCO)
],
);
Threat Policies
Policies control which threats terminate the app at the native level before Dart code can react.
| Policy | Exit Threats |
|---|---|
ThreatPolicy.none |
None (report only) |
ThreatPolicy.low |
repackaging, trustedInstall |
ThreatPolicy.medium |
root, hook, repackaging, trustedInstall, obfuscationIssues, multiInstance |
ThreatPolicy.high |
root, hook, repackaging, trustedInstall, debug, devicePasscode, obfuscationIssues, multiInstance, secureHardwareNotAvailable, locationSpoofing |
const policy = ThreatPolicy(
exitThreats: {Threat.root, Threat.repackaging, Threat.vpn},
);
Tip: Use
ThreatPolicy.noneduring development.
Scans & Individual Checks
final result = await FlutterRasp.instance.scanAll();
if (result.isCompromised) {
debugPrint('Detected: ${result.detectedThreats}');
}
Available: isRooted(), isEmulator(), isDebugged(), isHooked(), isRepackaged(), isUntrustedInstall(), isVpnConnected(), isDeveloperMode(), isDevicePasscodeDisabled(), isSecureHardwareUnavailable(), hasObfuscationIssues(), isTimeSpoofed(), isLocationSpoofed(), isMultiInstance().
Screen Capture Protection
await FlutterRasp.instance.blockScreenCapture(true);
Architecture
Flutter App
│
FlutterRasp (Singleton)
│
FlutterRaspPlatform (Interface)
│
MethodChannelFlutterRasp
├── MethodChannel (commands/checks)
└── EventChannel (threat stream)
Android (Kotlin) iOS (Swift)
───────────────── ─────────────────
DetectorRegistry DetectorRegistry
├── RootDetector ├── JailbreakDetector
├── EmulatorDetector ├── SimulatorDetector
├── DebugDetector ├── DebugDetector
├── HookDetector ├── HookDetector
├── RepackagingDetector ├── RepackagingDetector
├── TrustedInstallDetector ├── TrustedInstallDetector
├── VpnDetector ├── VpnDetector
├── DeveloperModeDetector ├── DevicePasscodeDetector
├── DevicePasscodeDetector └── SecureHardwareDetector
├── SecureHardwareDetector ScreenCaptureManager
├── ObfuscationDetector
├── TimeSpoofingDetector
├── LocationSpoofingDetector
└── MultiInstanceDetector
ScreenCaptureManager
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Adding a New Detector
- Create a detector class implementing
ThreatDetector(Android) orThreatDetectable(iOS) - Add it to the
DetectorRegistrylist - Add the corresponding
Threatenum value in Dart
License
This project is licensed under the MIT License - see the LICENSE file for details.
Libraries
- flutter_rasp
- A comprehensive RASP (Runtime Application Self-Protection) plugin for Flutter.