diff --git a/README.md b/README.md index 39c672c..535dc8f 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,42 @@ # jailbreak_root_detection [![pub package](https://img.shields.io/pub/v/jailbreak_root_detection.svg)](https://pub.dartlang.org/packages/jailbreak_root_detection) +[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -Uses [RootBeer](https://github.com/scottyab/rootbeer) + DetectFrida for Android root detection and [IOSSecuritySuite (~> 1.9.10)](https://github.com/securing/IOSSecuritySuite/tree/1.9.10) for iOS jailbreak detection. +Detects rooted, jailbroken, tampered and otherwise untrusted devices from Flutter. -## Getting started +Uses [RootBeer](https://github.com/scottyab/rootbeer) + Magisk and Frida checks for Android root detection, and [IOSSecuritySuite (~> 1.9.10)](https://github.com/securing/IOSSecuritySuite/tree/1.9.10) for iOS jailbreak detection. -In your flutter project add the dependency: +## Requirements -```yaml -jailbreak_root_detection: "^1.2.1" -``` +| | Minimum | +| --- | --- | +| Flutter | 3.44.0 | +| Dart SDK | 3.12.0 | +| Android | minSdk 21, compileSdk 34, Java/Kotlin 17 | +| iOS | 11.0 | -## Usage +The iOS side ships as a Swift Package (Swift Package Manager). A CocoaPods podspec is still +included, so both dependency managers work. -### Important: Test on Real Devices Only +## Getting started -This package must be tested on a real device (physical device). +Add the dependency to your `pubspec.yaml`: -Running on an emulator or simulator may cause false positives — for example, the detection may incorrectly report that the device is jailbroken or rooted. +```yaml +dependencies: + jailbreak_root_detection: "^1.2.3" +``` -### Android +Or: -```dart -final isNotTrust = await JailbreakRootDetection.instance.isNotTrust; -final isJailBroken = await JailbreakRootDetection.instance.isJailBroken; -final isRealDevice = await JailbreakRootDetection.instance.isRealDevice; -final isOnExternalStorage = await JailbreakRootDetection.instance.isOnExternalStorage; -final checkForIssues = await JailbreakRootDetection.instance.checkForIssues; -final isDevMode = await JailbreakRootDetection.instance.isDevMode; +```shell +flutter pub add jailbreak_root_detection ``` -### iOS +### iOS setup -- Update `Info.plist` +To let the plugin probe for jailbreak-related URL schemes, add them to `ios/Runner/Info.plist`: ```xml LSApplicationQueriesSchemes @@ -47,16 +50,100 @@ final isDevMode = await JailbreakRootDetection.instance.isDevMode; ``` +Without this entry iOS blocks the `canOpenURL` checks and jailbreak detection is less accurate. + +### Android setup + +No extra configuration required. + +## Usage + +```dart +import 'package:jailbreak_root_detection/jailbreak_root_detection.dart'; + +final detector = JailbreakRootDetection.instance; + +// One combined verdict — the usual entry point. +final isNotTrust = await detector.isNotTrust; +if (isNotTrust) { + // Block, warn, or degrade functionality. +} +``` + +### API + +| Member | Returns | Android | iOS | Description | +| --- | --- | :---: | :---: | --- | +| `isNotTrust` | `Future` | ✅ | ✅ | Combined verdict: jailbroken/rooted, not a real device, or (Android) installed on external storage. Returns `true` if any check throws. | +| `isJailBroken` | `Future` | ✅ | ✅ | Rooted (RootBeer, Frida, Magisk) on Android; jailbroken on iOS. | +| `isRealDevice` | `Future` | ✅ | ✅ | `false` on an emulator or simulator. | +| `isDebugged` | `Future` | ✅ | ✅ | A debugger is attached to the process. | +| `isDevMode` | `Future` | ✅ | — | Developer options are enabled. | +| `isOnExternalStorage` | `Future` | ✅ | — | The app is installed on external storage. | +| `isTampered(String bundleId)` | `Future` | — | ✅ | The app bundle/signature has been modified. | +| `checkForIssues` | `Future>` | ✅ | ✅ | All detected issues in one call. | + +Android-only members throw a `MissingPluginException` on iOS and vice versa, so guard them with +`Platform.isAndroid` / `Platform.isIOS`: + ```dart -final isNotTrust = await JailbreakRootDetection.instance.isNotTrust; -final isJailBroken = await JailbreakRootDetection.instance.isJailBroken; -final isRealDevice = await JailbreakRootDetection.instance.isRealDevice; -final checkForIssues = await JailbreakRootDetection.instance.checkForIssues; +if (Platform.isAndroid) { + final isOnExternalStorage = await detector.isOnExternalStorage; + final isDevMode = await detector.isDevMode; +} + +if (Platform.isIOS) { + const bundleId = 'com.w3conext.jailbreakRootDetectionExample'; + final isTampered = await detector.isTampered(bundleId); +} +``` -final bundleId = 'my-bundle-id'; // Ex: final bundleId = 'com.w3conext.jailbreakRootDetectionExample' -final isTampered = await JailbreakRootDetection.instance.isTampered(bundleId); +### checkForIssues + +`checkForIssues` runs every check the platform supports and returns only the problems it found — +an empty list means the device looks clean. + +```dart +final issues = await detector.checkForIssues; +for (final issue in issues) { + print('issue: $issue'); +} ``` -### Reference +| `JailbreakIssue` | Android | iOS | Meaning | +| --- | :---: | :---: | --- | +| `jailbreak` | ✅ | ✅ | Device is rooted or jailbroken. | +| `notRealDevice` | ✅ | ✅ | Running on an emulator or simulator. | +| `debugged` | ✅ | ✅ | A debugger is attached. | +| `fridaFound` | ✅ | ✅ | The Frida instrumentation framework was detected. | +| `devMode` | ✅ | — | Developer options are enabled. | +| `onExternalStorage` | ✅ | — | App is installed on external storage. | +| `proxied` | — | ✅ | An HTTP proxy is configured. | +| `reverseEngineered` | — | ✅ | Reverse-engineering tooling was detected. | +| `cydiaFound` | — | ✅ | Cydia was detected. | +| `tampered` | — | — | Reported only by `isTampered(bundleId)`, not by `checkForIssues`. | +| `unknown` | ✅ | ✅ | An issue this Dart version doesn't recognise. Android currently reports Magisk detection here. | + +Handle `unknown` as untrusted rather than ignoring it. + +## Important: test on real devices only + +This package must be tested on a physical device. + +Running on an emulator or simulator may cause false positives — for example, detection may +incorrectly report that the device is jailbroken or rooted. + +## Example + +See [`example/lib/main.dart`](example/lib/main.dart) for a complete app that runs every check +and prints the results. + +## Reference + +- [RootBeer](https://github.com/scottyab/rootbeer) +- [IOSSecuritySuite](https://github.com/securing/IOSSecuritySuite) +- [trust_fall](https://github.com/anish-adm/trust_fall) + +## License -- https://github.com/anish-adm/trust_fall +[MIT](LICENSE)