Android逆向练习 crackme0502
今天继续练习简单的crackme。
先看一下界面,还是输入注册码,点击检测后弹Toast提示成功、失败。
反编译APK
几种方式
1、直接用apktool反编译,得到smali代码
2、直接解压apk,得到的dex文件用BytecodeViewer打开(翻译成java源码)
3、d2j-dex2jar工具打成jar包,然后用jd-jui打开读java源码
定位代码:
先搜注册码相关的字符,找到onClick().
this.btnCheckSN.setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
if (new MainActivity.SNChecker(MainActivity.this, MainActivity.this.edtSN.getText().toString()).isRegistered()) {}
for (String str = "注册码正确";; str = "注册码错误")
{
Toast.makeText(MainActivity.this, str, 0).show();
return;
}
}
});
可以看到这里判断了个isRegistered(),然后下面的发编译代码有点问题。不过没关系,先看一眼isRegistered()函数:
public boolean isRegistered()
{
int i = 0;
if ((this.sn == null) || (this.sn.length() < 8)) {
return false;
}
int j = this.sn.length();
if (j == 8) {
switch (this.sn.charAt(0))
{
default:
bool = false;
if (bool) {
switch (this.sn.charAt(3))
{
default:
bool = false;
}
}
break;
}
}
do
{
for (;;)
{
return bool;
bool = true;
break;
bool = true;
}
bool = false;
} while (j != 16);
int k = 0;
label145:
if (k >= j) {
if (i % 6 != 0) {
break label181;
}
}
label181:
for (boolean bool = true;; bool = false)
{
break;
i += this.sn.charAt(k);
k++;
break label145;
}
}
按照以往的经验,直接一劳永逸将isRegistered()返回true就行了。修改smali时,我们直接在函数开始的地方插入代码,让它返回true。
const/4 v0, 0x1
return v0
然后我们看下上面提到的有错误的地方,就是这段:
if (new MainActivity.SNChecker(MainActivity.this, MainActivity.this.edtSN.getText().toString()).isRegistered()) {}
for (String str = "注册码正确";; str = "注册码错误")
{
Toast.makeText(MainActivity.this, str, 0).show();
return;
}
到smali中查看,通过分析得知其实是反编译成java代码的时候产生的问题。
.line 45
.local v0, "checker":Lcom/droider/crackme0502/MainActivity$SNChecker;
invoke-virtual {v0}, Lcom/droider/crackme0502/MainActivity$SNChecker;->isRegistered()Z
move-result v2 #isRegistered()的结果
if-eqz v2, :cond_0 #如果为false,就到cond_0
const-string v1, "\u6ce8\u518c\u7801\u6b63\u786e" #unicode转码 -> 注册码正确
.line 46
.local v1, "str":Ljava/lang/String;
:goto_0 #开始循环
iget-object v2, p0, Lcom/droider/crackme0502/MainActivity$2;->this$0:Lcom/droider/crackme0502/MainActivity;
const/4 v3, 0x0
#调用toast方法,v2相当于MainActivity.this,v1是str,v3=0
invoke-static {v2, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v2
invoke-virtual {v2}, Landroid/widget/Toast;->show()V
.line 47
return-void
.line 45
.end local v1 # "str":Ljava/lang/String;
:cond_0 #isRegistered()的结果位false跳到这里
const-string v1, "\u6ce8\u518c\u7801\u9519\u8bef" #unicode转码 -> 注册码错误
goto :goto_0
.end method
好了,打包apk试验,却发现应用闪退。。。看一眼logcat,发现了程序被修改的log提示。所以应该是某些地方做了某种验证,不符合后就kill掉应用。这里有两种方法,一种是搜索提示“程序被修改”字符,不过一般的是不会给你任何提示的;另一种是搜索finish()方法或者android.os.killprocess()方法。我们来搜索一下,果然在MyApp中发现了两处:
结合jd-jui代码
很明显的用了Java反射机制,手动调用了isRegistered()方法,参数是字符串1111。如果1111通过了验证或者调用isRegistered()失败,则用killProcess干掉本应用进程。知道了原理,也就好解决了,直接将两处killProcess()的调用nop掉就可以了。
重新打包验证,随便输入字符都能验证通过了。
crackme0502 APK连接:
链接: https://pan.baidu.com/s/1kVeNCoB 密码: b5km