Android逆向实例笔记—续力破解三个Android程序


这个首先感谢鱼C论坛的cbs大神,我是看了他的视频。自己再动手破解他给出这三个小程序。真心这样无私把技术分享给大家的人真的不多。再次感谢他。

这里我就我自己破解的三个小程序自己做做笔记吧,方便自己以后查看,也方便刚刚入门的童鞋。这些都是些没啥技术含量的东西,大神请飘过。

一、认识新工具

这里我先给出一个新的工具。jeb。给个我找的。分别有32和64的。https://yunpan.cn/cMuBpvug7qjc2  访问密码 da4a

还是照例给个样图

二、Crackme03

1.查看原apk

还是拖拽到蓝叠里面看看吧。



我们看到错误的提示是Bad boy。

那就让我们开心的打开apkIDE吧

2.反编译

反编译之后打开strings.xml。发现,没有Bad boy。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Android Crackme03 - [by deurus]</string>
    <string name="app_name2">About Crackme03</string>
    <string name="textoPrueba2">This is the third crackme of the Android collection crackmes, in this, the crackme take another phone values and with our name make something. For this reason, the crackme dont run in the emulator, only in the phone. Good luck for all!.</string>
    <string name="textodeurus">by deurus [29-10-10] [Made in Basque Country]</string>
    <string name="imei" />
    <string name="temp">Enter Name</string>
    <string name="labelserial">Enter Serial</string>
    <string name="line">--------------------------------------</string>
</resources>

那我们就只能看看smali里面的东西了。

搜索结果只有一处,还好。


双击过去,并往上找跳转。结果发现,这代码有混淆。没有办法了?

这个时候就该我们的jeb上了。


点击File-Open,然后选择我们的Crackme03。

然后点到Decompiled Java选项卡。双击左边的HelloAndroid。我们惊喜的发现这不是源码么?


其实不是哈。只是很类似了。而已。

其实,这里的话,我们也可以不用jeb哈。直接用apkIDE带一个东西。


点击打开,选择打开。也是一样的


让我们来看看代码。

package com.example.helloandroid;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View$OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class HelloAndroid extends Activity {
    private View$OnClickListener pulsarBoton;
    private View$OnClickListener pulsarBotonabout;
    public HelloAndroid() {
        super();
        this.pulsarBotonabout = new View$OnClickListener() {
            public void onClick(View v) {
                HelloAndroid.this.setContentView(2130903041);
                Intent v0 = new Intent();
                v0.setClass(HelloAndroid.this, prueba2.class);
                HelloAndroid.this.startActivity(v0);
                HelloAndroid.this.finish();
            }
        };
        this.pulsarBoton = new View$OnClickListener() {
            public void onClick(View v) {
                String v10 = HelloAndroid.this.findViewById(2131034116).getText().toString();
                int v11 = v10.length();
                String v12 = "";
                String v15 = HelloAndroid.this.findViewById(2131034118).getText().toString();
                if(v11 >= 4) {
                    goto label_29;
                }
                try {
                    Toast.makeText(HelloAndroid.this.getApplicationContext(), "Min 4 chars", 1).show
                            ();
                    return;
                label_29:
                    int v5;
                    for(v5 = 0; v5 < v10.length(); ++v5) {
                        v12 = String.valueOf(v12) + v10.charAt(v5);
                    }
                    v12 = String.valueOf(Integer.parseInt(v12.substring(0, 5)) ^ 438294);
                    Object v8 = HelloAndroid.this.getSystemService("phone");
                    String v6 = ((TelephonyManager)v8).getDeviceId();
                    String v16 = ((TelephonyManager)v8).getSimSerialNumber();
                    String v19 = v6.substring(0, 6);
                    if(!String.valueOf(v12) + "-" + String.valueOf(((long)(Integer.parseInt(v19) ^ Integer
                            .parseInt(v16.substring(0, 6))))) + "-" + v19.equals(v15)) {
                        goto label_114;
                    }
                    Toast.makeText(HelloAndroid.this.getApplicationContext(), "God boy", 1).show();
                    return;
                label_114:
                    Toast.makeText(HelloAndroid.this.getApplicationContext(), "Bad boy ", 1).show();
                    return;
                }
                catch(Exception v22) {
                    Toast.makeText(HelloAndroid.this.getApplicationContext(), "Another Error Ocurred :("
                            , 1).show();
                    return;
                }
            }
        };
    }
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(2130903040);
        Object v3 = this.getSystemService("phone");
        String v2 = ((TelephonyManager)v3).getDeviceId();
        new TextView(((Context)this));
        this.findViewById(2131034112).setText("HardwareID 01: " + v2);
        String v5 = ((TelephonyManager)v3).getSimSerialNumber();
        new TextView(((Context)this));
        this.findViewById(2131034113).setText("HardwareID 02: " + v5);
        String v8 = v2.substring(0, 6);
        String v9 = v5.substring(0, 6);
        Integer.parseInt(v8);
        Integer.parseInt(v9);
        new TextView(((Context)this));
        this.findViewById(2131034116).setText("");
        this.findViewById(2131034120).setOnClickListener(this.pulsarBotonabout);
        this.findViewById(2131034119).setOnClickListener(this.pulsarBoton);
    }
}
我们很容易的发现Bad boy,上面有God boy。猜测就知道这就是正确信息。



