Skip to content

Commit

Permalink
Updated root module
Browse files Browse the repository at this point in the history
  • Loading branch information
cioccarellia committed Dec 22, 2022
1 parent 0ec6fdd commit d492651
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 23 deletions.
2 changes: 1 addition & 1 deletion rooting/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ dependencies {

// libsu
implementation("com.github.topjohnwu.libsu:core:5.0.3") {
exclude group: 'androidx.annotation', module: 'annotation'
// exclude group: 'androidx.annotation', module: 'annotation'
}
implementation "androidx.annotation:annotation:1.5.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal object TargetsAttestator {
if (targets.root.enabled) {
TargetOutputDump(
DetectableSystemTarget.ROOT,
CombinedBinaryDump("su", context.packageName, settings.allowRootCheck),
CombinedBinaryDump("su", context.packageName, settings.allowExplicitRootCheck),
isDumpEnabled = true
)
} else {
Expand All @@ -101,7 +101,7 @@ internal object TargetsAttestator {
if (targets.magisk.enabled) {
TargetOutputDump(
DetectableSystemTarget.MAGISK,
CombinedBinaryDump("magisk", context.packageName, settings.allowRootCheck),
CombinedBinaryDump("magisk", context.packageName, settings.allowExplicitRootCheck),
isDumpEnabled = true
)
} else {
Expand All @@ -113,7 +113,7 @@ internal object TargetsAttestator {
if (targets.busybox.enabled) {
TargetOutputDump(
DetectableSystemTarget.BUSYBOX,
CombinedBinaryDump("busybox", context.packageName, settings.allowRootCheck),
CombinedBinaryDump("busybox", context.packageName, settings.allowExplicitRootCheck),
isDumpEnabled = true
)
} else {
Expand All @@ -125,7 +125,7 @@ internal object TargetsAttestator {
if (targets.toybox.enabled) {
TargetOutputDump(
DetectableSystemTarget.TOYBOX,
CombinedBinaryDump("toybox", context.packageName, settings.allowRootCheck),
CombinedBinaryDump("toybox", context.packageName, settings.allowExplicitRootCheck),
isDumpEnabled = true
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ internal enum class SelinuxGetenforceStatus {
DISABLED, PERMISSIVE, ENFORCING;
}

/**
* This command may fail under different circumstances.
* We want to have no false positives. Thus, in case of unknown output
* we assume that the status is set to enforcing.
* Only if we find evidence of selinux being either disabled or permissive
* we can infer some information.
* */
internal suspend fun detectSelinux(): SelinuxGetenforceStatus = withContext(Dispatchers.IO) {
when (Shell.cmd("getenforce").exec().out.joinToString().lowercase()) {
"disabled" -> SelinuxGetenforceStatus.DISABLED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ import com.kevlar.rooting.dsl.settings.target.SystemTargetsBuilder
* Holds settings for [com.kevlar.rooting.KevlarRooting].
*
* Current available settings include:
* - System targets (allows to target the detection of specific system modifications)
* - System status (allows to detect system conditions)
* - Allow root check (whether kevlar will try to acquire root access to detect certain targets)
* - 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,
val systemStatus: SystemStatus,
val allowRootCheck: Boolean
val allowExplicitRootCheck: Boolean
)

/**
Expand All @@ -48,7 +49,7 @@ public data class RootingSettings(
public class RootingSettingsBuilder : DslBuilder<RootingSettings>() {
private var systemTargets: SystemTargets = SystemTargets.default()
private var systemStatus: SystemStatus = SystemStatus.default()
private var allowRootCheck: Boolean = false
private var allowExplicitRootCheck: Boolean = false

public fun targets(block: SystemTargetsBuilder.() -> Unit) {
systemTargets = SystemTargetsBuilder().apply(block).build()
Expand All @@ -58,9 +59,16 @@ public class RootingSettingsBuilder : DslBuilder<RootingSettings>() {
systemStatus = SystemStatusBuilder().apply(block).build()
}

public fun allowRootCheck() {
allowRootCheck = true
/**
* 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
}

override fun build(): RootingSettings = RootingSettings(systemTargets, systemStatus, allowRootCheck)
override fun build(): RootingSettings = RootingSettings(systemTargets, systemStatus, allowExplicitRootCheck)
}
16 changes: 8 additions & 8 deletions rooting/src/main/kotlin/com/kevlar/rooting/shell/Dumper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@ import kotlinx.coroutines.withContext


/**
* We make 3 passes with different permission levels, and for each one
* We make 3 asynchronous passes with different permission levels, and for each one
* we test commands and infer whether root access is installed on the device
* */
internal suspend fun CombinedBinaryDump(
binaryName: String,
packageName: String,
allowRootCheck: Boolean
allowExplicitRootCheck: Boolean
): CombinedBinaryDump = withContext(Dispatchers.IO) {
val appDump = async {
BinaryDump(binaryName, packageName, ExecutionLevel.APP, allowRootCheck)
BinaryDump(binaryName, packageName, ExecutionLevel.APP, allowExplicitRootCheck)
}

val binDump = async {
BinaryDump(binaryName, packageName, ExecutionLevel.SH, allowRootCheck)
BinaryDump(binaryName, packageName, ExecutionLevel.SH, allowExplicitRootCheck)
}

val suDump = async {
BinaryDump(binaryName, packageName, ExecutionLevel.SU, allowRootCheck)
BinaryDump(binaryName, packageName, ExecutionLevel.SU, allowExplicitRootCheck)
}

//awaitAll(appDump, binDump, suDump)
awaitAll(appDump, binDump, suDump)

CombinedBinaryDump(appDump.await(), binDump.await(), suDump.await())
}
Expand All @@ -55,7 +55,7 @@ internal suspend fun BinaryDump(
binaryName: String,
packageName: String,
level: ExecutionLevel,
allowRootCheck: Boolean
allowExplicitRootCheck: Boolean
): BinaryDump = withContext(Dispatchers.IO) {
when (level) {
// App-level check
Expand Down Expand Up @@ -114,7 +114,7 @@ internal suspend fun BinaryDump(
)
}
ExecutionLevel.SU -> {
if (allowRootCheck) {
if (allowExplicitRootCheck) {
val shellId = async {
// We execute the `id` command as root
Shell.su("id").exec()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class RootingRepository @Inject constructor(
}
}

allowRootCheck()
allowExplicitRootCheck()
}

/**
Expand All @@ -62,7 +62,6 @@ class RootingRepository @Inject constructor(
rooting.attestateTargets(context)
}


suspend fun attestateStatus(): StatusRootingAttestation = withContext(externalDispatcher) {
rooting.attestateStatus()
}
Expand Down

0 comments on commit d492651

Please sign in to comment.