flutter_rasp 1.0.0 copy "flutter_rasp: ^1.0.0" to clipboard
flutter_rasp: ^1.0.0 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 #

pub package License: MIT Platform

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 #

Installation #

Add flutter_rasp to your pubspec.yaml:

dependencies:
  flutter_rasp: ^1.0.0

Platform Requirements #

Platform Minimum Version
Android API 24 (Android 7.0)
iOS 13.0

This plugin does not require any additional permissions.


Usage #

Initialization #

Initialize the SDK once at app startup. This configures and starts monitoring automatically:

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: 5),
    ),
    onThreatDetected: (Set<Threat> threats) {
      for (final threat in threats) {
        debugPrint('Threat detected: ${threat.name}');
      }
    },
  );

  runApp(const MyApp());
}

Threat Policies #

Policies control which threats cause the app to be terminated at the native level before any Dart code can react. Threats not in the policy's exitThreats are reported via onThreatDetected.

Policy Exit Threats Use Case
ThreatPolicy.none None Report only, no enforcement
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},
);

ThreatCallback #

Instead of (or in addition to) the generic onThreatDetected, you can use ThreatCallback to handle each threat individually:

await FlutterRasp.instance.initialize(
  config: const RaspConfig(policy: ThreatPolicy.medium),
  threatCallback: ThreatCallback(
    onRoot: () => debugPrint('Device is rooted!'),
    onEmulator: () => debugPrint('Running on emulator!'),
    onDebug: () => debugPrint('Debugger attached!'),
    onHook: () => debugPrint('Hooks detected!'),
    onTampered: () => debugPrint('App was tampered!'),
    onVpn: () => debugPrint('VPN is active!'),
    onDeveloperMode: () => debugPrint('Developer mode enabled!'),
  ),
);

You can also attach or replace callbacks at runtime:

FlutterRasp.instance.attachListener(
  ThreatCallback(
    onRoot: () => navigateToBlockedScreen(),
  ),
);

FlutterRasp.instance.detachListener();

Note: At least one of onThreatDetected or threatCallback must be provided. Both can be used simultaneously.

Development vs Production #

Use ThreatPolicy.none during development so the app is never terminated by the native enforcement layer. All threats are still detected and reported via callbacks, but no exit action is taken:

await FlutterRasp.instance.initialize(
  config: const RaspConfig(
    policy: ThreatPolicy.none,
    monitoringInterval: Duration(seconds: 5),
  ),
  onThreatDetected: (threats) {
    debugPrint('Detected: $threats');
  },
);

Note: When debugging on a physical device via Xcode WiFi, the remote debugging tunnel creates a network interface that is detected as a VPN connection. This is a false positive caused by Xcode, not by an actual VPN. This only happens during development — release builds on real devices are not affected.

For production, use .medium or .high to terminate the app on critical threats:

await FlutterRasp.instance.initialize(
  config: const RaspConfig(
    policy: ThreatPolicy.high,
  ),
  threatCallback: ThreatCallback(
    onVpn: () => showVpnWarning(),
  ),
);

Full Scan #

final result = await FlutterRasp.instance.scanAll();

if (result.isCompromised) {
  debugPrint('Threats detected: ${result.detectedThreats}');
}

Individual Checks #

final rasp = FlutterRasp.instance;

if (await rasp.isRooted()) {}
if (await rasp.isEmulator()) {}
if (await rasp.isDebugged()) {}
if (await rasp.isHooked()) {}
if (await rasp.isTampered()) {}
if (await rasp.isVpnConnected()) {}
if (await rasp.isDeveloperMode()) {}

Screen Capture Protection #

await FlutterRasp.instance.blockScreenCapture(true);
await FlutterRasp.instance.blockScreenCapture(false);
final isBlocked = await FlutterRasp.instance.isScreenCaptureBlocked();

App Integrity Configuration #

For real repackaging protection, provide your app's signing certificate hashes and bundle identifiers. Without this configuration, the integrity check only verifies the installation source. With it, the plugin compares the app's runtime signature against your expected values.

