From 9aa9537a5d4ac13b27452035f6d1be81fd3aacbb Mon Sep 17 00:00:00 2001 From: cioccarellia Date: Fri, 23 Dec 2022 14:31:47 +0100 Subject: [PATCH] Enabled parallelization & updated docs --- .idea/deploymentTargetDropDown.xml | 17 +++++++++ docs/pages/modules/rooting/implementation.md | 35 +++++++++++++++++++ docs/pages/modules/rooting/rooting.md | 2 +- rooting/build.gradle | 7 ++-- .../detection/status/EmulatorDetector.kt | 4 +++ .../detection/status/SelinuxDetector.kt | 9 +++-- .../detection/status/TestKeysDetector.kt | 3 ++ .../rooting/dsl/settings/RootingSettings.kt | 2 -- .../rooting/dsl/settings/target/Target.kt | 12 +++++++ .../kotlin/com/kevlar/rooting/shell/Dumper.kt | 2 +- .../showcase/data/repo/RootingRepository.kt | 5 --- 11 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c23244 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/pages/modules/rooting/implementation.md b/docs/pages/modules/rooting/implementation.md index 0a14c4a..ee1de3b 100644 --- a/docs/pages/modules/rooting/implementation.md +++ b/docs/pages/modules/rooting/implementation.md @@ -42,6 +42,41 @@ You go ahead and request whichever attestation(s) you need. The will produce two We go ahead and create a working single-attestation example (for system modifications aka targets). For two attestations refer to the sample code in the `:showcase` module of the github repository. +## Configuration +As we said, the kinds of checks you can run are divided in two different categories, `targets` and `status`. +The first is to check for eventual system modification, the former to check for eventual in-system status. + +The following complete configuration runs every check that kevlar disposes. + +In details: + +- `flagPermissive()`, if enabled, will report `DetectableSystemStatus.SELINUX` also if selinux status is set to permissive status (which is a stricter criteria), while by default it will only trip if selinux is disabled; +- `allowExplicitRootCheck()`, if enabled, will use more aggressive checks to determine if any of the required targets is installed, including explicitly trying to acquire root access. + + +```kotlin +private val rooting = KevlarRooting { + targets { + root() + magisk() + busybox() + toybox() + xposed() + } + + allowExplicitRootCheck() + + status { + testKeys() + emulator() + selinux { + flagPermissive() + } + } +} +``` + + ## In-Place This is the most concise way to implement rooting. diff --git a/docs/pages/modules/rooting/rooting.md b/docs/pages/modules/rooting/rooting.md index 323aa59..e5c3405 100644 --- a/docs/pages/modules/rooting/rooting.md +++ b/docs/pages/modules/rooting/rooting.md @@ -68,7 +68,7 @@ To [implement](implementation.md) this, you initialize `KevlarRooting` and provi } } - allowRootCheck() + allowExplicitRootCheck() } ``` diff --git a/rooting/build.gradle b/rooting/build.gradle index 3cf82a9..6080e67 100755 --- a/rooting/build.gradle +++ b/rooting/build.gradle @@ -82,9 +82,10 @@ dependencies { testImplementation "com.google.truth:truth:1.1.3" testImplementation "org.robolectric:robolectric:4.9" - // libsu - implementation("com.github.topjohnwu.libsu:core:5.0.3") { - // exclude group: 'androidx.annotation', module: 'annotation' + // libsu, fixed at 5.0.2 + //noinspection GradleDependency + implementation("com.github.topjohnwu.libsu:core:5.0.2") { + exclude group: 'androidx.annotation', module: 'annotation' } implementation "androidx.annotation:annotation:1.5.0" } diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/EmulatorDetector.kt b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/EmulatorDetector.kt index 84ab8f1..73cef2d 100644 --- a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/EmulatorDetector.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/EmulatorDetector.kt @@ -20,6 +20,10 @@ package com.kevlar.rooting.detection.status import android.os.Build +/** + * Analyzes environment DEVICE, FINGERPRINT, HARDWARE, MODEL, MANUFACTURER and PRODUCT to + * search for some specific emulator characteristics + * */ internal fun detectEmulator(): Boolean = (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) || Build.FINGERPRINT.startsWith("generic") diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/SelinuxDetector.kt b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/SelinuxDetector.kt index bea59b7..559df16 100644 --- a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/SelinuxDetector.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/SelinuxDetector.kt @@ -24,6 +24,9 @@ internal enum class SelinuxGetenforceStatus { DISABLED, PERMISSIVE, ENFORCING; } +private const val SX_DISABLED = """disabled""" +private const val SX_PERMISSIVE = """permissive""" + /** * This command may fail under different circumstances. * We want to have no false positives. Thus, in case of unknown output @@ -32,9 +35,9 @@ internal enum class SelinuxGetenforceStatus { * we can infer some information. * */ internal suspend fun detectSelinux(): SelinuxGetenforceStatus = withContext(Dispatchers.IO) { - when (Shell.cmd("getenforce").exec().out.joinToString().lowercase()) { - "disabled" -> SelinuxGetenforceStatus.DISABLED - "permissive" -> SelinuxGetenforceStatus.PERMISSIVE + when (Shell.cmd("getenforce").exec().out.joinToString().lowercase().trim()) { + SX_DISABLED -> SelinuxGetenforceStatus.DISABLED + SX_PERMISSIVE -> SelinuxGetenforceStatus.PERMISSIVE else -> SelinuxGetenforceStatus.ENFORCING } } \ No newline at end of file diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/TestKeysDetector.kt b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/TestKeysDetector.kt index b4fc07f..108ec16 100644 --- a/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/TestKeysDetector.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/detection/status/TestKeysDetector.kt @@ -18,6 +18,9 @@ package com.kevlar.rooting.detection.status import android.os.Build +/** + * Simply detects whether test keys are present in the build tags. + * */ internal fun detectTestKeys(): Boolean { val buildTags = Build.TAGS return buildTags != null && buildTags.contains("test-keys") diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/RootingSettings.kt b/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/RootingSettings.kt index 7ea5269..9d1181f 100755 --- a/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/RootingSettings.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/RootingSettings.kt @@ -29,8 +29,6 @@ import com.kevlar.rooting.dsl.settings.target.SystemTargetsBuilder * Current available settings include: * - System targets (allows to target the detection of specific system modifications) * - System status (allows to detect system conditions) - * - Allow explicit root check (whether kevlar will try to acquire explicit root access to detect - * certain targets, instead of using just passive reconnaissance) * */ public data class RootingSettings( val systemTargets: SystemTargets, diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/target/Target.kt b/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/target/Target.kt index dd9e8b4..d6be6d8 100755 --- a/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/target/Target.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/dsl/settings/target/Target.kt @@ -53,6 +53,7 @@ public data class XposedTarget( @RootingDslMarker public class RootTargetBuilder { private var enabled: Boolean = false + private var allowExplicitRootCheck: Boolean = false internal fun enable() { enabled = true @@ -62,6 +63,17 @@ public class RootTargetBuilder { enabled = false } + /** + * By default kevlar does not run the `su` binary. Instead, it passively analyzes the + * system environment to detect root access. + * + * If you don't mind having your application ask for root permission, you can enable this + * flag, so that kevlar will be trying to acquire root access as an additional check. + * */ + public fun allowExplicitRootCheck() { + allowExplicitRootCheck = true + } + public fun build(): RootTarget = RootTarget(enabled) } diff --git a/rooting/src/main/kotlin/com/kevlar/rooting/shell/Dumper.kt b/rooting/src/main/kotlin/com/kevlar/rooting/shell/Dumper.kt index afb24ec..06ad728 100644 --- a/rooting/src/main/kotlin/com/kevlar/rooting/shell/Dumper.kt +++ b/rooting/src/main/kotlin/com/kevlar/rooting/shell/Dumper.kt @@ -75,7 +75,7 @@ internal suspend fun BinaryDump( Shell.sh("run-as $packageName $binaryName").exec() } - //awaitAll(shellId, binaryPathExtraction, binaryTest) + awaitAll(shellId, binaryPathExtraction, binaryTest) BinaryDump( binaryName = binaryName, diff --git a/showcase/src/main/kotlin/com/kevlar/showcase/data/repo/RootingRepository.kt b/showcase/src/main/kotlin/com/kevlar/showcase/data/repo/RootingRepository.kt index 4d1de24..f2d551c 100755 --- a/showcase/src/main/kotlin/com/kevlar/showcase/data/repo/RootingRepository.kt +++ b/showcase/src/main/kotlin/com/kevlar/showcase/data/repo/RootingRepository.kt @@ -53,11 +53,6 @@ class RootingRepository @Inject constructor( allowExplicitRootCheck() } - /** - * This uses the default settings, only targets/root and status/emulator - * */ - private val defaultRooting = KevlarRooting() - suspend fun attestateRoot(): TargetRootingAttestation = withContext(externalDispatcher) { rooting.attestateTargets(context) }