Skip to content

Latest commit

 

History

History
662 lines (545 loc) · 26.5 KB

Lab-002.md

File metadata and controls

662 lines (545 loc) · 26.5 KB

Detect and Patch

If you haven't already, we need to install the CrackMe! application in our Genymotion emulator.

➜  app git:(master) ✗ adb devices    
List of devices attached 
192.168.56.101:5555	device

➜  app git:(master) ✗ adb install crackme.apk 
7187 KB/s (907915 bytes in 0.123s)
	pkg: /data/local/tmp/crackme.apk
Success

What happens when you try to run the application? -> CrackME! attempts to uninstall itself!


Emulator Detection

-- Analyze CrackME! with Androguard ---

➜  app git:(master) ✗ python ~/Tools/mobile/android/androguard/androlyze.py -s 
In [2]: a.get_activities()
Out[2]: ['com.versprite.crackme.KeyActivity']
In [3]: a.get_main_activity()
Out[3]: u'com.versprite.crackme.KeyActivity'

So now know that com.versprite.crackme.KeyActivity is the Main Activity. Now we have a start point for reversing the application.

In our previous lab, I explained that 'd' in the AnalyzeAPK() assigment contains a class that has the ability the parse and understand the DEX format.

If you type d.C [tab] ->

d.CLASS_Lcom_versprite_crackme_BuildConfig
d.CLASS_Lcom_versprite_crackme_KeyActivity
d.CLASS_Lcom_versprite_crackme_KeyActivity_1
d.CLASS_Lcom_versprite_crackme_R
d.CLASS_Lcom_versprite_crackme_R_anim
d.CLASS_Lcom_versprite_crackme_R_attr
d.CLASS_Lcom_versprite_crackme_R_bool
d.CLASS_Lcom_versprite_crackme_R_color
d.CLASS_Lcom_versprite_crackme_R_dimen
d.CLASS_Lcom_versprite_crackme_R_drawable
d.CLASS_Lcom_versprite_crackme_R_id
d.CLASS_Lcom_versprite_crackme_R_integer
d.CLASS_Lcom_versprite_crackme_R_layout
d.CLASS_Lcom_versprite_crackme_R_menu
d.CLASS_Lcom_versprite_crackme_R_mipmap
d.CLASS_Lcom_versprite_crackme_R_string
d.CLASS_Lcom_versprite_crackme_R_style
d.CLASS_Lcom_versprite_crackme_R_styleable
d.CLASS_Lcom_versprite_crackme_emulator_Detect
d.CLASS_Lcom_versprite_crackme_generate_Generate
d.CLASS_Lcom_versprite_crackme_generate_GenerateReceiver

This displays all of the classes within the classes.dex that have been analzyed by Androlyze. Now, because we know which class we want to focus on (d.CLASS_Lcom_versprite_crackme_KeyActivity), we can access it directly.

