Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 靜態分析 smali

Android 靜態分析 smali

編輯:關於Android編程

一、smali語言簡介

1、宏觀的介紹:http://source.android.com/devices/tech/dalvik/instruction-formats.html

2、具體的指令:http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html

3、《Android安全與逆向分析》一書

4、具體指令中的meth@BBBB、filed@BBBB、type@BBBB,方法、字段、類型:https://code.google.com/p/smali/wiki/TypesMethodsAndFields

5、具體指令中的vXXX,寄存器,https://code.google.com/p/smali/wiki/Registers

注:非static函數中,p0代指“this”,p1表示函數的第一個參數,p2代表函數中的第二個參數…而在static函數中p0才對應第一個參數(因為Java的static方法中沒有this方法)

6、整體的格式(混淆後的,如果沒有混淆結構會更詳細)

(1)、類:

.class public Lcom/jltxgcy/crack/MainActivity;
.super Landroid/app/Activity;
(2)、方法:

# direct methods  or vitual methods
.method public constructor ()V
    .locals 0

    invoke-direct {p0}, Landroid/app/Activity;->()V

    return-void
.end method
直接方法指構造函數,私有方法,靜態方法。虛方法指的是其他的。

(3)、字段

# instance fields or static filelds
.field private a:Landroid/widget/Button;
(4)、接口

# interfaces
.implements Landroid/view/View$OnClickListener
7、還可以參考http://blog.csdn.net/lpohvbe/article/details/7981386

注:invoke-static:調用靜態方法,invoke-direct:調用私有或者構造函數,invoke-virtual:調用public或者protected方法。


二、工程源碼目錄

\

在Android混淆機制這篇文章中,http://blog.csdn.net/jltxgcy/article/details/22670651,對於上面的CrackApk工程,根據不同的proguard-project.txt的不同規則,導出兩個混淆後的apk,一個是CrackApk01.apk,一個是CrackApk02.apk。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgICAgIENyYWNrQXBrMDEuYXBrw7vT0LGjwfTE2rK/wOBpc1JlZ2lzdGVyZWS3vbeoo6xDcmFja0FwazAyLmFwa7GjwfTBy8Tasr/A4GlzUmVnaXN0ZXJlZLe9t6ihozwvcD4KPHA+PGJyPgo8L3A+CjxwPiAgICAgIMq508NhcGt0b29svfjQ0Le0seDS68G9uPZhcGujrLLOv7xodHRwOi8vYmxvZy5jc2RuLm5ldC9qbHR4Z2N5L2FydGljbGUvZGV0YWlscy8yMjY5MDc1M6Gj1+6688n6s8lzbWFsadPv0dShozxicj4KPC9wPgo8cD4gICAgPC9wPgo8cD4gICAgICDPwsPmztLDx8C0ttSxyLfWzva3tLHg0uvJ+rPJtcRzbWFsabrNQ3JhY2tBcGu5pLPM1tC21NOmtcRqYXZhzsS8/qGjPC9wPgo8cD48YnI+CjwvcD4KPHA+ICAgICAgytfPyLfWzvZDcmFja0FwazAxLmFwa6GjPC9wPgo8cD4gICAgICAgTWFpbkFjdGl2aXR5LmphdmG0+sLryOfPwqO6PC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">package com.jltxgcy.crack; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private Button btnAnno; private Button btnCheckSN; private EditText edtSN; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnAnno = (Button) findViewById(R.id.btn_annotation); btnCheckSN = (Button) findViewById(R.id.btn_checksn); edtSN = (EditText) findViewById(R.id.edt_sn); btnAnno.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { getAnnotations(); } }); btnCheckSN.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SNChecker checker = new SNChecker(edtSN.getText().toString()); String str = checker.isRegistered() ? "注冊成功" : "注冊失敗"; Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); } }); } private void getAnnotations() { try { Toast.makeText(this, "getAnnotations", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } public class SNChecker { private String sn; public SNChecker(String sn) { this.sn = sn; } public boolean isRegistered() { boolean result = false; char ch = '\0'; int sum = 0; if (sn == null || (sn.length() < 8)) return result; int len = sn.length(); if (len == 8) { ch = sn.charAt(0); switch (ch) { case 'a': case 'f': result = true; break; default: result = false; break; } if (result) { ch = sn.charAt(3); switch (ch) { case '1': case '2': case '3': case '4': case '5': result = true; break; default: result = false; break; } } } else if (len == 16) { for (int i = 0; i < len; i++) { char chPlus = sn.charAt(i); sum += (int) chPlus; } result = ((sum % 6) == 0) ? true : false; } return result; } } }
MainActivity.java對應的反編譯過來的smali是以下四個文件,a.smali,b.smali,c.smali,MainActivity.smali

