How to disallow emulator, isdebuggable check for debug build - android

I am resolving some security defects for my app.
Defect is:
Should not allow release app to be run in emulator
Release app should not be debuggable
Should not connect to debugger
Release app should be installed from play store not from other resource
And app signature verification
Code 1)
private static boolean isEmulator() {
try {
boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
boolean emu = getSystemProperty("ro.kernel.qemu").length() > 0;
boolean sdk = getSystemProperty("ro.product.model").equals("sdk");
if (emu || goldfish || sdk) {
return true;
}
} catch (Exception e) {
}
return false;
}
Code 2)
public static boolean isDebuggable(Context context) {
if (IdscProperties.getIsDebug()) {
return true;
}
if (isDebuggableEnabled(context) || detectDebugger() || detectThreadCpuTimeNanos()) {
return true;
}
return false;
}
private static boolean isDebuggableEnabled(Context context) {
return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
Code 3)
private static boolean detectDebugger() {
return Debug.isDebuggerConnected();
}
Code 4)
private static boolean isInstallerPlayStore(Context context) {
final String installer = context.getPackageManager().getInstallerPackageName(context.getPackageName());
return installer != null && installer.startsWith(PLAY_STORE_APP_ID);
}
Code 5)
private static boolean isAppSignatureMatches(Context context) {
String signature = PackageVerifier.getCertificateHash(context, context.getPackageName());
return SIGNATURE.equals(signature);
}
So, My aim is to not allow these checks in debug builds.
We shall create a flag in some prob file and read it when these checks happen and disallow the function execution.
But the flag shall be modified by the hacker and re-pack the APK to dis-allow these checks.
My expectation is allow these checks in release build and not in debug build without any modifiable flag checks.

Before you start on this path, I want to make sure that you realize 2 things:
Every precaution you implement can be (relatively easily) circumvented on a rooted device
Your app can be easily decompiled into bytecode offline, and any security-related code will be plainly visible.
So, knowing this, if your aim is to prevent piracy, you also need to realize that anything you do will only add some extra steps for the attacker to go through. But if someone really wants to do it, it will not stop them.
If you still want advice on how to implement this, let me know

Related

How to check if application is running on background?

I am using firebase to send notifications to the application and based on the notification the user will be directed to some activity. so far so good, the problem I am having is that if the application is running on background the activity that will be shown is the main activity but I can not quite managed it to do it.
I believe there ar several questions like this, but do not quite get the answer I am looking for.
Any help or suggestion would be great, thanks
try
/**Flag to determine if the Activity is visible*/
private static boolean activityVisible;
private static boolean activityDestroy;
/**Is the application actually visible on the mobile screen*/
public static boolean isActivityVisible(){
return activityVisible;
}
/**Is the application actually destroyed*/
public static boolean isActivityDestroy(){
return activityDestroy;
}
/**Is the application actually destroyed*/
public static void activityDestroy(boolean isDestroy){
activityDestroy = isDestroy;
}
/**Is the application actually in the background*/
public static boolean isActivityInBackground(){
return !activityVisible;
}
/**Change the state of the Application to resume*/
public static void activityResumed() {
activityVisible = true;
}
/**Change the state of the Application to paused*/
public static void activityPaused() {
activityVisible = false;
}
and then for checking
Application app = ((Application)getApplicationContext());
boolean visible = app.isActivityVisible();
Android 10 (API level 29) and higher place restrictions on when apps can start activities when the app is running in the background. These restrictions help minimize interruptions for the user and keep the user more in control of what's shown on their screen.
You could use importance field of ActivityManager.
Below the method for Xamarin using by C#, but it's pretty similiar to Java.
P.S.: If you want I could port that code to Java
public static Importance GetAppState(Context context, string packageName)
{
try
{
var manager = (ActivityManager)context.GetSystemService(Context.ActivityService);
var processes = manager.RunningAppProcesses;
if (processes != null)
foreach (var process in processes)
if (process.ProcessName.Equals(packageName))
return process.Importance;
}
catch
{
}
return Importance.Gone;
}

How to prevent app from being cached in android

After some research I found that Android likes to cache some parts of an app while installing to improve the performance while runtime.
Is there a way to prevent Android from caching things from my app?
I am sharing my app via my website and users install and update the app manually. As soon as I update my app some Activities and Code-parts seems to be cached on their devices.
You could delete your cache everytime before you update or before you close you application.
Code to clear the cache:
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
Call Trimcache when you want to clear the cache (before you update perhaps? or override the onStop() method, to clear the cache when the application is going to close.
The way I see you should also have a cache problem when you're NOT updating your app.
If you want to force a server fetch when you upgrade your app you could store a boolean in Shared Preferences, using a key associated with the app version. So when you install version 1 you fetch and make putsBoolean(version, true) where version == "1". When version 2 is installed you'll find a false, which will trigger a fetch, followed by setting putsBoolean(version, true) - but in this case version == "2".
If you are reusing information that have a different meaning when you update, the solution is storing the information in a different part of the cache, so it's not sent to an activity that is not prepared to display it.
Otherwise the solution by #jordy-dieltjens seems a good one.

pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) not giving corerct answer