Android #

Provide your signing certificate SHA-256 hashes in Base64 format:

const config = RaspConfig(
  androidConfig: AndroidRaspConfig(
    signingCertHashes: ['YOUR_BASE64_SHA256_HASH'],
  ),
);

How to get your signing certificate hash:

keytool -list -v -keystore your-keystore.jks -alias your-alias

Copy the SHA256 fingerprint (e.g., AB:CD:EF:...), remove the colons, decode the hex to bytes, and encode as Base64. Or use this one-liner:

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 Android 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

You can also customize which app stores are considered trusted:

const config = RaspConfig(
  androidConfig: AndroidRaspConfig(
    signingCertHashes: ['YOUR_BASE64_SHA256_HASH'],
    supportedStores: [
      'com.android.vending',
      'com.amazon.venezia',
    ],
  ),
);

Default trusted stores: Google Play, Amazon Appstore, Huawei AppGallery, Samsung Galaxy Store.

iOS #

Provide your Apple Team ID and expected bundle identifiers:

const config = RaspConfig(
  iosConfig: IosRaspConfig(
    teamId: 'YOUR_TEAM_ID',
    bundleIds: ['com.yourcompany.yourapp'],
  ),
);

How to get your Team ID:

  1. Go to Apple Developer Account
  2. Your Team ID is displayed under Membership Details
  3. It's a 10-character alphanumeric string (e.g., A1B2C3D4E5)

Full Example #

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}');
      }
    },
  );

  runApp(const MyApp());
}

API Reference #

FlutterRasp #

Method Return Type Description
instance FlutterRasp Singleton instance
initialize({config, onThreatDetected, threatCallback}) Future<void> Initialize SDK and start monitoring
scanAll({enabledThreats}) Future<RaspResult> Run full security scan
isRooted() Future<bool> Check root/jailbreak
isEmulator() Future<bool> Check emulator/simulator
isDebugged() Future<bool> Check debugger
isHooked() Future<bool> Check hooks (Frida/Xposed)
isTampered() Future<bool> Check app integrity
isVpnConnected() Future<bool> Check VPN
isDeveloperMode() Future<bool> Check developer mode
blockScreenCapture(bool) Future<void> Toggle screen protection
isScreenCaptureBlocked() Future<bool> Check screen protection state
attachListener(ThreatCallback) void Replace the current threat callback
detachListener() void Remove the current threat callback
isInitialized bool Whether SDK is initialized

RaspConfig #

Parameter Type Default Description
enabledThreats Set<Threat> All threats Threats to check
policy ThreatPolicy ThreatPolicy.none Enforcement policy
monitoringInterval Duration 10 seconds Time between scans (min 1s)
androidConfig AndroidRaspConfig? null Android integrity configuration
iosConfig IosRaspConfig? null iOS integrity configuration

ThreatPolicy #

Preset Exit Threats
ThreatPolicy.none None
ThreatPolicy.low tampered
ThreatPolicy.medium root, hook, tampered
ThreatPolicy.high root, hook, tampered, debug

AndroidRaspConfig #

Parameter Type Default Description
signingCertHashes List<String> Required SHA-256 certificate hashes in Base64
supportedStores List<String> Play, Amazon, Huawei, Samsung Trusted installer package names

IosRaspConfig #

Parameter Type Default Description
teamId String Required Apple Developer Team ID
bundleIds List<String> Required Expected bundle identifiers

RaspResult #

Property Type Description
threats Map<Threat, bool> All check results
isCompromised bool true if any threat detected
detectedThreats Set<Threat> Set of detected threats
isRooted bool Root/jailbreak result
isEmulator bool Emulator result
isDebugged bool Debugger result
isHooked bool Hook result
isTampered bool Integrity result
isVpnConnected bool VPN result
isDeveloperMode bool Developer mode result

ThreatCallback #

