flutter_rasp 1.0.1
flutter_rasp: ^1.0.1 copied to clipboard
A comprehensive RASP (Runtime Application Self-Protection) plugin for Flutter. Detect root, jailbreak, emulators, debuggers, hooks, tampering, VPN, and more.
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 | ✅ | ✅ | Detects rooted devices, su binaries, Cydia, sandbox escape |
| Emulator / Simulator | ✅ | ✅ | Identifies emulators via build properties and environment |
| Debugger | ✅ | ✅ | Detects attached debuggers (JDWP, ptrace) |
| Hooks (Frida/Xposed) | ✅ | ✅ | Scans for Frida, Xposed, Cycript, Substrate |
| App Integrity | ✅ | ✅ | Verifies signing certificates, bundle IDs, and installation source |
| VPN | ✅ | ✅ | Detects active VPN connections |
| Developer Mode | ✅ | ❌ | Checks if developer options or ADB are enabled |
| Screen Capture Protection | ✅ | ✅ | Blocks screenshots and screen recording |
Getting Started #
Add flutter_rasp to your pubspec.yaml:
dependencies:
flutter_rasp: ^1.0.0
| Platform | Minimum Version |
|---|---|
| Android | API 24 (Android 7.0) |
| iOS | 13.0 |
No additional permissions required.
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: (Set<Threat> threats) {
for (final threat in threats) {
debugPrint('Threat: ${threat.name}');
}
},
threatCallback: ThreatCallback(
onRoot: () => navigateToBlockedScreen(),
onVpn: () => showVpnWarning(),
),
);
runApp(const MyApp());
}
Note: At least one of
onThreatDetectedorthreatCallbackmust be provided. Both can be used simultaneously.
Threat Policies #
Policies control which threats terminate the app at the native level (exit(1)) before Dart code can react. Threats not in exitThreats are reported via callbacks only.
| Policy | Exit Threats | Use Case |
|---|---|---|
ThreatPolicy.none |
None | Report only (use during development) |
ThreatPolicy.low |
tampered | Minimal protection |
ThreatPolicy.medium |
root, hook, tampered | Balanced protection |
ThreatPolicy.high |
root, hook, tampered, debug | Maximum protection |
Custom policies:
const policy = ThreatPolicy(
exitThreats: {Threat.root, Threat.tampered, Threat.vpn},
);
Tip: Use
ThreatPolicy.noneduring development. When debugging via Xcode WiFi, the remote tunnel is detected as a VPN false positive — this only happens in debug builds.
Runtime Callbacks #
You can replace or remove callbacks at any time after initialization:
FlutterRasp.instance.attachListener(
ThreatCallback(onRoot: () => navigateToBlockedScreen()),
);
FlutterRasp.instance.detachListener();
Full Scan & Individual Checks #
final result = await FlutterRasp.instance.scanAll();
if (result.isCompromised) {
debugPrint('Detected: ${result.detectedThreats}');
}
if (await FlutterRasp.instance.isRooted()) { }
if (await FlutterRasp.instance.isHooked()) { }
Available checks: isRooted(), isEmulator(), isDebugged(), isHooked(), isTampered(), isVpnConnected(), isDeveloperMode().
Screen Capture Protection #
await FlutterRasp.instance.blockScreenCapture(true);
final isBlocked = await FlutterRasp.instance.isScreenCaptureBlocked();
App Integrity Configuration #
Without platform configs, integrity checks only verify the installation source. With them, the plugin compares runtime signatures against your expected values.
Android #
Provide your signing certificate SHA-256 hash in Base64:
const config = RaspConfig(
androidConfig: AndroidRaspConfig(
signingCertHashes: ['YOUR_BASE64_SHA256_HASH'],
supportedStores: ['com.android.vending'], // default: Play, Amazon, Huawei, Samsung
),
);
Get your hash:
keytool -list -v -keystore your-keystore.jks -alias your-alias 2>/dev/null \
| grep SHA256 \
| awk '{print $2}' \
| tr -d ':' \
| xxd -r -p \
| base64
For the debug keystore:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android 2>/dev/null \
| grep SHA256 \
| awk '{print $2}' \
| tr -d ':' \
| xxd -r -p \
| base64
iOS #
Provide your Apple Team ID and expected bundle identifiers:
const config = RaspConfig(
iosConfig: IosRaspConfig(
teamId: 'A1B2C3D4E5',
bundleIds: ['com.yourcompany.yourapp'],
),
);
Find your Team ID at Apple Developer Account → Membership Details (10-character alphanumeric string).
Utilities #
HashConverter #
Convert signing certificate hashes between SHA-256 hex and Base64:
final base64Hash = hashConverter.fromSha256toBase64('AE:4F:12:...');
final hexHash = hashConverter.fromBase64toSha256(base64Hash);
hashConverter.isValidSha256Format(hexString);
hashConverter.isValidBase64Sha256(base64String);
Detection Details #
Root / Jailbreak #
Android: Scans for su binaries, root management apps (Magisk, SuperSU, KingRoot), ro.debuggable/ro.secure properties, and test-keys build tags.
iOS: Checks for jailbreak artifacts (Cydia, MobileSubstrate, apt), sandbox write tests, Cydia URL scheme, and posix_spawn process restrictions.
Hook Detection #
Android: Scans processes and /proc/self/maps for Frida, tests ports 27042/27043, detects Xposed/LSPosed/EdXposed packages, checks stack traces and /proc/self/fd for named pipes.
iOS: Checks DYLD_INSERT_LIBRARIES, scans loaded dylibs via _dyld_image_count(), tests Frida port 27042.
App Integrity #
Android: Verifies installation source against trusted stores and compares APK signing certificate hash (when configured).
iOS: Checks appStoreReceiptURL, detects embedded.mobileprovision, verifies PIE flag in Mach-O header, validates bundle ID and Team ID (when configured).
VPN Detection #
Android: Checks ConnectivityManager for TRANSPORT_VPN and scans network interfaces for VPN prefixes (tun, ppp, pptp, tap, ipsec).
iOS: Enumerates interfaces via getifaddrs() for VPN prefixes and inspects CFNetworkCopySystemProxySettings for proxy/tunnel entries.
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
├── IntegrityDetector ├── IntegrityDetector
├── VpnDetector ├── VpnDetector
└── DeveloperModeDetector └── ScreenCaptureManager
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.