I want to check if a device has any cameras before trying to open a qr code reader.
I have the following code:
public boolean checkDeviceCompatibility() {
PackageManager pm = context.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
// use front camera
Toast.makeText(
context,
"This device does not have a back camera so it has automatically reverted to the front camera",
Toast.LENGTH_SHORT).show();
return true;
}
} else {
util.displayErrorDialog(
context,
"This device does not have any cameras and therefore cannot make use of the QR Code feature.");
return false;
}
}
But now if I run this code in debug mode on my galaxy S3 with two cameras. the first if statement is returned false.
Why could this be?
FEATURE_CAMERA_ANY was added in Android 4.2. hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) should return false for any pre-4.2 device. If your S3 is still on 4.1, that would explain your problem.
To make it clear.
FEATURE_CAMERA_ANY was added to Android 4.2 ( API-17): Android - developers.
code:
public static boolean hasCamera(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
}
Note that using this code will return false if device under version 4.2:
Then you should know that there is a bug with emulator when use FEATURE_CAMERA_ANY feature (with android 4.2 and above). see: Emulator does not honour Camera support flag
Thats why Im still using old way even its deprecated:
public static boolean hasCamera() {
return android.hardware.Camera.getNumberOfCameras() > 0;
}

Two checks of Content Resolver for Allow Mock Locations providing different results

I have the following code that evaluates to true in the emulator (OS 2.3.3) when "applications > settings > development > allow mock locations" is unchecked. I would expect the method to return false but it returns true.
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
return false;
}
else {
return true;
}
}
The following change returns false, as expected (BTW what is better .equals or .ContentEquals?):
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0")) { //.contentEquals("0")
return false;
}
else {
return true;
}
}
I prefer the first example because it should allow for cases where a null value may exist, assigning a default of 0 and still allowing execution of the logic without failure (in fact, I suspect this case may exist but have not proved it - e.g. a manufacturer implements Android without all the these settings established (i.e. some like Allow Mock Locations would begin their life as null)...waiting until a user check's the setting before writing a 1 (or 0 when unchecked) to the table).
So what is the problem? Well, I get the feeling from bug reports that different devices handle this check differently but not having access to all device types, I am looking for recommendations on how to handle generically / the best. Also, why would the first example not work?
Well I decided to simply use the following check:
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).contentEquals("1")) {
return true;
}
else {
return false;
}
}
This method, of course, deals with the null case appropriately--returning false.
I cannot say why the code in the original question does not work...maybe a bug in the SDK.

Is it possible to find out if an Android application runs as part of an instrumentation test

Is there a runtime check for an application to find out if it runs as part of an instrumentation test?
Background: Our application performs a database sync when starting. But that should happen only when started regularly. It especially interferes with the instrumentation tests testing the db sync. Not surprisingly.
And with all the other tests it's just a waste of CPU cycles.
A much simpler solution is check for a class that would only be present in a test classpath, works with JUnit 4 (unlike the solution using ActivityUnitTestCase) and doesn't require to send custom intents to your Activities / Services (which might not even be possible in some cases)
private boolean isTesting() {
try {
Class.forName("com.company.SomeTestClass");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
Since API Level 11, the ActivityManager.isRunningInTestHarness() method is available. This might do what you want.
If you are using Robolectric, you can do something like this:
public boolean isUnitTest() {
String device = Build.DEVICE;
String product = Build.PRODUCT;
if (device == null) {
device = "";
}
if (product == null) {
product = "";
}
return device.equals("robolectric") && product.equals("robolectric");
}
If you're using ActivityUnitTestCase, you could set a custom Application object with setApplication, and have a flag in there to switch database sync on or off? There's an example of using a custom Application object on my blog:
http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-3/
You can pass an intent extra to your activity indicating it's under test.
1) In your test, pass "testMode" extra to your activity:
public void setUp() throws Exception {
super.setUp();
Intent activityIntent = new Intent();
activityIntent.putExtra("testMode", true);
setActivityIntent(activityIntent);
}
2) In your activity, check for testMode:
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getBoolean("testMode")) {
// disable your database sync
}
d= (◕‿↼ ) Great answer, but if some library developer (like me) wants to know if the Host (or App using the library) is being tested, then try:
import android.content.pm.ApplicationInfo;
// ...
private static int wasTestRun = 0xDEAD;
/**
* Should only be used to speed up testing (no behavior change).
* #return true in tests, if Gradle has the right dependencies.
*/
public static boolean isTestRun(#NonNull Context context) {
if (wasTestRun != 0xDEAD) {
return wasTestRun != 0;
}
// Ignore release builds (as App may be using JUnit by mistake).
if (isDebuggable(context)) {
try {
Class.forName("org.junit.runner.Runner");
wasTestRun = 1;
return true;
} catch (ClassNotFoundException ignored) {
}
}
wasTestRun = 0;
return false;
}
public static boolean isDebuggable(#Nullable Context context) {
return context != null && (context.getApplicationContext()
.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
Note that I am not using any AtomicBoolean or other helpers, as it is already pretty fast (and locking may just bring the speed down).
You can try this
if (isRunningTest == null) {
isRunningTest = false;
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
List<StackTraceElement> list = Arrays.asList(stackTrace);
for (StackTraceElement element : list) {
if (element.getClassName().startsWith("androidx.test.runner.MonitoringInstrumentation")) {
isRunningTest = true;
break;
}
}
}
This work for me because no actual device is running
public static boolean isUnitTest() {
return Build.BRAND.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.PRODUCT.startsWith(Build.UNKNOWN);
}

Categories

Resources