Android 静态分析smail

     即前篇文章Android 静态分析 smali,我一直在思考以下几个问题:

     1、子类使用的父类中的方法,那么对应的smail是invoke-super还是invoke-virtual呢?对应的类是父类还是子类呢?

     解释:invoke-direct {p0}, Landroid/app/Activity;-><init>()V,这里所说的父类还是子类指的是invoke参数后面跟着的类,在这个例子中是Landroid/app/Activity。

     2、在抽象的父类中使用抽象的方法,但是这个方法的实现却在子类,那么对应的smali的类是父类还是子类呢?

     3、生成子类的对象后,通过这个对象去调用父类的方法,那么对应的smali的类是父类还是子类呢?

     4、如果子类向上转型为父类,再调用被子类覆盖的方法时,那么对应的smali的类是父类还是子类呢?

     5、如果子类向上转型为父类,并且父类是接口,再调用被子类覆盖的接口中的方法时,那么对应的smali的类是父类还是子类呢?


     带着这些疑问,我们先建一个Android工程。

     MainActivity.java

package com.example.crackdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//生成子类对象(子类public构造函数),可以使用子类public方法和父类未被覆盖的public方法。
		SubClass subClass = new SubClass(this);
		subClass.doSomething();
		subClass.doSuperSomething(this);
		
		//如果向上转型生成父类对象,只能调用父类的public方法如果子类复写了该方法,那么调用子类的对应方法。
		SuperClass subClass1 = new SubClass(this);
		subClass1.doSubSomething();
		
		//如果向下转型,可以使用子类public方法和父类未被覆盖的public方法。
		//如果被覆盖了,则调用子类的对应方法
		SubClass subClass2 = (SubClass) subClass1;
		subClass2.doSubSomething();
		
		//如果向上转型生成父类对象,只能调用父类的public方法如果子类复写了该方法,那么调用子类的对应方法。
		SuperInterface superInterface = new SubClass(this);
		superInterface.doInterfaceSomething();
	}
}


     SubClass.java

package com.example.crackdemo;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

public class SubClass extends SuperClass implements SuperInterface {
	private Context mContext;

	public SubClass(Context context) {
		mContext = context;
	}

	@Override
	public void doSubSomething() {
		Toast.makeText(mContext, "doSubSomething", Toast.LENGTH_LONG).show();
	}

	public void doSomething() {
		doSuperSomething(mContext);
		doOwnSomething();
	}
	
	private void doOwnSomething() {
		Toast.makeText(mContext, "doOwnSomething", Toast.LENGTH_LONG).show();
	}

	@Override
	public void doInterfaceSomething() {
		Log.d("jltxgcy", "doInterfaceSomething");
	}

}

     SuperClass.java

package com.example.crackdemo;

import android.content.Context;
import android.widget.Toast;

public abstract class SuperClass {
	public abstract void doSubSomething();
	
	public void doSuperSomething(Context context){
		doSubSomething();
		Toast.makeText(context, "doSuperSomething", Toast.LENGTH_LONG).show();
	}
}

    SuperInterface.java

package com.example.crackdemo;

public interface SuperInterface {
	public void doInterfaceSomething();
}

    反编译,生成的smail:

     MainActivity.smali

.class public Lcom/example/crackdemo/MainActivity;
.super Landroid/app/Activity;


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

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

    return-void
.end method


# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1

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

    const/high16 v0, 0x7f030000

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

    new-instance v0, Lcom/example/crackdemo/a;

    invoke-direct {v0, p0}, Lcom/example/crackdemo/a;-><init>(Landroid/content/Context;)V

    invoke-virtual {v0}, Lcom/example/crackdemo/a;->b()V

    invoke-virtual {v0, p0}, Lcom/example/crackdemo/a;->a(Landroid/content/Context;)V //调用了父类的doSuperSomething
	

    new-instance v0, Lcom/example/crackdemo/a;

    invoke-direct {v0, p0}, Lcom/example/crackdemo/a;-><init>(Landroid/content/Context;)V

    invoke-virtual {v0}, Lcom/example/crackdemo/b;->a()V //调用了子类的doSubSomething
	

    check-cast v0, Lcom/example/crackdemo/a;

    invoke-virtual {v0}, Lcom/example/crackdemo/a;->a()V //调用了子类的doSubSomething
	

    new-instance v0, Lcom/example/crackdemo/a;

    invoke-direct {v0, p0}, Lcom/example/crackdemo/a;-><init>(Landroid/content/Context;)V

    invoke-interface {v0}, Lcom/example/crackdemo/c;->c()V //调用了子类的doInterfaceSomething

    return-void
.end method

     a.smail(SubClass.java)

.class public Lcom/example/crackdemo/a;
.super Lcom/example/crackdemo/b;

# interfaces
.implements Lcom/example/crackdemo/c;


# instance fields
.field private a:Landroid/content/Context;