In [4]: d.CLASS_Lcom_versprite_crackme_KeyActivity.
d.CLASS_Lcom_versprite_crackme_KeyActivity.FIELD_key
d.CLASS_Lcom_versprite_crackme_KeyActivity.FIELD_submitbtn
d.CLASS_Lcom_versprite_crackme_KeyActivity.METHOD_access_000
d.CLASS_Lcom_versprite_crackme_KeyActivity.METHOD_addListenerOnButton
d.CLASS_Lcom_versprite_crackme_KeyActivity.METHOD_init
d.CLASS_Lcom_versprite_crackme_KeyActivity.METHOD_onCreate
d.CLASS_Lcom_versprite_crackme_KeyActivity.access_flags
d.CLASS_Lcom_versprite_crackme_KeyActivity.access_flags_string
d.CLASS_Lcom_versprite_crackme_KeyActivity.annotations_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.class_data_item
d.CLASS_Lcom_versprite_crackme_KeyActivity.class_data_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.class_idx
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_access_flags
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_access_flags_string
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_annotations_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_class_data
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_class_data_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_class_idx
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_fields
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_interfaces
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_interfaces_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_length
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_methods
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_name
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_obj
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_raw
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_source
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_source_ext
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_source_file_idx
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_static_values_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_superclass_idx
d.CLASS_Lcom_versprite_crackme_KeyActivity.get_superclassname
d.CLASS_Lcom_versprite_crackme_KeyActivity.interfaces
d.CLASS_Lcom_versprite_crackme_KeyActivity.interfaces_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.name
d.CLASS_Lcom_versprite_crackme_KeyActivity.offset
d.CLASS_Lcom_versprite_crackme_KeyActivity.reload
d.CLASS_Lcom_versprite_crackme_KeyActivity.set_name
d.CLASS_Lcom_versprite_crackme_KeyActivity.show
d.CLASS_Lcom_versprite_crackme_KeyActivity.show_xref
d.CLASS_Lcom_versprite_crackme_KeyActivity.sname
d.CLASS_Lcom_versprite_crackme_KeyActivity.source
d.CLASS_Lcom_versprite_crackme_KeyActivity.source_file_idx
d.CLASS_Lcom_versprite_crackme_KeyActivity.static_values
d.CLASS_Lcom_versprite_crackme_KeyActivity.static_values_off
d.CLASS_Lcom_versprite_crackme_KeyActivity.superclass_idx

-- We can inspect the entire Class the easy way first! --

In [13]: d.CLASS_Lcom_versprite_crackme_KeyActivity.source()
package com.versprite.crackme;
public class KeyActivity extends android.app.Activity {
    private android.widget.EditText key;
    private android.widget.Button submitbtn;

    public KeyActivity()
    {
        return;
    }

    static synthetic android.widget.EditText access$000(com.versprite.crackme.KeyActivity p1)
    {
        return p1.key;
    }

    public void addListenerOnButton()
    {
        this.key = ((android.widget.EditText) this.findViewById(2131296320));
        this.submitbtn = ((android.widget.Button) this.findViewById(2131296321));
        this.submitbtn.setOnClickListener(new com.versprite.crackme.KeyActivity$1(this));
        return;
    }

    protected void onCreate(android.os.Bundle p5)
    {
        super.onCreate(p5);
        this.setContentView(2130968599);
        if (new com.versprite.crackme.emulator.Detect().detectEmulator().equals(Boolean.TRUE)) {
            android.util.Log.d("Emulator Detected!", "Uninstalling ...");
            android.content.Intent v1_1 = new android.content.Intent("android.intent.action.UNINSTALL_PACKAGE");
            v1_1.setData(android.net.Uri.parse("package:com.versprite.crackme"));
            this.startActivity(v1_1);
            this.finish();
        }
        this.addListenerOnButton();
        return;
    }
}


In [14]: 

We really care about what is going on in the onCreate() method. Why? -> http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)

- Called when the Activity is starting
- This is where most initialization should go

