Android逆向练习 crackme0502

今天继续练习简单的crackme。
先看一下界面,还是输入注册码,点击检测后弹Toast提示成功、失败。

Android逆向练习 crackme0502_第1张图片

反编译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
Android逆向练习 crackme0502_第2张图片

然后我们看下上面提到的有错误的地方,就是这段:

 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中发现了两处:

Android逆向练习 crackme0502_第3张图片

结合jd-jui代码

Android逆向练习 crackme0502_第4张图片

很明显的用了Java反射机制,手动调用了isRegistered()方法,参数是字符串1111。如果1111通过了验证或者调用isRegistered()失败,则用killProcess干掉本应用进程。知道了原理,也就好解决了,直接将两处killProcess()的调用nop掉就可以了。

重新打包验证,随便输入字符都能验证通过了。

crackme0502 APK连接:
链接: https://pan.baidu.com/s/1kVeNCoB 密码: b5km

你可能感兴趣的:(Android逆向练习 crackme0502)