Android逆向分析之APKTool

来源:互联网 发布:linux 卸载chromium 编辑:程序博客网 时间:2024/04/30 05:22

由于刚踏入Android逆向分析领域,因此有许多的不懂,所以得不断地去学习。

因为是入门,我又有一定的Android应用开发基础,所以先从一些简单工程的反编译开始入手,先了解一些反编译所用到的工具。

上一次写博客,记录了反编译工具dex2jar和jd-gui 的使用,这次继续记录另一款比较强大的反编译工具APKTool。

该工具的使用方法很简单,只需要在dos控制台里输入apktool  d  xxx.apk 则可以在当前文件夹生成一个装有该APK的smali文件夹。

通过记事本可打开smali文件,可以看到一套以smali语法写的编码,实际上就是android虚拟机Dalvik的汇编语言。

算了,本人语言表达技术不好,还是直接上图清晰明了:

第一步,编写一个简单的应用工程,并打包APK,用于下面的反编译(直接用上一次博客中用到的登录界面应用):

MainActivity.java:

public class MainActivity extends Activity {    private final String ACCOUNT="samuel";    private final String PASSWORD="123456";    private EditText etAccount, etPassword;    private Button btnLogin;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        etAccount=(EditText)findViewById(R.id.et_account);        etPassword=(EditText)findViewById(R.id.et_password);        btnLogin=(Button)findViewById(R.id.btn_login);        btnLogin.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if(isOK(etAccount.getText().toString(), etPassword.getText().toString())){                    Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();                }else{                    Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();                }            }        });    }    private boolean isOK(String account, String password){        if(account.equals(ACCOUNT) && password.equals(PASSWORD))            return true;        else            return false;    }}
布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical"        android:layout_centerInParent="true">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:orientation="horizontal">            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="帐号:"/>            <EditText                android:id="@+id/et_account"                android:layout_width="100dp"                android:layout_height="wrap_content" />        </LinearLayout>        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:orientation="horizontal">            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="密码:"/>            <EditText                android:id="@+id/et_password"                android:layout_width="100dp"                android:layout_height="wrap_content" />        </LinearLayout>        <Button            android:id="@+id/btn_login"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center_horizontal"            android:text="登录"/>    </LinearLayout></RelativeLayout>

第二步,下载APKTool,下面底部附有下载连接:


第三步,dos下cd到APKTool的位置,再输入apktool  d  login.apk,回车进入反编译,完了后在当前文件夹下生成login文件夹,该文件夹里有smali文件:





第四步,用记事本打开login->smali中的LoginActivity.smali:

.class public Lcom/samuelzhan/logintest/LoginActivity;.super Landroid/app/Activity;# instance fields.field private final a:Ljava/lang/String;.field private final b:Ljava/lang/String;.field private c:Landroid/widget/EditText;.field private d:Landroid/widget/EditText;.field private e:Landroid/widget/Button;# direct methods.method public constructor <init>()V    .locals 1    invoke-direct {p0}, Landroid/app/Activity;-><init>()V    const-string v0, "samuel"    iput-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->a:Ljava/lang/String;    const-string v0, "123456"    iput-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->b:Ljava/lang/String;    return-void.end method.method static synthetic a(Lcom/samuelzhan/logintest/LoginActivity;)Landroid/widget/EditText;    .locals 1    iget-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->c:Landroid/widget/EditText;    return-object v0.end method.method static synthetic a(Lcom/samuelzhan/logintest/LoginActivity;Ljava/lang/String;Ljava/lang/String;)Z    .locals 1    invoke-direct {p0, p1, p2}, Lcom/samuelzhan/logintest/LoginActivity;->a(Ljava/lang/String;Ljava/lang/String;)Z    move-result v0    return v0.end method.method private a(Ljava/lang/String;Ljava/lang/String;)Z    .locals 1    const-string v0, "samuel"    invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z    move-result v0    if-eqz v0, :cond_0    const-string v0, "123456"    invoke-virtual {p2, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z    move-result v0    if-eqz v0, :cond_0    const/4 v0, 0x1    :goto_0    return v0    :cond_0    const/4 v0, 0x0    goto :goto_0.end method.method static synthetic b(Lcom/samuelzhan/logintest/LoginActivity;)Landroid/widget/EditText;    .locals 1    iget-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->d:Landroid/widget/EditText;    return-object v0.end method# virtual methods.method protected onCreate(Landroid/os/Bundle;)V    .locals 2    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V    const v0, 0x7f040019    invoke-virtual {p0, v0}, Lcom/samuelzhan/logintest/LoginActivity;->setContentView(I)V    const v0, 0x7f0c0050    invoke-virtual {p0, v0}, Lcom/samuelzhan/logintest/LoginActivity;->findViewById(I)Landroid/view/View;    move-result-object v0    check-cast v0, Landroid/widget/EditText;    iput-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->c:Landroid/widget/EditText;    const v0, 0x7f0c0051    invoke-virtual {p0, v0}, Lcom/samuelzhan/logintest/LoginActivity;->findViewById(I)Landroid/view/View;    move-result-object v0    check-cast v0, Landroid/widget/EditText;    iput-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->d:Landroid/widget/EditText;    const v0, 0x7f0c0052    invoke-virtual {p0, v0}, Lcom/samuelzhan/logintest/LoginActivity;->findViewById(I)Landroid/view/View;    move-result-object v0    check-cast v0, Landroid/widget/Button;    iput-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->e:Landroid/widget/Button;    iget-object v0, p0, Lcom/samuelzhan/logintest/LoginActivity;->e:Landroid/widget/Button;    new-instance v1, Lcom/samuelzhan/logintest/a;    invoke-direct {v1, p0}, Lcom/samuelzhan/logintest/a;-><init>(Lcom/samuelzhan/logintest/LoginActivity;)V    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V    return-void.end method

对比一下MainActivity.java里的源代码,其实Dalvik汇编语言还是比较好理解的。


第五步,修改smali文件,让登录系统无论帐号密码是否正确,均可以实现登录成功,即破解:


修改返回值,让它只返回0x1,即true


第六步,重新打包:

在dos下,cd到apktool.jar当前的位置,输入apktool  b  <刚刚反编译生成文件夹的路径>


反编译后和打包后的login文件夹会多出两个文件夹,dist里有打包后的apk


第七步,因为反编译后签名被破坏,需要重新签名才能在手机上安装:

签名工具很多,我这里使用的是Auto-sign,下面附加下载


用记事本打开批处理文件Sign.bat,并修改


修改后保存,并运行Sign.bat文件


多出一个已签名的APK,至此反编译修改smali文件重新打包的工作基本已完成,现在验证一下,是否输入任意的帐号密码也能显示登录成功。

效果图:


本来输入的帐号密码应该是 samuel   123456,现在随便输入都可以显示“登录成功”提示字符,说明破解成功了~

工具下载:APKTool & Auto-sign

0 0
原创粉丝点击