What looks important in the onCreate() method?

 if (new com.versprite.crackme.emulator.Detect().detectEmulator().equals(Boolean.TRUE)) {
            android.util.Log.d("Emulator Detected!", "Uninstalling ...");
            android.content.Intent v1_1 = new android.content.Intent("android.intent.action.UNINSTALL_PACKAGE");
            v1_1.setData(android.net.Uri.parse("package:com.versprite.crackme"));
            this.startActivity(v1_1);
            this.finish();
- Creates a new instance of Detect()
- Calls detectEmulator()
- If it returns TRUE
	- Create a new Intent object
	- Assign the 'android.intent.action.UNINSTALL_PACKAGE' action
	- Set the com.versprite.crackme package
	- Start the appropriate Activitiy with this Intent object

The ActivityManager will handle this Intent object, and knows that com.android.packageinstaller/.UninstallerActivity can handle this action.

This is what logcat will tell us:

I/ActivityManager(22534): START u0 {act=android.intent.action.UNINSTALL_PACKAGE dat=package:com.versprite.crackme cmp=com.android.packageinstaller/.UninstallerActivity} from pid 24549

I/ActivityManager(22534): Displayed com.android.packageinstaller/.UninstallerActivity: +195ms (total +210ms)

We have a pretty good representation of what the source code would like for this Activity, but we can also inspect the bytecode as well.


-- Enumerate Methods --

In [15]: for method in d.CLASS_Lcom_versprite_crackme_KeyActivity.get_methods(): print(method.pretty_show())

get_methods() returns a list of method instances that belong to the KeyActivity class. We can run a simple for in loop over these methods, and call pretty_show(), which will provide some syntax highlighting.

-- onCreate() --

########## Method Information
Lcom/versprite/crackme/KeyActivity;->onCreate(Landroid/os/Bundle;)V [access_flags=protected]
########## Params
- local registers: v0...v4
- v5: android.os.Bundle
- return: void
####################
***************************************************************************
onCreate-BB@0x0 : 
	0  (00000000) invoke-super        v4, v5, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
	1  (00000006) const               v2, 2130968599
	2  (0000000c) invoke-virtual      v4, v2, Lcom/versprite/crackme/KeyActivity;->setContentView(I)V
	3  (00000012) new-instance        v0, Lcom/versprite/crackme/emulator/Detect;
	4  (00000016) invoke-direct       v0, Lcom/versprite/crackme/emulator/Detect;-><init>()V
	5  (0000001c) invoke-virtual      v0, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;
	6  (00000022) move-result-object  v2
	7  (00000024) sget-object         v3, Ljava/lang/Boolean;->TRUE Ljava/lang/Boolean;
	8  (00000028) invoke-virtual      v2, v3, Ljava/lang/Boolean;->equals(Ljava/lang/Object;)Z
	9  (0000002e) move-result         v2
	10 (00000030) if-eqz              v2, 31 [ onCreate-BB@0x34 onCreate-BB@0x6e ]

onCreate-BB@0x34 : 
	11 (00000034) const-string        v2, 'Emulator Detected!'
	12 (00000038) const-string        v3, 'Uninstalling ...'
	13 (0000003c) invoke-static       v2, v3, Landroid/util/Log;->d(Ljava/lang/String; Ljava/lang/String;)I
	14 (00000042) new-instance        v1, Landroid/content/Intent;
	15 (00000046) const-string        v2, 'android.intent.action.UNINSTALL_PACKAGE'
	16 (0000004a) invoke-direct       v1, v2, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
	17 (00000050) const-string        v2, 'package:com.versprite.crackme'
	18 (00000054) invoke-static       v2, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
	19 (0000005a) move-result-object  v2
	20 (0000005c) invoke-virtual      v1, v2, Landroid/content/Intent;->setData(Landroid/net/Uri;)Landroid/content/Intent;
	21 (00000062) invoke-virtual      v4, v1, Lcom/versprite/crackme/KeyActivity;->startActivity(Landroid/content/Intent;)V
	22 (00000068) invoke-virtual      v4, Lcom/versprite/crackme/KeyActivity;->finish()V [ onCreate-BB@0x6e ]

onCreate-BB@0x6e : 
	23 (0000006e) invoke-virtual      v4, Lcom/versprite/crackme/KeyActivity;->addListenerOnButton()V
	24 (00000074) return-void         

***************************************************************************
########## XREF
T: Lcom/versprite/crackme/emulator/Detect; <init> ()V 16
T: Lcom/versprite/crackme/emulator/Detect; detectEmulator ()Ljava/lang/Boolean; 1c
T: Lcom/versprite/crackme/KeyActivity; addListenerOnButton ()V 6e
####################

What do we know about this method so far?

- local registers (non-paramters) v0 .. v4
- v5 android.os.Bundle (argument)
- returns void

-- Method Isolation --

In [30]: onCreate = d.CLASS_Lcom_versprite_crackme_KeyActivity.METHOD_onCreate
In [31]: onCreate.pretty_show()
########## Method Information
Lcom/versprite/crackme/KeyActivity;->onCreate(Landroid/os/Bundle;)V [access_flags=protected]
########## Params
- local registers: v0...v4
- v5: android.os.Bundle
- return: void
####################
***************************************************************************
onCreate-BB@0x0 : 
	0  (00000000) invoke-super        v4, v5, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
	1  (00000006) const               v2, 2130968599
	2  (0000000c) invoke-virtual      v4, v2, Lcom/versprite/crackme/KeyActivity;->setContentView(I)V
	3  (00000012) new-instance        v0, Lcom/versprite/crackme/emulator/Detect;
	4  (00000016) invoke-direct       v0, Lcom/versprite/crackme/emulator/Detect;-><init>()V
	5  (0000001c) invoke-virtual      v0, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;
	6  (00000022) move-result-object  v2
	7  (00000024) sget-object         v3, Ljava/lang/Boolean;->TRUE Ljava/lang/Boolean;
	8  (00000028) invoke-virtual      v2, v3, Ljava/lang/Boolean;->equals(Ljava/lang/Object;)Z
	9  (0000002e) move-result         v2
	10 (00000030) if-eqz              v2, 31 [ onCreate-BB@0x34 onCreate-BB@0x6e ]

onCreate-BB@0x34 : 
	11 (00000034) const-string        v2, 'Emulator Detected!'
	12 (00000038) const-string        v3, 'Uninstalling ...'
	13 (0000003c) invoke-static       v2, v3, Landroid/util/Log;->d(Ljava/lang/String; Ljava/lang/String;)I
	14 (00000042) new-instance        v1, Landroid/content/Intent;
	15 (00000046) const-string        v2, 'android.intent.action.UNINSTALL_PACKAGE'
	16 (0000004a) invoke-direct       v1, v2, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
	17 (00000050) const-string        v2, 'package:com.versprite.crackme'
	18 (00000054) invoke-static       v2, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
	19 (0000005a) move-result-object  v2
	20 (0000005c) invoke-virtual      v1, v2, Landroid/content/Intent;->setData(Landroid/net/Uri;)Landroid/content/Intent;
	21 (00000062) invoke-virtual      v4, v1, Lcom/versprite/crackme/KeyActivity;->startActivity(Landroid/content/Intent;)V
	22 (00000068) invoke-virtual      v4, Lcom/versprite/crackme/KeyActivity;->finish()V [ onCreate-BB@0x6e ]

onCreate-BB@0x6e : 
	23 (0000006e) invoke-virtual      v4, Lcom/versprite/crackme/KeyActivity;->addListenerOnButton()V
	24 (00000074) return-void         

***************************************************************************
########## XREF
T: Lcom/versprite/crackme/emulator/Detect; <init> ()V 16
T: Lcom/versprite/crackme/emulator/Detect; detectEmulator ()Ljava/lang/Boolean; 1c
T: Lcom/versprite/crackme/KeyActivity; addListenerOnButton ()V 6e
####################
	3  (00000012) new-instance        v0, Lcom/versprite/crackme/emulator/Detect;
	4  (00000016) invoke-direct       v0, Lcom/versprite/crackme/emulator/Detect;-><init>()V
	5  (0000001c) invoke-virtual      v0, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;
	6  (00000022) move-result-object  v2
- new-instance vx, type
	- Instantiates an object type and puts the reference of the newly created instance
- invoke-direct {parameters}, methodtocall
	- Invokes the virtual method with parameters without the virtual method resolutions
- invoke-virtual {vx .. vy}, methodtocall
	- Invokes method with a range of registers (First parameters is always "this")
- move-result-object vx
	- Move the result value of the previous method invocation into vx

So what does this do?

	3  (00000012) new-instance        v0, Lcom/versprite/crackme/emulator/Detect;
	4  (00000016) invoke-direct       v0, Lcom/versprite/crackme/emulator/Detect;-><init>()V
	5  (0000001c) invoke-virtual      v0, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;
	6  (00000022) move-result-object  v2

How about this?

onCreate-BB@0x34 : 
	11 (00000034) const-string        v2, 'Emulator Detected!'
	12 (00000038) const-string        v3, 'Uninstalling ...'
	13 (0000003c) invoke-static       v2, v3, Landroid/util/Log;->d(Ljava/lang/String; Ljava/lang/String;)I
	14 (00000042) new-instance        v1, Landroid/content/Intent;
	15 (00000046) const-string        v2, 'android.intent.action.UNINSTALL_PACKAGE'
	16 (0000004a) invoke-direct       v1, v2, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
	17 (00000050) const-string        v2, 'package:com.versprite.crackme'
	18 (00000054) invoke-static       v2, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
	19 (0000005a) move-result-object  v2
	20 (0000005c) invoke-virtual      v1, v2, Landroid/content/Intent;->setData(Landroid/net/Uri;)Landroid/content/Intent;
	21 (00000062) invoke-virtual      v4, v1, Lcom/versprite/crackme/KeyActivity;->startActivity(Landroid/content/Intent;)V
	22 (00000068) invoke-virtual      v4, Lcom/versprite/crackme/KeyActivity;->finish()V [ onCreate-BB@0x6e ]

You can always call source() if you wanna!

In [32]: onCreate.source()
protected void onCreate(android.os.Bundle p5)
    {
        super.onCreate(p5);
        this.setContentView(2130968599);
        if (new com.versprite.crackme.emulator.Detect().detectEmulator().equals(Boolean.TRUE)) {
            android.util.Log.d("Emulator Detected!", "Uninstalling ...");
            android.content.Intent v1_1 = new android.content.Intent("android.intent.action.UNINSTALL_PACKAGE");
            v1_1.setData(android.net.Uri.parse("package:com.versprite.crackme"));
            this.startActivity(v1_1);
            this.finish();
        }
        this.addListenerOnButton();
        return;
    }

-- What have we learned so far? --

- We have a class Detect() that has method called detectEmulator()
- If that returns TRUE
- The application will try to uninstall 

-- Detect! --

In [33]: d.CLASS_Lcom_versprite_crackme_emulator_Detect.source()
package com.versprite.crackme.emulator;
public class Detect extends android.app.Application {
    private Boolean d;
    private String[] props;

    public Detect()
    {
        Boolean v0_1 = new String[4];
        v0_1[0] = "ro.secure";
        v0_1[1] = "ro.product.name";
        v0_1[2] = "ro.build.host";
        v0_1[3] = "ro.build.tags";
        this.props = v0_1;
        this.d = Boolean.TRUE;
        return;
    }

    public Boolean detectEmulator()
    {
        String[] v0 = this.props;
        int v5 = v0.length;
        int v4 = 0;
        while (v4 < v5) {
            String v8 = v0[v4];
            try {
                Class v10 = Class.forName("android.os.SystemProperties");
                Class[] v6 = new Class[1];
                v6[0] = String;
                reflect.Method v3 = v10.getMethod("get", v6);
                Object[] v7 = new Object[1];
                v7[0] = v8;
                boolean v12_8 = new Object[1];
                v12_8[0] = v8;
                String v9_1 = ((String) v3.invoke(v10, v12_8));
            } catch (reflect.InvocationTargetException v1_1) {
                v1_1.printStackTrace();
                v4++;
            } catch (reflect.InvocationTargetException v1_0) {
                v1_0.printStackTrace();
            } catch (reflect.InvocationTargetException v1_3) {
                v1_3.printStackTrace();
            } catch (reflect.InvocationTargetException v1_2) {
                v1_2.printStackTrace();
            }
            if ((!v9_1.equals(Integer.valueOf(0))) && ((!v9_1.equals("buildbot.soft.genymobile.com")) && (!v9_1.equals("vbox86p")))) {
            } else {
                android.util.Log.d("Emulator Detected!", v9_1);
                boolean v12_0 = this.d;
            }
            return v12_0;
        }
        v12_0 = Boolean.FALSE;
        return v12_0;
    }
}


In [34]: 

-- We need to focus on the detectEmulator() method --

In [34]: detect = d.CLASS_Lcom_versprite_crackme_emulator_Detect.METHOD_detectEmulator

In [35]: detect.source()
public Boolean detectEmulator()
    {
        String[] v0 = this.props;
        int v5 = v0.length;
        int v4 = 0;
        while (v4 < v5) {
            String v8 = v0[v4];
            try {
                Class v10 = Class.forName("android.os.SystemProperties");
                Class[] v6 = new Class[1];
                v6[0] = String;
                reflect.Method v3 = v10.getMethod("get", v6);
                Object[] v7 = new Object[1];
                v7[0] = v8;
                boolean v12_8 = new Object[1];
                v12_8[0] = v8;
                String v9_1 = ((String) v3.invoke(v10, v12_8));
            } catch (reflect.InvocationTargetException v1_1) {
                v1_1.printStackTrace();
                v4++;
            } catch (reflect.InvocationTargetException v1_0) {
                v1_0.printStackTrace();
            } catch (reflect.InvocationTargetException v1_3) {
                v1_3.printStackTrace();
            } catch (reflect.InvocationTargetException v1_2) {
                v1_2.printStackTrace();
            }
            if ((!v9_1.equals(Integer.valueOf(0))) && ((!v9_1.equals("buildbot.soft.genymobile.com")) && (!v9_1.equals("vbox86p")))) {
            } else {
                android.util.Log.d("Emulator Detected!", v9_1);
                boolean v12_0 = this.d;
            }
            return v12_0;
        }
        v12_0 = Boolean.FALSE;
        return v12_0;
    }

This method is using Java Reflection to access the 'android.os.SystemProperties' class and corresponding get() method, to retrieve values from the system property store. The system property store is created by init, the first user-land application during the boot process for Android. The system properties contain configuration data that can be used to easily identify whether or not the system is being 'emulated'.

 public Detect()
    {
        Boolean v0_1 = new String[4];
        v0_1[0] = "ro.secure";
        v0_1[1] = "ro.product.name";
        v0_1[2] = "ro.build.host";
        v0_1[3] = "ro.build.tags";
        this.props = v0_1;
        this.d = Boolean.TRUE;
        return;
    }

These are the target properties, which are being looped through, and their values inspected. So we really want to understand what happens in order for a jump to this index, to occur:

detectEmulator-BB@0x92 : 
	41 (00000092) const-string        v12, 'Emulator Detected!'
	42 (00000096) invoke-static       v12, v9, Landroid/util/Log;->d(Ljava/lang/String; Ljava/lang/String;)I
	43 (0000009c) iget-object         v12, v14, Lcom/versprite/crackme/emulator/Detect;->d Ljava/lang/Boolean; [ detectEmulator-BB@0xa0 ]

The method is specifically checking these values: 'buildbot.soft.genymobile.com' and 'vbox86p'

detectEmulator-BB@0x0 : 
	0  (00000000) const-string        v2, 'buildbot.soft.genymobile.com'
	1  (00000004) const-string        v11, 'vbox86p'
	2  (00000008) iget-object         v0, v14, Lcom/versprite/crackme/emulator/Detect;->props [Ljava/lang/String;
	3  (0000000c) array-length        v5, v0
	4  (0000000e) const/4             v4, 0 [ detectEmulator-BB@0x10 ]

The 'source' isn't the most accurate representation of what is going on, and without diving into the byte code line by line, the assumption is the code is looping through the system properties and if a match is found against specific values, then emulation is being detected.

-- Patch it! --

We need to find out where we can patch out the bytecode to always return 'FALSE' back to the calling 'onCreate' method.

onCreate-BB@0x0 : 
	0  (00000000) invoke-super        v4, v5, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
	1  (00000006) const               v2, 2130968599
	2  (0000000c) invoke-virtual      v4, v2, Lcom/versprite/crackme/KeyActivity;->setContentView(I)V
	3  (00000012) new-instance        v0, Lcom/versprite/crackme/emulator/Detect;
	4  (00000016) invoke-direct       v0, Lcom/versprite/crackme/emulator/Detect;-><init>()V
	5  (0000001c) invoke-virtual      v0, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;
	6  (00000022) move-result-object  v2
	7  (00000024) sget-object         v3, Ljava/lang/Boolean;->TRUE Ljava/lang/Boolean;
	8  (00000028) invoke-virtual      v2, v3, Ljava/lang/Boolean;->equals(Ljava/lang/Object;)Z
	9  (0000002e) move-result         v2
	10 (00000030) if-eqz              v2, 31 [ onCreate-BB@0x34 onCreate-BB@0x6e ]

What happens if change the instruction 'if-eqz' to 'if-nez'?

- if-eqz = is True
- if-nez = is False

In order to do this, we must modify the smali itself!

1.) Drop into the output directory from the apktool

➜  crackme git:(master) ✗ pwd
/Users/rotlogix/BSidesSF-2015/app/crackme

2.) CD into the appropriate smali directory