a.smali代碼如下:

.class final Lcom/jltxgcy/crack/a;
.super Ljava/lang/Object;

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


# instance fields
.field final synthetic a:Lcom/jltxgcy/crack/MainActivity;


# direct methods
.method constructor (Lcom/jltxgcy/crack/MainActivity;)V
    .locals 0

    iput-object p1, p0, Lcom/jltxgcy/crack/a;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;->()V

    return-void
.end method


# virtual methods
.method public final onClick(Landroid/view/View;)V
    .locals 1

    iget-object v0, p0, Lcom/jltxgcy/crack/a;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-static {v0}, Lcom/jltxgcy/crack/MainActivity;->a(Lcom/jltxgcy/crack/MainActivity;)V

    return-void
.end method

b.smali代碼如下:

.class final Lcom/jltxgcy/crack/b;
.super Ljava/lang/Object;

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


# instance fields
.field final synthetic a:Lcom/jltxgcy/crack/MainActivity;


# direct methods
.method constructor (Lcom/jltxgcy/crack/MainActivity;)V
    .locals 0

    iput-object p1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;->()V

    return-void
.end method


# virtual methods
.method public final onClick(Landroid/view/View;)V
    .locals 7

    const/16 v6, 0x8

    const/4 v0, 0x1

    const/4 v1, 0x0

    new-instance v4, Lcom/jltxgcy/crack/c;

    iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    iget-object v3, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-static {v3}, Lcom/jltxgcy/crack/MainActivity;->b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText;

    move-result-object v3

    invoke-virtual {v3}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object v3

    invoke-interface {v3}, Landroid/text/Editable;->toString()Ljava/lang/String;

    move-result-object v3

    invoke-direct {v4, v2, v3}, Lcom/jltxgcy/crack/c;->(Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V

    iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    if-eqz v2, :cond_0

    iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    invoke-virtual {v2}, Ljava/lang/String;->length()I

    move-result v2

    if-ge v2, v6, :cond_2

    :cond_0
    move v0, v1

    :cond_1
    :goto_0
    :pswitch_0
    if-eqz v0, :cond_5

    const-string v0, "\u6ce8\u518c\u6210\u529f"

    :goto_1
    iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-static {v2, v0, v1}, 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

    return-void

    :cond_2
    iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    invoke-virtual {v2}, Ljava/lang/String;->length()I

    move-result v5

    if-ne v5, v6, :cond_3

    iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    invoke-virtual {v2, v1}, Ljava/lang/String;->charAt(I)C

    move-result v2

    sparse-switch v2, :sswitch_data_0

    move v2, v1

    :goto_2
    if-eqz v2, :cond_7

    iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    const/4 v3, 0x3

    invoke-virtual {v2, v3}, Ljava/lang/String;->charAt(I)C

    move-result v2

    packed-switch v2, :pswitch_data_0

    move v0, v1

    goto :goto_0

    :sswitch_0
    move v2, v0

    goto :goto_2

    :cond_3
    const/16 v2, 0x10

    if-ne v5, v2, :cond_6

    move v2, v1

    move v3, v1

    :goto_3
    if-lt v3, v5, :cond_4

    rem-int/lit8 v2, v2, 0x6

    if-eqz v2, :cond_1

    move v0, v1

    goto :goto_0

    :cond_4
    iget-object v6, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    invoke-virtual {v6, v3}, Ljava/lang/String;->charAt(I)C

    move-result v6

    add-int/2addr v2, v6

    add-int/lit8 v3, v3, 0x1

    goto :goto_3

    :cond_5
    const-string v0, "\u6ce8\u518c\u5931\u8d25"

    goto :goto_1

    :cond_6
    move v0, v1

    goto :goto_0

    :cond_7
    move v0, v2

    goto :goto_0

    nop

    :sswitch_data_0
    .sparse-switch
        0x61 -> :sswitch_0
        0x66 -> :sswitch_0
    .end sparse-switch

    :pswitch_data_0
    .packed-switch 0x31
        :pswitch_0
        :pswitch_0
        :pswitch_0
        :pswitch_0
        :pswitch_0
    .end packed-switch
.end method

c.smali代碼如下:

.class public final Lcom/jltxgcy/crack/c;
.super Ljava/lang/Object;


# instance fields
.field a:Ljava/lang/String;

.field final synthetic b:Lcom/jltxgcy/crack/MainActivity;


# direct methods
.method public constructor (Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V
    .locals 0

    iput-object p1, p0, Lcom/jltxgcy/crack/c;->b:Lcom/jltxgcy/crack/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;->()V

    iput-object p2, p0, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String;

    return-void
.end method

MainActivity.smali代碼如下:

.class public Lcom/jltxgcy/crack/MainActivity;
.super Landroid/app/Activity;


# instance fields
.field private a:Landroid/widget/Button;

.field private b:Landroid/widget/Button;

.field private c:Landroid/widget/EditText;


# direct methods
.method public constructor ()V
    .locals 0

    invoke-direct {p0}, Landroid/app/Activity;->()V

    return-void
.end method

.method static synthetic a(Lcom/jltxgcy/crack/MainActivity;)V
    .locals 2

    :try_start_0
    const-string v0, "getAnnotations"

    const/4 v1, 0x0

    invoke-static {p0, v0, v1}, 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
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

    :goto_0
    return-void

    :catch_0
    move-exception v0

    invoke-virtual {v0}, Ljava/lang/Exception;->printStackTrace()V

    goto :goto_0
.end method

.method static synthetic b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText;
    .locals 1

    iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->c:Landroid/widget/EditText;

    return-object v0
.end method


# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
    .locals 2

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

    const/high16 v0, 0x7f03

    invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->setContentView(I)V

    const/high16 v0, 0x7f08

    invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->a:Landroid/widget/Button;

    const v0, 0x7f080002

    invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->b:Landroid/widget/Button;

    const v0, 0x7f080001

    invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/EditText;

    iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->c:Landroid/widget/EditText;

    iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->a:Landroid/widget/Button;

    new-instance v1, Lcom/jltxgcy/crack/a;

    invoke-direct {v1, p0}, Lcom/jltxgcy/crack/a;->(Lcom/jltxgcy/crack/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->b:Landroid/widget/Button;

    new-instance v1, Lcom/jltxgcy/crack/b;

    invoke-direct {v1, p0}, Lcom/jltxgcy/crack/b;->(Lcom/jltxgcy/crack/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    return-void
.end method

.method public onCreateOptionsMenu(Landroid/view/Menu;)Z
    .locals 2

    invoke-virtual {p0}, Lcom/jltxgcy/crack/MainActivity;->getMenuInflater()Landroid/view/MenuInflater;

    move-result-object v0

    const/high16 v1, 0x7f07

    invoke-virtual {v0, v1, p1}, Landroid/view/MenuInflater;->inflate(ILandroid/view/Menu;)V

    const/4 v0, 0x1

    return v0
.end method

MyApp.java代碼如下:

package com.jltxgcy.crack.app;

import android.app.Application;
import android.widget.Toast;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import com.jltxgcy.crack.MainActivity;

public class MyApp extends Application{

    @Override
    public void onCreate() {
    	Toast.makeText(this, "app creat", Toast.LENGTH_SHORT).show();
        super.onCreate();
    }
    
}

MyApp.java對應的反編譯出來的smali文件為MyApp.smali

MyApp.smali代碼如下:

.class public Lcom/jltxgcy/crack/app/MyApp;
.super Landroid/app/Application;


# direct methods
.method public constructor ()V
    .locals 0

    invoke-direct {p0}, Landroid/app/Application;->()V

    return-void
.end method


# virtual methods
.method public onCreate()V
    .locals 2

    const-string v0, "app creat"

    const/4 v1, 0x0

    invoke-static {p0, v0, v1}, 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

    invoke-super {p0}, Landroid/app/Application;->onCreate()V

    return-void
.end method

然後我們來分析CrackApk02.apk,由於混淆機制保存了內部類isRegister,所以b.smail和c.smail有所不同。

b.smali代碼如下:

.class final Lcom/jltxgcy/crack/b;
.super Ljava/lang/Object;

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


# instance fields
.field final synthetic a:Lcom/jltxgcy/crack/MainActivity;


# direct methods
.method constructor (Lcom/jltxgcy/crack/MainActivity;)V
    .locals 0

    iput-object p1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;->()V

    return-void
.end method


# virtual methods
.method public final onClick(Landroid/view/View;)V
    .locals 3

    new-instance v0, Lcom/jltxgcy/crack/c;

    iget-object v1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-static {v2}, Lcom/jltxgcy/crack/MainActivity;->b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText;

    move-result-object v2

    invoke-virtual {v2}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object v2

    invoke-interface {v2}, Landroid/text/Editable;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-direct {v0, v1, v2}, Lcom/jltxgcy/crack/c;->(Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V

    invoke-virtual {v0}, Lcom/jltxgcy/crack/c;->isRegistered()Z

    move-result v0

    if-eqz v0, :cond_0

    const-string v0, "\u6ce8\u518c\u6210\u529f"

    :goto_0
    iget-object v1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity;

    const/4 v2, 0x0

    invoke-static {v1, v0, v2}, 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

    return-void

    :cond_0
    const-string v0, "\u6ce8\u518c\u5931\u8d25"

    goto :goto_0
.end method

c.smali代碼如下:

.class public final Lcom/jltxgcy/crack/c;
.super Ljava/lang/Object;


# instance fields
.field final synthetic a:Lcom/jltxgcy/crack/MainActivity;

.field private b:Ljava/lang/String;


# direct methods
.method public constructor (Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V
    .locals 0

    iput-object p1, p0, Lcom/jltxgcy/crack/c;->a:Lcom/jltxgcy/crack/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;->()V

    iput-object p2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    return-void
.end method


# virtual methods
.method public final isRegistered()Z
    .locals 6

    const/16 v3, 0x8

    const/4 v0, 0x1

    const/4 v1, 0x0

    iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    if-eqz v2, :cond_0

    iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    invoke-virtual {v2}, Ljava/lang/String;->length()I

    move-result v2

    if-ge v2, v3, :cond_1

    :cond_0
    :goto_0
    return v1

    :cond_1
    iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    invoke-virtual {v2}, Ljava/lang/String;->length()I

    move-result v4

    if-ne v4, v3, :cond_3

    iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    invoke-virtual {v2, v1}, Ljava/lang/String;->charAt(I)C

    move-result v2

    sparse-switch v2, :sswitch_data_0

    move v2, v1

    :goto_1
    if-eqz v2, :cond_5

    iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    const/4 v3, 0x3

    invoke-virtual {v2, v3}, Ljava/lang/String;->charAt(I)C

    move-result v2

    packed-switch v2, :pswitch_data_0

    move v0, v1

    :cond_2
    :goto_2
    :pswitch_0
    move v1, v0

    goto :goto_0

    :sswitch_0
    move v2, v0

    goto :goto_1

    :cond_3
    const/16 v2, 0x10

    if-ne v4, v2, :cond_0

    move v2, v1

    move v3, v1

    :goto_3
    if-lt v3, v4, :cond_4

    rem-int/lit8 v2, v2, 0x6

    if-eqz v2, :cond_2

    move v0, v1

    goto :goto_2

    :cond_4
    iget-object v5, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String;

    invoke-virtual {v5, v3}, Ljava/lang/String;->charAt(I)C

    move-result v5

    add-int/2addr v2, v5

    add-int/lit8 v3, v3, 0x1

    goto :goto_3

    :cond_5
    move v1, v2

    goto :goto_0

    :sswitch_data_0
    .sparse-switch
        0x61 -> :sswitch_0
        0x66 -> :sswitch_0
    .end sparse-switch

    :pswitch_data_0
    .packed-switch 0x31
        :pswitch_0
        :pswitch_0
        :pswitch_0
        :pswitch_0
        :pswitch_0
    .end packed-switch
.end method

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