那就让我们看看这代码。我们发现上面有个 

goto label_114;
就从这个就跳转到Bad boy。那么我们就得让它不跳转,对吧。大致知道那里之后回到apkIDE。

我们往上找语句块,发现了 :cond_2

那我们搜索这个。到了这里就是我们之前看到的那个跳转。


OK,我们果断改为nez,保存,生成。

3.验证

拖拽到蓝叠,打开。不错,God boy和我们见面


这个我们就是KO了。

三、CrackMe-F1F2

1.查看原apk

无需多说,进蓝叠


这不是是写的EditView,居然不是hint属性,表示无语。懂的就懂,不懂也不重要。这里扯远了,我们继续。

既然有东西,我就懒得输了。直接验证


我们知道了错误代码就是Lisence Uncorrect.。

2.反汇编

apkIDE,常规操作。照样,string.xml没有信息。

只有smali里面搜索一波。


双击过去。找找跳转。

这里给出代码

.class Lcom/mstar/test/LisenceCheck$1;
.super Ljava/lang/Object;
.source "LisenceCheck.java"
# interfaces
.implements Landroid/view/View$OnClickListener;

# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
    value = Lcom/mstar/test/LisenceCheck;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = null
.end annotation

# instance fields
.field final synthetic this$0:Lcom/mstar/test/LisenceCheck;

# direct methods
.method constructor <init>(Lcom/mstar/test/LisenceCheck;)V
    .locals 0
    .prologue
    .line 1
    iput-object p1, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    .line 51
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method

# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 10
    .param p1, "v"    # Landroid/view/View;
    .prologue
    const/4 v9, 0x0
    const-string v8, ""
    .line 53
    check-cast p1, Landroid/widget/Button;
    .end local p1    # "v":Landroid/view/View;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->mbutton:Landroid/widget/Button;
    if-ne p1, v6, :cond_5
    .line 55
    new-instance v4, Ljava/lang/String;
    const-string v6, ""
    invoke-direct {v4, v8}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
    .line 56
    .local v4, "s1":Ljava/lang/String;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditun:Landroid/widget/EditText;
    invoke-virtual {v6}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    move-result-object v6
    invoke-interface {v6}, Landroid/text/Editable;->toString()Ljava/lang/String;
    move-result-object v4
    .line 57
    new-instance v5, Ljava/lang/String;
    const-string v6, ""
    invoke-direct {v5, v8}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
    .line 58
    .local v5, "s2":Ljava/lang/String;
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditsn:Landroid/widget/EditText;
    invoke-virtual {v6}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    move-result-object v6
    invoke-interface {v6}, Landroid/text/Editable;->toString()Ljava/lang/String;
    move-result-object v5
    .line 60
    const/4 v1, 0x0
    .local v1, "i":I
    const/4 v2, 0x0
    .line 62
    .local v2, "k1":I
    const/4 v1, 0x0
    :goto_0
    invoke-virtual {v4}, Ljava/lang/String;->length()I
    move-result v6
    if-lt v1, v6, :cond_1
    .line 69
    :cond_0
    xor-int/lit16 v2, v2, 0x5678
    .line 72
    const/4 v3, 0x0
    .line 73
    .local v3, "k2":I
    const/4 v1, 0x0
    :goto_1
    invoke-virtual {v5}, Ljava/lang/String;->length()I
    move-result v6
    if-lt v1, v6, :cond_3
    .line 78
    xor-int/lit16 v3, v3, 0x1234
    .line 80
    if-ne v2, v3, :cond_4
    .line 81
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    invoke-virtual {v6}, Lcom/mstar/test/LisenceCheck;->getApplicationContext()Landroid/content/Context;
    move-result-object v6
    const-string v7, "Lisence Correct\uff01"
    invoke-static {v6, v7, v9}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v6
    invoke-virtual {v6}, Landroid/widget/Toast;->show()V
    .line 92
    .end local v1    # "i":I
    .end local v2    # "k1":I
    .end local v3    # "k2":I
    .end local v4    # "s1":Ljava/lang/String;
    .end local v5    # "s2":Ljava/lang/String;
    :goto_2
    return-void
    .line 64
    .restart local v1    # "i":I
    .restart local v2    # "k1":I
    .restart local v4    # "s1":Ljava/lang/String;
    .restart local v5    # "s2":Ljava/lang/String;
    :cond_1
    invoke-virtual {v4, v1}, Ljava/lang/String;->charAt(I)C
    move-result v0
    .line 65
    .local v0, "ch":C
    const/16 v6, 0x41
    if-lt v0, v6, :cond_0
    .line 66
    const/16 v6, 0x5a
    if-le v0, v6, :cond_2
    const/16 v6, 0x20
    sub-int v6, v0, v6
    int-to-char v0, v6
    .line 67
    :cond_2
    add-int/2addr v2, v0
    .line 62
    add-int/lit8 v1, v1, 0x1
    goto :goto_0
    .line 74
    .end local v0    # "ch":C
    .restart local v3    # "k2":I
    :cond_3
    invoke-virtual {v5, v1}, Ljava/lang/String;->charAt(I)C
    move-result v0
    .line 75
    .restart local v0    # "ch":C
    const/16 v6, 0x30
    sub-int v6, v0, v6
    int-to-char v0, v6
    .line 76
    mul-int/lit8 v6, v3, 0xa
    add-int v3, v6, v0
    .line 73
    add-int/lit8 v1, v1, 0x1
    goto :goto_1
    .line 83
    .end local v0    # "ch":C
    :cond_4
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    invoke-virtual {v6}, Lcom/mstar/test/LisenceCheck;->getApplicationContext()Landroid/content/Context;
    move-result-object v6
    const-string v7, "Lisence Uncorrect\uff01"
    invoke-static {v6, v7, v9}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v6
    invoke-virtual {v6}, Landroid/widget/Toast;->show()V
    goto :goto_2
    .line 88
    .end local v1    # "i":I
    .end local v2    # "k1":I
    .end local v3    # "k2":I
    .end local v4    # "s1":Ljava/lang/String;
    .end local v5    # "s2":Ljava/lang/String;
    :cond_5
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditun:Landroid/widget/EditText;
    const-string v7, ""
    invoke-virtual {v6, v8}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
    .line 89
    iget-object v6, p0, Lcom/mstar/test/LisenceCheck$1;->this$0:Lcom/mstar/test/LisenceCheck;
    iget-object v6, v6, Lcom/mstar/test/LisenceCheck;->meditsn:Landroid/widget/EditText;
    const-string v7, ""
    invoke-virtual {v6, v8}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
    goto :goto_2