➜  crackme git:(master) ✗ ls
BuildConfig.smali   R$anim.smali        R$color.smali       R$id.smali          R$menu.smali        R$style.smali       emulator
KeyActivity$1.smali R$attr.smali        R$dimen.smali       R$integer.smali     R$mipmap.smali      R$styleable.smali   generate
KeyActivity.smali   R$bool.smali        R$drawable.smali    R$layout.smali      R$string.smali      R.smali

3.) Open up KeyActivity.smali in whatever editor you love to use, and find the onCreate() method

.method protected onCreate(Landroid/os/Bundle;)V
    .locals 4
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;

    .prologue
    .line 24
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 25
    const v2, 0x7f040017

    invoke-virtual {p0, v2}, Lcom/versprite/crackme/KeyActivity;->setContentView(I)V

    .line 27
    new-instance v0, Lcom/versprite/crackme/emulator/Detect;

    invoke-direct {v0}, Lcom/versprite/crackme/emulator/Detect;-><init>()V

    .line 29
    .local v0, "detect":Lcom/versprite/crackme/emulator/Detect;
    invoke-virtual {v0}, Lcom/versprite/crackme/emulator/Detect;->detectEmulator()Ljava/lang/Boolean;

    move-result-object v2

    sget-object v3, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;

    invoke-virtual {v2, v3}, Ljava/lang/Boolean;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-eqz v2, :cond_0

4.) Modify the 'if-eqz' instruction to 'if-nez'


    invoke-virtual {v2, v3}, Ljava/lang/Boolean;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-nez v2, :cond_0

    .line 30
    const-string v2, "Emulator Detected!"

5.) Save the file

We will need to rebuild the APK and sign it with an appropriate key in order to reinstall this back into our emulator.

6.) Build new APK

➜  app git:(master) ✗ java -jar ~/Tools/mobile/android/apktool/apktool_2.0.0rc4.jar b crackme -o modified_crackme.apk
I: Using Apktool 2.0.0-RC4
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Copying raw resources...
I: Building apk file...

7.) Sign new APK

➜  app git:(master) ✗ keytool -genkey -v -keystore crackme.keystore -alias crackme -keyalg RSA -keysize 2048 -validity 10000
➜  app git:(master) ✗ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore crackme.keystore modified_crackme.apk crackme

Make sure you have removed the old application from your emulator!

8.) Install new APK

➜  app git:(master) ✗ adb install modified_crackme.apk

Now when you start the application, you should see the 'Welcome to CrackME!'!