# direct methods
.method public constructor <init>(Landroid/content/Context;)V
    .locals 0

    invoke-direct {p0}, Lcom/example/crackdemo/b;-><init>()V

    iput-object p1, p0, Lcom/example/crackdemo/a;->a:Landroid/content/Context;

    return-void
.end method

.method private d()V  //private void doOwnSomething()
    .locals 3

    iget-object v0, p0, Lcom/example/crackdemo/a;->a:Landroid/content/Context;

    const-string v1, "doOwnSomething"

    const/4 v2, 0x1

    invoke-static {v0, v1, 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
.end method


# virtual methods
.method public a()V  //public void doSubSomething()
    .locals 3

    iget-object v0, p0, Lcom/example/crackdemo/a;->a:Landroid/content/Context;

    const-string v1, "doSubSomething"

    const/4 v2, 0x1

    invoke-static {v0, v1, 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
.end method

.method public b()V //public void doSomething()
    .locals 1

    iget-object v0, p0, Lcom/example/crackdemo/a;->a:Landroid/content/Context;

    invoke-virtual {p0, v0}, Lcom/example/crackdemo/a;->a(Landroid/content/Context;)V //调用了父类的doSuperSomething

    invoke-direct {p0}, Lcom/example/crackdemo/a;->d()V

    return-void
.end method

.method public c()V //public void doInterfaceSomething()
    .locals 2

    const-string v0, "jltxgcy"

    const-string v1, "doInterfaceSomething"

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    return-void
.end method

     b.smali(SuperClass.java)

.class public abstract Lcom/example/crackdemo/b;
.super Ljava/lang/Object;


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

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

    return-void
.end method


# virtual methods
.method public abstract a()V
.end method

.method public a(Landroid/content/Context;)V
    .locals 2

    invoke-virtual {p0}, Lcom/example/crackdemo/b;->a()V //调用了子类的doSubSomething	

    const-string v0, "doSuperSomething"

    const/4 v1, 0x1

    invoke-static {p1, 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
.end method

     c.smali(SuperInterface.java)

.class public interface abstract Lcom/example/crackdemo/c;
.super Ljava/lang/Object;


# virtual methods
.method public abstract c()V
.end method

     回答第一个问题:

     在a.smail中的方法b,对应SubClass类中doSomething中调用了父类的doSuperSomething,如下:

     invoke-virtual {p0, v0}, Lcom/example/crackdemo/a;->a(Landroid/content/Context;)V ,我们看到这里使用的是invoke-virtual,并且->前面使用的是子类,但是->后面的方法a(Landroid/content/Context;)V,却是父类的方法。

     如果在java中是这样写的:

public void doSomething() {
		super.doSuperSomething(mContext);
		doOwnSomething();
	}
     那么对应的smail是这样的,  invoke-super{p0, v0}, Lcom/example/crackdemo/b;->a(Landroid/content/Context;)V,此时使用的invoke-super,并且->前面使用的是父类。

     回答第二个问题:

     在b.smali的方法a,对应SuperClass类中doSuperSomething中调用了doSubSomething,如下:

     invoke-virtual {p0}, Lcom/example/crackdemo/b;->a()V,我们看到这里使用的是invoke-virtual,此时->前面Lcom/example/crackdemo/b使用的是父类,但->后面a()V实际调用的却是子类中方法。


    回答第三个问题:

		SubClass subClass = new SubClass(this);
		subClass.doSomething();
		subClass.doSuperSomething(this);
     doSuperSomething对应的smali如下,在MainActivity.smali的onCreate方法:

invoke-virtual {v0, p0}, Lcom/example/crackdemo/a;->a(Landroid/content/Context;)V
    我们可以看到->前面Lcom/example/crackdemo/a使用的是子类,但->后面a(Landroid/content/Context;)V实际调用的是父类中的方法。


    回答第四个问题:

//如果向上转型生成父类对象,只能调用父类的public方法如果子类复写了该方法,那么调用子类的对应方法。
		SuperClass subClass1 = new SubClass(this);
		subClass1.doSubSomething();
    doSubSomething 对应的smali如下,在MainActivity.smali的onCreate方法:

invoke-virtual {v0}, Lcom/example/crackdemo/b;->a()V
    我们可以看到->前面Lcom/example/crackdemo/b使用的是父类的b,但 ->后面a()V实际上调用的是子类中的方法。

     回答第五个问题:

//如果向上转型生成父类对象,只能调用父类的public方法如果子类复写了该方法,那么调用子类的对应方法。
		SuperInterface superInterface = new SubClass(this);
		superInterface.doInterfaceSomething();
     doInterfaceSomething 对应的smali如下,在MainActivity.smali的onCreate方法:

    invoke-interface {v0}, Lcom/example/crackdemo/c;->c()V //调用了子类的doInterfaceSomething
      我们可以看到->前面 Lcom/example/crackdemo/c 使用的是父类接口c,但 ->后面c()V 实际上调用的是子类中的方法。

你可能感兴趣的:(Android 静态分析smail)