Parameter Type Description
onRoot VoidCallback? Called when root/jailbreak is detected
onEmulator VoidCallback? Called when emulator/simulator is detected
onDebug VoidCallback? Called when debugger is attached
onHook VoidCallback? Called when hooks are detected
onTampered VoidCallback? Called when app integrity is compromised
onVpn VoidCallback? Called when VPN is active
onDeveloperMode VoidCallback? Called when developer mode is enabled

Threat Enum #

enum Threat {
  root,
  emulator,
  debug,
  hook,
  tampered,
  vpn,
  developerMode,
}

Detection Details #

Root / Jailbreak #

Android:

  • Scans for su binaries in system paths
  • Detects root management apps (Magisk, SuperSU, KingRoot)
  • Checks ro.debuggable and ro.secure system properties
  • Verifies build tags for test-keys

iOS:

  • Checks for jailbreak artifacts (Cydia, MobileSubstrate, apt)
  • Performs sandbox write test outside app container
  • Detects Cydia URL scheme
  • Uses posix_spawn to verify process restrictions

Hook Detection #

Android:

  • Scans running processes for Frida
  • Reads /proc/self/maps for injected libraries
  • Tests Frida default ports (27042, 27043)
  • Detects Xposed/LSPosed/EdXposed packages
  • Scans stack trace for Xposed class names
  • Checks /proc/self/fd for Frida named pipes

iOS:

  • Checks DYLD_INSERT_LIBRARIES environment variable
  • Scans loaded dylibs via _dyld_image_count()
  • Tests Frida default port (27042)

App Integrity #

Android:

  • Verifies installation source against trusted stores
  • Compares APK signing certificate SHA-256 hash against expected values (when configured)
  • Detects repackaged apps signed with a different certificate

iOS:

  • Checks appStoreReceiptURL for App Store vs sandbox/TestFlight
  • Detects embedded.mobileprovision presence
  • Verifies PIE flag in Mach-O binary header
  • Validates bundle ID against expected values (when configured)
  • Extracts and validates Team ID from provisioning profile (when configured)

VPN Detection #

Android:

  • Checks active network transport via ConnectivityManager for TRANSPORT_VPN
  • Scans network interfaces for VPN prefixes (tun, ppp, pptp, tap, ipsec)

iOS:

  • Enumerates network interfaces via getifaddrs() for VPN prefixes (ppp, tap, tun, ipsec)
  • Inspects CFNetworkCopySystemProxySettings scoped proxy entries for VPN tunnels (including utun)

Utilities #

HashConverter #

The hashConverter utility helps convert signing certificate hashes between formats:

import 'package:flutter_rasp/flutter_rasp.dart';

final sha256Hex = 'AE:4F:12:31:E0:AF:E1:35:E9:BC:0A:F5:21:AF:9B:C6:'
    '7E:09:76:B1:B4:D6:4E:79:90:DB:AC:30:82:E4:6E:69';

final base64Hash = hashConverter.fromSha256toBase64(sha256Hex);
final backToHex = hashConverter.fromBase64toSha256(base64Hash);

hashConverter.isValidSha256Format('abcdef...');
hashConverter.isValidBase64Sha256(base64Hash);

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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/new-detection)
  3. Commit your changes (git commit -m 'Add new detection')
  4. Push to the branch (git push origin feature/new-detection)
  5. Open a Pull Request

Adding a New Detector #

To add a new threat detector, you only need to:

  1. Create a detector class implementing ThreatDetector (Android) or ThreatDetectable (iOS)
  2. Add it to the DetectorRegistry list
  3. Add the corresponding Threat enum value in Dart

License #

This project is licensed under the MIT License - see the LICENSE file for details.

0
likes
0
points
324
downloads

Publisher

verified publisherjuandpt.dev

Weekly Downloads

A comprehensive RASP (Runtime Application Self-Protection) plugin for Flutter. Detect root, jailbreak, emulators, debuggers, hooks, tampering, VPN, and more.

Repository (GitHub)
View/report issues

Topics

#security #rasp #jailbreak #root-detection #flutter-plugin

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on flutter_rasp

Packages that implement flutter_rasp