Skip to content

Instantly share code, notes, and snippets.

@aslamanver
Last active January 14, 2020 06:11
Show Gist options
  • Select an option

  • Save aslamanver/560727f71beb7076f48458c455591545 to your computer and use it in GitHub Desktop.

Select an option

Save aslamanver/560727f71beb7076f48458c455591545 to your computer and use it in GitHub Desktop.
Tamper Detection - Android tamper detection, signature verification, root check and emulator detection in standard way.
android {
// ...
signingConfigs {
release {
storeFile file("/home/user/Documents/sign/test.jks")
storePassword "Test#123"
keyAlias "test"
keyPassword "Test#123"
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
useProguard true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.release
}
}
}
dependencies {
// ...
implementation 'com.scottyab:rootbeer-lib:0.0.7'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'
}
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Build;
import android.provider.Settings;
import android.util.Base64;
import com.scottyab.rootbeer.RootBeer;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import io.fabric.sdk.android.services.common.CommonUtils;
public class TC {
/*
* --------------------------------------------------------------------------------------------
* Base64 encoded SHA Key of application signature from test.jks
* B18EE15CC134393CEA12EB467BC3B15BB12793E2
* --------------------------------------------------------------------------------------------
*
* */
private static final String Sx1526 = "QjE4RUUxNUNDMTM0MzkzQ0VBMTJFQjQ2N0JDM0IxNUJCMTI3OTNFMg==";
/*
* ----------------------
* Signature verification
* ----------------------
*
* */
public static boolean s(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : packageInfo.signatures) {
// PLog.d("SIGN_KEY", gs1(signature.toByteArray()));
if (b6s(Sx1526).equals(gs1(signature.toByteArray()))) {
// PLog.d("SIGN_KEY", "VERIFIED SIGNATURE");
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/*
* -----------
* Root check
* -----------
*
* */
public static boolean r(Context context) {
boolean isEmulator = e(context);
String buildTags = Build.TAGS;
if (!isEmulator && buildTags != null && buildTags.contains("test-keys")) {
return true;
} else {
File file = new File("/system/app/Superuser.apk");
if (file.exists()) {
return true;
} else {
file = new File("/system/xbin/su");
return !isEmulator && file.exists();
}
}
}
/*
* -----------------
* Root fabric check
* -----------------
*
* */
public static boolean rf(Context context) {
return CommonUtils.isRooted(context);
}
/*
* --------------
* Emulator check
* --------------
*
* */
public static boolean e(Context context) {
String androidId = Settings.Secure.getString(context.getContentResolver(), "android_id");
return "sdk".equals(Build.PRODUCT) || "google_sdk".equals(Build.PRODUCT) || androidId == null;
}
/*
* -------------
* SHA1 - Getter
* -------------
*
* */
private static String gs1(byte[] sig) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA1");
digest.update(sig);
byte[] hashtext = digest.digest();
return bth(hashtext);
}
/*
* ----------------
* As root - check
* ----------------
*
* */
public static Boolean ar(String command) {
try {
Process process = Runtime.getRuntime().exec("su");
process.getOutputStream().write(command.getBytes());
process.getOutputStream().flush();
process.getOutputStream().close();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
// return output.toString();
return true;
} catch (IOException e) {
return false;
} catch (InterruptedException e) {
return false;
}
}
/*
* ------------------
* Root beer - check
* ------------------
*
* */
public static boolean rb(Context context) {
return new RootBeer(context).isRooted();
}
/*
* ----------------
* Execute app scan
* ----------------
*
* */
public static void eas(Context context) {
if (cte(context)) {
System.exit(1);
throw new RuntimeException();
}
}
/*
* --------------------------------------------------------------------------------------------
* Private methods
* --------------------------------------------------------------------------------------------
*
*
* ------------
* Bytes to Hex
* ------------
*
* */
private static String bth(byte[] bytes) {
final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
/*
* ----------------
* Base64 to String
* ----------------
*
* */
private static String b6s(String base64) throws UnsupportedEncodingException {
byte[] data = Base64.decode(base64, Base64.DEFAULT);
return new String(data, "UTF-8");
}
/*
* -------------------
* Can throw exception
* -------------------
*
* */
private static boolean cte(Context context) {
return TC.e(context) || TC.r(context) || TC.rf(context) || TC.ar("ls -a") || TC.rb(context) || !TC.s(context);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment