记录一次安卓动态调试dex

这次我们来调试dex,题目是GCTF 2017中的一道安卓水题,算法一望而知,但我们换一种方法做做看。

题目附件:com.example.crackme.apk

你大概需要:
1.一部手机,已root,有ro.debuggable=1,安卓4.4.4(非必须),cpu架构32位(非必须,但这题我在64位机子上调试失败)
2.IDA
3.JEB2(此处非必须)

参照前一篇文章,手机连电脑,adb连shell以root启动android_server,adb再转发端口,这里不再多说。

apk文件拖到IDA里,选择dex文件。

根据JEB2中的反汇编结果,我们找到关键的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void onCreate(Bundle arg3) {
super.onCreate(arg3);
this.setContentView(2130968601);
this.setTitle(2131099677);
this.edit_userName = "Tenshine";
this.edit_sn = this.findViewById(2131492945);
this.btn_register = this.findViewById(2131492946);
this.btn_register.setOnClickListener(new View$OnClickListener() {
public void onClick(View arg5) {
if(!MainActivity.this.checkSN(MainActivity.this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this, 2131099678, 0).show();
}
else {
Toast.makeText(MainActivity.this, 2131099675, 0).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(2131099673);
}
}
});
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
private boolean checkSN(String name, String sn) {
boolean v7 = false;
if(name != null) {
try {
if(name.length() == 0) {
return v7;
}

if(sn == null) {
return v7;
}

if(sn.length() != 22) { // sn长度必须为22
return v7;
}

MessageDigest v1 = MessageDigest.getInstance("MD5"); // MD5加密name
v1.reset();
v1.update(name.getBytes());
String enc1 = MainActivity.toHexString(v1.digest(), "");
StringBuilder ecn2 = new StringBuilder();
int v4;
for(v4 = 0; v4 < enc1.length(); v4 += 2) {
ecn2.append(enc1.charAt(v4)); // 取md5后的奇数位
}

if(!"flag{" + ecn2.toString() + "}".equalsIgnoreCase(sn)) {
return v7;
}
}
catch(NoSuchAlgorithmException v2) {
goto label_40;
}

v7 = true;
}

return v7;
label_40:
v2.printStackTrace();
return v7;
}

如果是静态分析的话,这样也就分析出来了,很简单,但现在我们假设中间是一坨很复杂的算法,那么动态分析就方便的多了。

IDA中找到关键代码下好断点。

手机端打开crackme到主界面,IDA选择attach to process

成功后会显示如下,点一下运行。

输入长度22位的假flag后成功断下

打开local窗口

单步f8,

切换到local窗口

可以看到,flag直接通过动态跟踪的方式出来了。