Skip to content

Commit

Permalink
Merge branch 'master' into convert-sample-to-kotlin
Browse files Browse the repository at this point in the history
* master:
  Update readme to clarify when the root cloak tests we valid
  Change log and increment version to 0.0.9
  add advice to use background thread in README (#150)
  Delete strings.xml (#149)
  Added appbrain shield to readme
  Update RootBeer.java (#142)
  Fixed documentation to fix issue #144 (#146)
  Add fstack protector. (#136)
  Add additional dangerous apps packages (#145)
  • Loading branch information
scottyab committed May 4, 2021
2 parents ab1c8b5 + 95821ec commit 645ae89
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 19 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# RootBeer ![image](./app/src/main/res/mipmap-xhdpi/ic_launcher.png)

[![RootBeer](https://www.appbrain.com/stats/libraries/shield/rootbeer.svg)](https://www.appbrain.com/stats/libraries/details/rootbeer/rootbeer)

A tasty root checker library and sample app. We've scoured the internets for different methods of answering that age old question... **Has this device got root?**

# Root checks
Expand All @@ -26,15 +28,16 @@ We call through to our native root checker to run some of its own checks. Native

## Disclaimer and limitations!

We love root! both [Scott](https://github.com/scottyab) and [Mat](https://github.com/stealthcopter) (the main contributors) use rooted devices. But we appreciate sometimes you might want to have a indication your app is running on a rooted handset. Plus we wanted to see if we could beat the root cloakers. So that's what this library gives you, an *indication* of root.
We love root! both [Scott](https://github.com/scottyab) and [Mat](https://github.com/stealthcopter) (the creators) own and use rooted devices (albeit not as daily driver). However we appreciate it can be useful to have an indication your app is running on a rooted device. Plus as hackday style project we wanted to see if we could beat the root cloakers at the time in 2015.

Remember **root==god**, so there's no 100% way to check for root.
Remember **root==god**, so there's no 100% guaranteed way to check for root! treat this as an *indication* of root.

<img src="./art/rootbeerjesus.png" width=200 />


### Root cloakers
We've tested the Rootbeer lib and it shows an indication of root when testing with the following root cloak apps. However Rootbeer is defeated when using a combination of the root cloakers activated at the same time.

In **2015** we successfully tested Rootbeer and it flagged an indication of root when testing with the following root cloak apps. However Rootbeer was defeated when using a combination of the root cloakers activated at the same time.

Tested cloakers:

Expand All @@ -52,7 +55,7 @@ if (rootBeer.isRooted()) {
}
```

You can also call each of the checks individually as the sample app does.
You can also call each of the checks individually as the sample app does. It is advisable to call `isRooted()` from a background thread as it involves disk I/O.

### False positives

Expand All @@ -75,7 +78,7 @@ Available on [maven central](https://search.maven.org/#search%7Cga%7C1%7Ca%3A%22

```java
dependencies {
implementation 'com.scottyab:rootbeer-lib:0.0.8'
implementation 'com.scottyab:rootbeer-lib:0.0.9'
}
```

Expand Down
8 changes: 8 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
Change Log

#v0.0.9

* Support for Android TV devices #129 @deepakpk009
* Add additional dangerous apps packages #145 @Fi5t
* Add fstack protector #136 @slawert

#v0.0.8

* Removed busybox from the default root checking methods
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

VERSION_NAME=0.0.8
VERSION_CODE=8
VERSION_NAME=0.0.9
VERSION_CODE=9
GROUP=com.scottyab


Expand Down
21 changes: 20 additions & 1 deletion rootbeerlib/src/main/java/com/scottyab/rootbeer/Const.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,26 @@ private Const() throws InstantiationException {
"com.ramdroid.appquarantine",
"com.ramdroid.appquarantinepro",
"com.android.vending.billing.InAppBillingService.COIN",
"com.chelpus.luckypatcher"
"com.android.vending.billing.InAppBillingService.LUCK",
"com.chelpus.luckypatcher",
"com.blackmartalpha",
"org.blackmart.market",
"com.allinone.free",
"com.repodroid.app",
"org.creeplays.hack",
"com.baseappfull.fwd",
"com.zmapp",
"com.dv.marketmod.installer",
"org.mobilism.android",
"com.android.wp.net.log",
"com.android.camera.update",
"cc.madkite.freedom",
"com.solohsu.android.edxp.manager",
"org.meowcat.edxposed.manager",
"com.xmodgame",
"com.cih.game_cih",
"com.charles.lpoqasert",
"catch_.me_.if_.you_.can_"
};

public static final String[] knownRootCloakingPackages = {
Expand Down
66 changes: 58 additions & 8 deletions rootbeerlib/src/main/java/com/scottyab/rootbeer/RootBeer.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ public RootBeer(Context context) {
}

/**
* Run all the checks.
* To run the same check but without looking for the busybox binary to avoid a false positive for certain devices please
* see {@link #isRootedWithoutBusyBoxCheck() isRootedWithoutBusyBoxCheck}
* Run all the root detection checks.
*
* @return true, we think there's a good *indication* of root | false good *indication* of no root (could still be cloaked)
*/
Expand All @@ -52,12 +50,13 @@ public boolean isRooted() {
* @deprecated This method is deprecated as checking without the busybox binary is now the
* default. This is because many manufacturers leave this binary on production devices.
*/
@Deprecated
public boolean isRootedWithoutBusyBoxCheck() {
return isRooted();
}

/**
* Run all the checks apart including checking for the busybox binary.
* Run all the checks including checking for the busybox binary.
* Warning: Busybox binary is not always an indication of root, many manufacturers leave this
* binary on production devices
* @return true, we think there's a good *indication* of root | false good *indication* of no root (could still be cloaked)
Expand Down Expand Up @@ -297,31 +296,82 @@ public boolean checkForDangerousProps() {
public boolean checkForRWPaths() {

boolean result = false;


//Run the command "mount" to retrieve all mounted directories
String[] lines = mountReader();

if (lines == null){
// Could not read, assume false;
return false;
}

//The SDK version of the software currently running on this hardware device.
int sdkVersion = android.os.Build.VERSION.SDK_INT;

/**
*
* In devices that are running Android 6 and less, the mount command line has an output as follow:
*
* <fs_spec_path> <fs_file> <fs_spec> <fs_mntopts>
*
* where :
* - fs_spec_path: describes the path of the device or remote filesystem to be mounted.
* - fs_file: describes the mount point for the filesystem.
* - fs_spec describes the block device or remote filesystem to be mounted.
* - fs_mntopts: describes the mount options associated with the filesystem. (E.g. "rw,nosuid,nodev" )
*
*/

/** In devices running Android which is greater than Marshmallow, the mount command output is as follow:
*
* <fs_spec> <ON> <fs_file> <TYPE> <fs_vfs_type> <(fs_mntopts)>
*
* where :
* - fs_spec describes the block device or remote filesystem to be mounted.
* - fs_file: describes the mount point for the filesystem.
* - fs_vfs_type: describes the type of the filesystem.
* - fs_mntopts: describes the mount options associated with the filesystem. (E.g. "(rw,seclabel,nosuid,nodev,relatime)" )
*/

for (String line : lines) {

// Split lines into parts
String[] args = line.split(" ");

if (args.length < 4){
if ((sdkVersion <= android.os.Build.VERSION_CODES.M && args.length < 4)
|| (sdkVersion > android.os.Build.VERSION_CODES.M && args.length < 6)) {
// If we don't have enough options per line, skip this and log an error
QLog.e("Error formatting mount line: "+line);
continue;
}

String mountPoint = args[1];
String mountOptions = args[3];
String mountPoint;
String mountOptions;

/**
* To check if the device is running Android version higher than Marshmallow or not
*/
if (sdkVersion > android.os.Build.VERSION_CODES.M) {
mountPoint = args[2];
mountOptions = args[5];
} else {
mountPoint = args[1];
mountOptions = args[3];
}

for(String pathToCheck: Const.pathsThatShouldNotBeWritable) {
if (mountPoint.equalsIgnoreCase(pathToCheck)) {

/**
* If the device is running an Android version above Marshmallow,
* need to remove parentheses from options parameter;
*/
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.M) {
mountOptions = mountOptions.replace("(", "");
mountOptions = mountOptions.replace(")", "");

}

// Split options out and compare against "rw" to avoid false positives
for (String option : mountOptions.split(",")){

Expand Down
1 change: 1 addition & 0 deletions rootbeerlib/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ include $(CLEAR_VARS)
LOCAL_MODULE := tool-checker
LOCAL_SRC_FILES := toolChecker.cpp
LOCAL_LDLIBS := -llog
LOCAL_CPPFLAGS := -fstack-protector-all

include $(BUILD_SHARED_LIBRARY)
3 changes: 0 additions & 3 deletions rootbeerlib/src/main/res/values/strings.xml

This file was deleted.

0 comments on commit 645ae89

Please sign in to comment.