Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安全和逆向:如何逆向分析Android程序

安全和逆向:如何逆向分析Android程序

編輯:關於Android編程

經過前面對各種反編譯工具apktool,dx2jar,jd-gui等工具的介紹,本章節我們結合一個實際的案例,向大家講解如何分析Android程序。
一、分析步驟
1.使用dex2jar和jd-gui工具分析Java反編譯源碼;
2.使用apktools,反編譯Smail文件。由於Smail語法單獨閱讀比較困難,我們可以結合Java反編譯的源碼進行分析;
3.根據相關的特征和線索,修改Smail源碼,使用apktools重新打包;
4.使用jarsigner重新簽名apk,安裝並驗證修改是否正確,重復步驟3;
二 、案例簡介
這裡我們以最簡單的用戶登錄為案例,校驗用戶輸入用戶名和密碼通過,則Toast顯示Login Success!,否則Login Faild!(運行如下圖):

三、分析實踐
1.使用dex2jar和jd-gui工具分析Java反編譯登錄頁面源碼NextActivity(相關工具的使用,查看《安全和逆向》系列博客相關文章):

2.使用apktools(相關工具的使用,查看《安全和逆向》系列博客相關文章),反編譯Smail主要Smail文件(如下圖):

3.分析由Java源碼可知,相關的Smail文件為NextActivity.smail和NextActivity$1.smail文件(相關Smail語法,查看《安全和逆向》系列博客相關文章),詳細如下:
NextActivity.smail文件:
.class public Lcom/qunar/hotel/NextActivity; 
.super Landroid/support/v7/app/AppCompatActivity; 
.source "NextActivity.java" 

# instance fields 
.field private mLogin:Landroid/widget/Button; 
.field private mPassword:Landroid/widget/EditText; 
.field private mUser:Landroid/widget/EditText; 

# direct methods 
.method public constructor ()V 
    .locals 0 
 ... ... 
    return-object v0 
.end method 

# virtual methods 
.method protected onCreate(Landroid/os/Bundle;)V 
    .locals 2 
    .param p1, "aSavedInstanceState"    # Landroid/os/Bundle; 

    .prologue 
    .line 23 

    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V 

    .line 24 
    sget v0, Lcom/qunar/hotel/R$layout;->activity_next:I 
    invoke-virtual {p0, v0}, Lcom/qunar/hotel/NextActivity;->setContentView(I)V 

    .line 26 
    sget v0, Lcom/qunar/hotel/R$id;->user:I 
    invoke-virtual {p0, v0}, Lcom/qunar/hotel/NextActivity;->findViewById(I)Landroid/view/View; 
    move-result-object v0 
    check-cast v0, Landroid/widget/EditText; 
    iput-object v0, p0, Lcom/qunar/hotel/NextActivity;->mUser:Landroid/widget/EditText; 

    .line 27 
    sget v0, Lcom/qunar/hotel/R$id;->password:I 
    invoke-virtual {p0, v0}, Lcom/qunar/hotel/NextActivity;->findViewById(I)Landroid/view/View; 
    move-result-object v0 
    check-cast v0, Landroid/widget/EditText; 
    iput-object v0, p0, Lcom/qunar/hotel/NextActivity;->mPassword:Landroid/widget/EditText; 
 
    .line 28 
    sget v0, Lcom/qunar/hotel/R$id;->login:I 
    invoke-virtual {p0, v0}, Lcom/qunar/hotel/NextActivity;->findViewById(I)Landroid/view/View; 
    move-result-object v0 
    check-cast v0, Landroid/widget/Button; 
    iput-object v0, p0, Lcom/qunar/hotel/NextActivity;->mLogin:Landroid/widget/Button; 

    .line 30 
    iget-object v0, p0, Lcom/qunar/hotel/NextActivity;->mLogin:Landroid/widget/Button; 
    new-instance v1, Lcom/qunar/hotel/NextActivity$1; 
    invoke-direct {v1, p0}, Lcom/qunar/hotel/NextActivity$1;->(Lcom/qunar/hotel/NextActivity;)V 
    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V 

    .line 40 
    return-void 
.end method
NextActivity#1.smail文件:
.class Lcom/qunar/hotel/NextActivity$1; 
.super Ljava/lang/Object; 
.source "NextActivity.java" 

# interfaces 
.implements Landroid/view/View$OnClickListener; 

# annotations 
.annotation system Ldalvik/annotation/EnclosingMethod; 
    value = Lcom/qunar/hotel/NextActivity;->onCreate(Landroid/os/Bundle;)V 
.end annotation 