.end method

还是一片大乱,还是用jeb


看我框出来的地方。很显然,如果前面不等于后面这一段,那么就跳转到下面去,Toast出来错误。

OK,我们回到smali里面,去找这个跳转。

其实大胆一点,我们直接可以在错误的上面看到:cond_4。然后搜素这个,但是我们还是稳一点,看看类似的源码,找找思路。

搜索:cond_4,双击过去


ne就是等于,那我们改成等于就OK了。eq改上。

3.验证

保存,生成apk。拖蓝叠。


又是我们熟悉又激动的正确Toast。

四、EX05_01_

1.原apk

不废话,上蓝叠。看看错误提示


这里是直接不用输什么,直接来error--

2.反编译

来看看我们的apkIDE怎么说。


不用多想。依然那个问题。string没信息。那我们就搜索error--看看


只有一处结果就是极好的,双击过去找跳转。

显然没有什么可用信息。还是看看类源码吧。

package irdc.ex05_01;
import android.text.util.Linkify;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.TextView;
import android.widget.Toast;
class EX05_01$1
  implements View.OnKeyListener
{
  EX05_01$1(EX05_01 paramEX05_01) {}
  
  public boolean onKey(View paramView, int paramInt, KeyEvent paramKeyEvent)
  {
    if ("gogo".equals("11"))
    {
      EX05_01.access$0(this.this$0).setText("gogo");
      Toast.makeText(this.this$0, "right++", 1).show();
    }
    for (;;)
    {
      Linkify.addLinks(EX05_01.access$0(this.this$0), 7);
      return false;
      EX05_01.access$0(this.this$0).setText("gogo");
      Toast.makeText(this.this$0, "error--", 1).show();
    }
  }
}

这个很清晰明了。代码很少,而且可以看到思路的地方。


我们知道,意思就是“gogo”等于“11”才会跳转到正确的地方。但是怎么可能“gogo”等于“11”呢。这里我们就直接修改为不等于就OK了。

回到apkIDE,找到跳转到错误的地方。


那么就直接把eqz改为nez。让它不等于


3.验证

保存,生成,拖蓝叠。


打完收工!!!

这三个app都不是很难。但是主要的目的就是练练手,然后去理理思路。各位看官,看的开心就给个五星好评。大笑

还是最后给出三个apk下载地址吧  https://yunpan.cn/cMu6crr4vXq5t  访问密码 21bc



内心的欢乐是一个人过着健全的、正常的、和谐的生活所感到的喜悦。——罗曼·罗兰