Now that we have bypass the emulator check, we can start digging into how the application generates the key. This is what we need to successfully submit.
-- Enumerate classes, and find keyword 'versprite' --
We can use Androguard to enumerate all the classes within are target package.
In [13]: classes = list()
In [14]: for c in d.get_classes(): classes.append(c.name)
In [15]: for c in classes:
if "versprite" in c:
print(c)
....:
Lcom/versprite/crackme/BuildConfig;
Lcom/versprite/crackme/KeyActivity$1;
Lcom/versprite/crackme/KeyActivity;
Lcom/versprite/crackme/R$anim;
Lcom/versprite/crackme/R$attr;
Lcom/versprite/crackme/R$bool;
Lcom/versprite/crackme/R$color;
Lcom/versprite/crackme/R$dimen;
Lcom/versprite/crackme/R$drawable;
Lcom/versprite/crackme/R$id;
Lcom/versprite/crackme/R$integer;
Lcom/versprite/crackme/R$layout;
Lcom/versprite/crackme/R$menu;
Lcom/versprite/crackme/R$mipmap;
Lcom/versprite/crackme/R$string;
Lcom/versprite/crackme/R$style;
Lcom/versprite/crackme/R$styleable;
Lcom/versprite/crackme/R;
Lcom/versprite/crackme/emulator/Detect;
Lcom/versprite/crackme/generate/Generate;
Lcom/versprite/crackme/generate/GenerateReceiver;
We see something suspect!
Lcom/versprite/crackme/generate/Generate; Lcom/versprite/crackme/generate/GenerateReceiver;
GenerateReceiver
appears to be a Broadcast Receiver, lets verify that!
In [17]: a.get_receivers()
Out[17]: ['com.versprite.crackme.generate.GenerateReceiver']
-- GenerateReceiver --
In [18]: d.CLASS_Lcom_versprite_crackme_generate_GenerateReceiver.source()
package com.versprite.crackme.generate;
public class GenerateReceiver extends android.content.BroadcastReceiver {
public GenerateReceiver()
{
return;
}
public void onReceive(android.content.Context p8, android.content.Intent p9)
{
android.os.Bundle v0 = p9.getExtras();
if (v0 != null) {
String v2 = v0.getString("key");
android.util.Log.d("GenerateReceiver", new StringBuilder().append("Key Received: ").append(v2).toString());
if (!new com.versprite.crackme.generate.Generate().c(v2).equals(Boolean.valueOf(1))) {
android.widget.Toast.makeText(p8.getApplicationContext(), "Try Again!", 0).show();
} else {
android.widget.Toast.makeText(p8.getApplicationContext(), "Success!", 0).show();
}
}
return;
}
}
Can anyone tell me what is going here?
When the onReceive() method is called, it is called with an Intent object. The GenerateReceiver then retrieves the 'key' from the Intent extras, calls Generate() and evaluates it to be TRUE or FALSE.
Who can tell me what this is doing?
n [22]: for m in d.CLASS_Lcom_versprite_crackme_generate_Generate.get_methods(): print(m.pretty_show())
########## Method Information
Lcom/versprite/crackme/generate/Generate;-><init>()V [access_flags=public constructor]
########## Params
local registers: v0...v0
- return: void
####################
***************************************************************************
<init>-BB@0x0 :
0 (00000000) invoke-direct v0, Landroid/app/Application;-><init>()V
1 (00000006) return-void
***************************************************************************
########## XREF
F: Lcom/versprite/crackme/generate/GenerateReceiver; onReceive (Landroid/content/Context; Landroid/content/Intent;)V 4e
####################
None
########## Method Information
Lcom/versprite/crackme/generate/Generate;->c(Ljava/lang/String;)Ljava/lang/Boolean; [access_flags=public]
########## Params
- local registers: v0...v3
- v4: java.lang.String
- return: java.lang.Boolean
####################
***************************************************************************
c-BB@0x0 :
0 (00000000) const/16 v2, 10
1 (00000004) new-array v0, v2, [B
2 (00000008) fill-array-data v0, 20
3 (0000000e) invoke-virtual v4, Ljava/lang/String;->getBytes()[B
4 (00000014) move-result-object v1
5 (00000016) invoke-static v0, v1, Ljava/util/Arrays;->equals([B [B)Z
6 (0000001c) move-result v2
7 (0000001e) if-eqz v2, 5 [ c-BB@0x22 c-BB@0x28 ]
c-BB@0x22 :
8 (00000022) sget-object v2, Ljava/lang/Boolean;->TRUE Ljava/lang/Boolean; [ c-BB@0x26 ]
c-BB@0x26 :
9 (00000026) return-object v2
c-BB@0x28 :
10 (00000028) sget-object v2, Ljava/lang/Boolean;->FALSE Ljava/lang/Boolean;
11 (0000002c) goto -3 [ c-BB@0x26 ]
c-BB@0x2e :
12 (0000002e) nop
13 (00000030) fill-array-data-payload'Bs1d3s_SF0'
***************************************************************************
########## XREF
F: Lcom/versprite/crackme/generate/GenerateReceiver; onReceive (Landroid/content/Context; Landroid/content/Intent;)V 54
####################
None
1.) Create a new bytearray
1 (00000004) new-array v0, v2, [B
2 (00000008) fill-array-data v0, 20
2.) Call getBytes() on the parameter passed to the method, then compare it - equals() - against the bytearay it has created
3 (0000000e) invoke-virtual v4, Ljava/lang/String;->getBytes()[B
4 (00000014) move-result-object v1
5 (00000016) invoke-static v0, v1, Ljava/util/Arrays;->equals([B [B)Z
6 (0000001c) move-result v2
7 (0000001e) if-eqz v2, 5 [ c-BB@0x22 c-BB@0x28 ]
3.) If we look at idx 0x2e, we see are key being filled into the array
c-BB@0x2e :
12 (0000002e) nop
13 (00000030) fill-array-data-payload'Bs1d3s_SF0'
4.) Finally the source output
In [23]: d.CLASS_Lcom_versprite_crackme_generate_Generate.METHOD_c.source()
public Boolean c(String p4)
{
Boolean v2_2;
byte[] v0 = new byte[10];
v0 = {66, 115, 49, 100, 51, 115, 95, 83, 70, 48};
if (!java.util.Arrays.equals(v0, p4.getBytes())) {
v2_2 = Boolean.FALSE;
} else {
v2_2 = Boolean.TRUE;
}
return v2_2;
}