Bypassing Android Anti Emulation part I

Post Date

Published on
Authors
Bypassing Android Anti Emulation part I

TLDR: I wrote this publication some time ago and some people asked me if I could re-upload it because it was on my personal site juanurs.com, that’s why you can find it here again :) Enjoy!

Introduction

This is the first of a series of posts where we will focus on solving Android Reversing challenges. The challenge is focused on a binary protection called anti-emulation, (you can find more information in the OWASP Top Ten 2014/2016 article). In the upcoming entries, we will describe other protections, such as root checker, certificate pinning, anti-tampering, obfuscation techniques, along with ways to protect our app from different tools (Xposed tool, Frida, etc.).

You can find this challenge on my personal repository. It came from a Blackhat course I took in 2017, thanks @din3zh and @prateekg147!

Download link for the apk

Sha1 signature for ReverzeMe1.apk:

> a2d88143cc3de73387931f84439a4c5e4fdfe123

Before the analysis of the challenge itself, we will introduce the concept of Anti-Emulation on Android. A good reference for this topic is the Mobile Security Testing Guide by OWASP. It provides some examples about these techniques, and different ways to analyze them. There is also an API called SafetyNet, which is an Android API, that creates a profile of the device using software and hardware information, which is useful for checking different Android protections.

If we see the Emulator Detection Examples section, an application has several ways to detect the emulation process.

For example, by checking different methods, like:

> **_Build_**, **_TelephonyManager_**, **_android.os.SystemProperties_**, **_ro.product.device_**, **_ro.kernel.qemu_**, etc.

Depending on the response, it can infer if it is running on a physical device or in an Android Emulator. To check if the app has this implementation in place, we can try to obtain its code. This can be done through different techniques and we can use some tools, such as apktool, jadx or cfr, etc., which use will be explained in the following post.

Anti-Emulation Checks

There are several checks that an application can perform in order to detect whether we are running it on an emulated environment or an actual device. Usually, malware APKs have these kinds of protections to avoid any analysis. Some common validations are listed here (anti-emulation process), along with some examples.

Below are some code examples of different validations that I have encountered on applications while writing this post:

Code block #1
Code block #2
Code block #3

Some validation methods are even called isEmulator(), carrierNameFromTelephonyManager(), or, my personal favorite so far, smellsLikeAnEmulator(). All of them look for the same or similar validations. They test with equals, contains, startsWith or endsWith against some hardcoded strings that can be interpreted as being set by an emulator. But they all look pretty much the same.

I wondered why this happened and googled it and got the answer: of course, the first result was a Stackoverflow answer.

I started looking into some others apps, and I found some many more quite similar implementations:

Code block #4
Code block #5
Code block #6
Code block #7

The difference with the previous set of validation methods is that, while the first set validates through string comparisons, the second one does by looking at the Android system properties to try to detect emulated environments.

Then, by simply analyzing the implementation methods, we can identify two main approaches to implement an anti-emulation protection. We can use this link as an Android reference.

Strings Comparisons

Let’s take a look at the isEmulator() example and its validations:

Code block #8

I wrote this reference table:

Comparisons

We can check them in a easy way using the following command in our computers with adb (Android Device Bridge):

╰─$ adb shell getprop ro.build.fingerprint
generic/vbox86p/vbox86p:5.1/LMY47D/genymotion08250738:userdebug/test-keys

Basically, we can use $adb shell getprop < key > to check the different values.

Android System Properties validations

Now that we know how to check for validation through strings, we can do the same with the Android System Properties validations.

Android has a set of properties about the device that can be read using the getprop command line utility, like we saw recently. Those System Properties are stored in a key value pair format in the property files (default.prop, local.prop, etc). And we’ll read those to check the Anti-Emulation process.

If we want to understand more about the property files, using adb shell cat default.prop, we can check the property output:

$adb shell cat default.prop  
# ADDITIONAL_DEFAULT_PROPERTIES # 
ro.lockscreen.disable.default=true  
ro.secure=1  
ro.allow.mock.location=0  
ro.debuggable=1  
ro.zygote=zygote32  
dalvik.vm.dex2oat-Xms=64m  
dalvik.vm.dex2oat-Xmx=512m  
dalvik.vm.image-dex2oat-Xms=64m  
dalvik.vm.image-dex2oat-Xmx=64m  
persist.sys.usb.config=adb

But if we returned to the previous image:

They are checking ro.hardware, ro.kernel.qemu, ro.serialno, ro.product.name, ro.product.model, ro.hardware, etc. We can check this output too using:

╰─$ adb shell getprop ro.product.name vbox86p  
╰─$ adb shell getprop ro.product.device vbox86p  
╰─$ adb shell getprop ro.product.model Custom Phone - 5.1.0 - API 22–768x1280  
╰─$ adb shell getprop ro.kernel.qemu 1  
╰─$ adb shell getprop ro.hardware vbox86  
╰─$ adb shell getprop qemu.hw.mainkeys 0  
╰─$ adb shell getprop ro.bootloader unknown  
╰─$ adb shell getprop ro.bootmode unknown  
╰─$ adb shell getprop ro.secure 1  
╰─$ adb shell getprop ro.build.fingerprint generic/vbox86p/vbox86p:5.1/LMY47D/genymotion08250738:userdebug/test-keys  
╰─$ adb shell getprop ro.build.version.sdk 22

And, again, if the value of ro.secure is 1, the app is running on an emulator. The same goes for ro.kernel.qemu and the others.

Now it is easy to understand what part of the code we need to modify to bypass the emulation process. We need to check all the implementations inside the code to bypass the application.

And we’ll discuss that in the next entry.

Don’t forget to follow us!

Just Mobile Security | LinkedIn

Juan Urbano Stordeur (@juanurss) / Twitter

This article was written by Juan Urbano Stordeur, Founder & CEO of Just Mobile Security