.annotation system Ldalvik/annotation/InnerClass; 
    accessFlags = 0x0 
    name = null 
.end annotation 

# instance fields 
.field final synthetic this$0:Lcom/qunar/hotel/NextActivity; 

# direct methods 
.method constructor (Lcom/qunar/hotel/NextActivity;)V 
    .locals 0 
    .param p1, "this$0"    # Lcom/qunar/hotel/NextActivity; 

    .prologue 
    .line 30 

    iput-object p1, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    invoke-direct {p0}, Ljava/lang/Object;->()V 

    return-void 
.end method 

# virtual methods 
.method public onClick(Landroid/view/View;)V 
    .locals 4 
    .param p1, "aView"    # Landroid/view/View; 

    .prologue 
    const/4 v3, 0x0 

    //判斷用戶名和密碼的正確性 
    .line 33 
    iget-object v0, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    # getter for: Lcom/qunar/hotel/NextActivity;->mUser:Landroid/widget/EditText; 
    invoke-static {v0}, Lcom/qunar/hotel/NextActivity;->access$000(Lcom/qunar/hotel/NextActivity;)Landroid/widget/EditText; 
    move-result-object v0 
    invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable; 
    move-result-object v0 
    invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String; 
    move-result-object v0 
    const-string v1, "user" 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z 
    move-result v0 
    //如果equals方法返回true 
    if-eqz v0, :cond_0 
    iget-object v0, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    # getter for: Lcom/qunar/hotel/NextActivity;->mPassword:Landroid/widget/EditText; 
    invoke-static {v0}, Lcom/qunar/hotel/NextActivity;->access$100(Lcom/qunar/hotel/NextActivity;)Landroid/widget/EditText; 
    move-result-object v0 
    invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable; 
    move-result-object v0 
    invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String; 
    move-result-object v0 
    const-string v1, "123456" 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z 
    move-result v0 
    //如果equals方法返回true 
    if-eqz v0, :cond_0 

    //登錄成功彈出Login Scuess Tost提示 
    .line 34 
    iget-object v0, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    invoke-virtual {v0}, Lcom/qunar/hotel/NextActivity;->getApplication()Landroid/app/Application; 
    move-result-object v0 
    iget-object v1, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    invoke-virtual {v1}, Lcom/qunar/hotel/NextActivity;->getResources()Landroid/content/res/Resources; 
    move-result-object v1 
    sget v2, Lcom/qunar/hotel/R$string;->login_success:I 
    invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; 
    move-result-object v1 
    invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; 
    move-result-object v0 
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V 

    .line 38 
    :goto_0 
    return-void 

    //登錄失敗彈出Login Faild Tost提示 
    .line 36 
    :cond_0 
    iget-object v0, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    invoke-virtual {v0}, Lcom/qunar/hotel/NextActivity;->getApplication()Landroid/app/Application; 
    move-result-object v0 
    iget-object v1, p0, Lcom/qunar/hotel/NextActivity$1;->this$0:Lcom/qunar/hotel/NextActivity; 
    invoke-virtual {v1}, Lcom/qunar/hotel/NextActivity;->getResources()Landroid/content/res/Resources; 
    move-result-object v1 
    sget v2, Lcom/qunar/hotel/R$string;->login_faild:I 
    invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; 
    move-result-object v1 
    invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; 
    move-result-object v0 
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V 
    goto :goto_0 
.end method 
4.分析相關Smail和Java文件,通過相關login_success,Toast,equals等關鍵字,閱讀出基本的代碼邏輯。該案例在Java源碼中已經清晰得出用戶名和密碼為user,123456,這裡我們演示如何通過分析修改smail文件“破譯”。閱讀關鍵代碼如下,我們可以將if(mUser.getText().toString().equals("user"))語句修改為if("user".equals("user")),同理if("12345".equals("123456")),即invoke-virtual {v0, v1}修改為invoke-virtual {v1, v1}即可“繞過”用戶名和密碼驗證。實際開發情況會比較復雜,這裡我們僅僅簡單修改用於演示分析過程;
//mUser.getText() 
invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable; 
move-result-object v0 
//mUser.getText().toString() 
invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String; 
move-result-object v0 
const-string v1, "user" 
//if(mUser.getText().toString.equals("user")) 
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z 
move-result v0 
//if(mUser.getText().toString.equals("user") == true) 
if-eqz v0, :cond_0 
5.重新打包並簽名apk(相關工具的使用,查看《安全和逆向》系列博客相關文章),安裝後驗證如下圖,成功“繞過”用戶名和密碼驗證;

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved