# MobShield Android Open-source mobile app hardening for Android: modular RASP detectors, signal aggregation, and per-build native personalization. [![Android CI](https://github.com/Inforaam/MobShield-Android/actions/workflows/android-ci.yml/badge.svg)](https://github.com/Inforaam/MobShield-Android/actions/workflows/android-ci.yml) [![Maven Central](https://img.shields.io/maven-central/v/io.github.inforaam/mobshield-core)](https://central.sonatype.com/artifact/io.github.inforaam/mobshield-core) [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) ![minSdk: 24](https://img.shields.io/badge/minSdk-24-lightgrey.svg) MobShield runs a set of detection modules, aggregates their weighted signals into `ThreatEvent`s, and reports your app's runtime posture through a listener — so your app can react to root, hooking, debugging, emulator, and integrity-tampering conditions. ## Why MobShield - **Signals, not a verdict.** Each check emits a weighted, confidence-scored `Signal`. A pure aggregator turns them into a `ThreatEvent` per threat type (root, hooks, debugger, emulator, integrity), so you decide what a score means for your app instead of getting an opaque pass/fail. - **Modular.** Take only the detectors you need: `mobshield-core` plus any of the root, hooks, debugger, environment and integrity modules. - **Detect-only by default.** MobShield reports; it never kills your process unless you opt in with a `TerminationPolicy`. - **No account, no telemetry.** There is no backend and no outbound network calls; the only socket use is the Frida check, which probes `127.0.0.1` on the device. Reports stay in your app; send them to your own server if you want them (see `MobShield.currentSignedReport`). - **Modern-root aware.** Checks target Magisk, Zygisk, Shamiko and KernelSU artifacts, and Frida and LSPosed instrumentation, not just a `su` file lookup. - **Auditable.** Every signal, its technique and its default weight is documented in [docs/detection](docs/detection), with a clean-vs-compromised [validation matrix](docs/validation.md). Coverage is mapped to OWASP MASVS in [docs/masvs-mapping.md](docs/masvs-mapping.md). ### When to use it (and when not to) - **Use it** for client-side posture signals you can act on or forward to your backend: warn, restrict a feature, step up authentication, or flag a session. - **Pair it with server-side checks.** Client-side detection can be bypassed by a determined attacker with control of the device. Treat MobShield as one layer of defense in depth, and verify anything that matters on your server (for example with [Play Integrity](https://developer.android.com/google/play/integrity) attestation). It does not replace it. - **Native detectors are best-effort.** Several checks read `/proc` and probe the runtime, which is the same ground an attacker's tooling operates on. Expect cat-and-mouse; keep the library updated. ## Modules | Module | Purpose | |--------|---------| | `mobshield-core` | Public API facade, aggregator, validation harness, JNI bridge (skeleton) | | `mobshield-detect-root` | Magisk, Zygisk, Shamiko, KernelSU signals | | `mobshield-detect-hooks` | Frida, LSPosed, Xposed | | `mobshield-detect-debugger` | ptrace, TracerPid | | `mobshield-detect-environment` | Emulator, automation, ADB | | `mobshield-detect-integrity` | Signature and build anchor | | `mobshield-gradle-plugin` | Per-build personalization (`io.mobshield.personalize`) | | `mobshield-sample-app` | Compose integration demo (all detectors) | ## Why MobShield - **Fully auditable.** The detection logic is open source, so you can review it, fork it, and audit it. There's no binary blob. - **No telemetry.** MobShield makes no network calls. Threat events go only to your listener and, if you choose, your backend. - **Modular.** Add only the detectors you need. - **Safe to roll out.** It's detect-only by default and never kills your process unless you opt in. - **Harder to bypass generically.** The Gradle plugin personalizes each build, so one off-the-shelf bypass script doesn't fit every app. - **Server-verifiable.** Signed posture reports let your backend decide whether to trust a session. MobShield raises the cost of an attack. Like any client-side protection, it can't make an app unbreakable, so pair it with server-side checks. ## How it compares | | MobShield | [freeRASP](https://github.com/talsec/Free-RASP-Android) | [RootBeer](https://github.com/scottyab/rootbeer) | |---|---|---|---| | License | Apache-2.0 | MIT wrapper + proprietary binary core, fair-usage policy | Apache-2.0 | | Detection logic auditable | ✅ | ❌ (closed binary) | ✅ | | Sends data to a vendor | ❌ No network calls | Incident data feeds Talsec's weekly Security Report | ❌ | | Root (Magisk, Zygisk, Shamiko, KernelSU) | ✅ | ✅ | Basic (su binary, root/cloak apps, props) | | Hooking (Frida, LSPosed, Xposed) | ✅ | ✅ | ❌ | | Debugger | ✅ | ✅ | ❌ | | Emulator / automation / ADB | ✅ | ✅ | ❌ | | Signature / repackaging integrity | ✅ | ✅ | ❌ | | Backend-verifiable report | ✅ Signed report, your own key | AppiCrypt (commercial plan) | ❌ | | Per-build personalization | ✅ | ❌ | ❌ | | Platforms | Android + [iOS](https://github.com/Inforaam/MobShield-iOS) | Android, iOS, Flutter, RN, Cordova, Capacitor | Android | freeRASP is ahead on cross-platform framework support and a few extra checks, such as installation source and screen capture. If you need those today, it's a good choice. *Comparison based on each project's public README as of October 2026. Corrections are welcome via PR.* ## OWASP MASVS mapping | MASVS v2 control | MobShield module | |---|---| | MASVS-RESILIENCE-1: platform integrity | `mobshield-detect-root`, `mobshield-detect-environment` | | MASVS-RESILIENCE-2: anti-tampering | `mobshield-detect-integrity` | | MASVS-RESILIENCE-4: anti-dynamic analysis | `mobshield-detect-hooks`, `mobshield-detect-debugger`, `mobshield-detect-environment` | ## Requirements - JDK 17+ - Android SDK 34 - Gradle 8.7+ (wrapper included) - NDK **28.0.13004108** (via SDK Manager; required for **16 KB page size** / Play compliance) Native modules are built with `ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON` and 16 KB ELF linker alignment. Rebuild and publish a new tag after upgrading the NDK. ## Install ### Maven Central (recommended) MobShield is published to Maven Central under the `io.github.inforaam` group. Add `mobshield-core`, plus only the detectors you need: ```kotlin dependencies { val mobshield = "1.0.10" implementation("io.github.inforaam:mobshield-core:$mobshield") // optional detectors: implementation("io.github.inforaam:mobshield-detect-root:$mobshield") implementation("io.github.inforaam:mobshield-detect-hooks:$mobshield") implementation("io.github.inforaam:mobshield-detect-debugger:$mobshield") implementation("io.github.inforaam:mobshield-detect-environment:$mobshield") implementation("io.github.inforaam:mobshield-detect-integrity:$mobshield") } ``` The `io.mobshield.personalize` Gradle plugin is not part of the Maven Central release, because its plugin id sits outside the `io.github.inforaam` namespace. ### JitPack (single umbrella dependency) ```kotlin // settings.gradle.kts -> dependencyResolutionManagement.repositories maven { url = uri("https://jitpack.io") } // build.gradle.kts dependencies { implementation("com.github.Inforaam:MobShield-Android:1.0.8") } ``` JitPack builds from git tags, so it offers the tagged releases (latest: 1.0.8). The umbrella artifact is a single AAR that bundles core and all five detect modules, and it cannot be trimmed to individual modules; use Maven Central for that. ## Quick start Register the detectors, implement a listener, and start MobShield with an application `Context`. It runs in **detect-only** mode by default (it reports; it never terminates your process). ```kotlin import io.mobshield.core.MobShield import io.mobshield.core.MobShieldConfig import io.mobshield.core.MobShieldListener import io.mobshield.core.ThreatEvent import io.mobshield.detect.root.RootDetectionRegistrar import io.mobshield.detect.hooks.HookDetectionRegistrar import io.mobshield.detect.debugger.DebugDetectionRegistrar import io.mobshield.detect.environment.EmulatorDetectionRegistrar import io.mobshield.detect.integrity.IntegrityDetectionRegistrar val listener = object : MobShieldListener { override fun onThreat(event: ThreatEvent) { Log.w("MobShield", "threat: ${event.type} ${event.severity} score=${event.score}") } override fun onAllChecksFinished(events: List) { Log.i("MobShield", "scan finished: ${events.size} threat(s)") } } val config = MobShieldConfig() // detect-only by default RootDetectionRegistrar.register(context, config) HookDetectionRegistrar.register(context, config) DebugDetectionRegistrar.register(context, config) EmulatorDetectionRegistrar.register(context, config) IntegrityDetectionRegistrar.register(context, config) MobShield.start(context, config, listener) ``` Read the current posture at any time, or stop scanning: ```kotlin val state = MobShield.getState() // riskLevel, activeThreats, running, lastScanMs MobShield.stop() ``` Common configuration (all optional): ```kotlin val config = MobShieldConfig.builder() .periodicIntervalSec(30) // rescan every 30s (default: one scan at start) .expectedPackageId("com.example.app") // anchor package-id integrity .expectedSigners(listOf("")) // anchor signing-cert integrity .detectOnly(false) // opt in to termination .terminationPolicy(TerminationPolicy.EXIT_ON_CRITICAL) .build() ``` For a signed posture report you can verify on your backend, see `MobShield.currentSignedReport(key)`. ## Build ```bash ./gradlew :mobshield-sample-app:assembleDebug ./gradlew test ``` See [mobshield-sample-app/README.md](mobshield-sample-app/README.md) for a walkthrough. ## Documentation - [Detection validation matrix](docs/validation.md) — every signal each module emits and the clean vs compromised baselines. - [Detection notes](docs/detection) — per-detector background. ## Release Pushing a `v*.*.*` tag makes that release installable through JitPack, and runs [`release.yml`](.github/workflows/release.yml), which stages the six library modules in the Sonatype Central Portal. The deployment is published by hand from the portal after it has been checked. The workflow needs the `maven-central` environment and these repository secrets: `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD` (a Central Portal user token), `SIGNING_KEY` (ASCII-armored GPG private key), `SIGNING_KEY_ID` and `SIGNING_KEY_PASSWORD`. Local verification: ```bash ./gradlew :mobshield-core:publishToMavenLocal -PVERSION_NAME=1.0.7-SNAPSHOT ``` ## License All of MobShield Android (Kotlin, Gradle and native C/C++ sources) is licensed under [Apache-2.0](LICENSE).