您的位置:首页 > 大数据 > 人工智能

Smail学习笔录

2016-02-22 16:27 501 查看
一、Smail的数据类型:B---byte C---char D---double F---float I---int J---long S---short V---void Z---boolean [XXX---arrayLxxx/yyy---object

这里解析下最后两项,数组的表示方式是:在基本类型前加上中括号“[”,例如int数组和float数组分别表示为:[I、[F;对象的表示则以L作为开头,格式是:LPackageName/objectName;(注意必须有个分号跟在后面),例如String对象在Smail中为:LJava/lang/String,其中Java/lang对应Java.lang.String就是定义在该包下的一个对象。

二、函数的定义:

函数的定义一般为:

Func-Name(Para-Type1Para-Type2Para-Type3Para...)Return-type

注意参数与参数之间没有任何分隔符:

1. foo ()V 表示 void foo();

2. foo(III)Z表示boolean foo(int,int,int);

3.foo(Z[I[ILjava/lang/String;J)L/java/lang/string; 表示:String foo(boolean,int[],int[],String,long)

三、Smail文件的具体介绍

1.Smail中的继承、接口、包信息首先看看开头的几行:

1] .class public Lcom/disney/WMW/WMWActivity;
2] .super Lcom/disney/common/BaseActivity;
3] .source "WMWActivity.java"
4]
5] # interfaces
6] .implements Lcom/burstly/lib/ui/IBurstlyAdListener;

7]
8] # annotations
9] .annotation system Ldalvik/annotation/MemberClasses;
10] value = {
11] Lcom/disney/WMW/WMWActivity$MessageHandler;,
12] Lcom/disney/WMW/WMWActivity$FinishActivityArgs;
13] }
14] .end annotation

1-3行定义的是基本信息:这是个由WMWActivity.java编译得到的smali文件(第3行)

它是com.disney.WMW这个package下的一个类,继承自com.disney.common.BaseActivity

5-6行定义的接口信息:这个类实现了一个com.burstly.lib.ui这个package下的BustyAdLsitener接口

8-14行定义的则是内部类:它有两个成员内部类----Messagehandler和FinishActivityArgs。

class WMWActivity extends BaseActivity implements IBurstlyAdListener{
//...
class MessageHandler {
//...
}
class FinishActivityArgs{
//...
}
}
值得注意的地方:Dalvik VM与JVM的最大区别之一就是Dalvik VM是基于寄存器。基于寄存器就是Smail里的所有操作都必须经过寄存器来进行;本地寄存器用V开头数字结尾的符号来表示,例如V0、V1、V2....参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2...特别注意的是,p0不一定是函数的第一个参数,在非static的函数中,p0代指“this”,p1表示函数的第一个参数,p2代表函数的第二个参数,而在static函数中的p0才对应第一参数(因为Java的static方法中没有this方法)。本地寄存器没有限制,理论上是可以任意使用的,下面例子:

const/4 v0, 0x0
iput-boolean v0, p0, Lcom/disney/WMW/WMWActivity;->isRunning:Z
上面的两句中,使用了V0寄存器,并把值0x0存到v0中,然后第二句用iput-boolan这个指令v0中的值存放到com.disney.WMWActivity.isRunning这个成员变量中,即相当于;this.isRunnning = false;在这里就是com.disney.WVMActivity实例。关于这两句话的具体指令和含暂可不用理会

2.Smail中的成员变量

下面学习有关成员变量的内容:

1 ] # static fields
2 ] .field private static final PREFS_INSTALLATION_IDjava/lang/String; = "installationId"
3 ] //...
4 ]

6 ] # instance fields
7 ] .field private _activityPackageNamejava/lang/String;
8 ] //...

上面定义的static fields和instance fields均为成员变量,格式是:field public/private[static][final] varName<类型>.然而static fields和 instance fields还是有区别的,当然区别很明显,那就是static fields 是static的,而instance则不是,根据这个区别来获取这些不同的成员变量是也有不同的指令。一般来说,获取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,操作的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等

没有“-object”后缀的表示操作的成员变量对象是基本数据类型,带“-object”表示操作的成员变量

是对象类型,特别低,Boolean类型则使用带“-Boolean”的指令操作。

(1)获取static fields的指令类似是:

sget-object v0, Lcom/disney/WMW/WMWActivity;->PREFS_INSTALLATION_ID:Ljava/lang/String;

sget-object就是用来获取变量值并保存到紧接着的参数的寄存器中,在这里,把上面出现的PREFS_INSTALLATION_ID这个String成员变量获取并放到v0这个寄存器中,注意:前面需要该变量所属的类的类型,后面需要加一个冒号和该成员变量的类型,中间是“->”表示所属关系。

(2)获取instance fields的指令与static fields的基本一样,只是由于不是static变量,不能仅仅指出该变量所在类的类型,还需要该变量所在类的实例。

3.Smail中的函数调用:

Smail中的而函数和成员变量一样也分为两种类型,但是不同成员变量的static和instance之分,而是direct和virtual之分,那么direct method和virtual method有什么区别呢?直白地讲,direct method 就是private 函数,其余的public和protect函数都属于virtual method。所以在调用函数时,有invoke-direct,invoke-virtual,另外还有invoke-static、invoke-super以及invoke-interface等几种不同的指令。当然其实还有invoke-XXX、range指令,这是参数多余4个的时候调用的指令

(1)、invoke-static;顾名思义就是调用static函数的,因为是static函数,所以比起其他调用少一个参数

invoke-static {}, Lcom/disney/WMW/UnlockHelper;->unlockCrankypack()Z
这里注意到 invoke-static后面有一对大括号“{}”,其实是调用该方法的实例+参数列表,由于这个方法既不需要参数也不需要static的,所以{}内为空

(2)、invoke-super“调用父类方法用的指令,在onCrete、onDestroy等方法都能看到

(3)、invoke-direct:调用private函数的,例如: invoke-direct {p0}, Lcom/disney/WMW/WMWActivity;->getGlobalIapHandler()Lcom/disney/config/GlobalPurchaseHandler;
这里GlobalPurchaseHandler getGlobalPurchaseHandler 就是定义WMWActivity中常见的private函数
,如果修改Smail时错用invoke-virtual或invoke-static将在回编译后 程序运行时引发一个常见的
VerifyError

(4)invoke-virtual:用于调用protect或者public函数,同样注意修改Smail时不要错用invoke-direct

4、Smail中函数实体分析

.method protected onDestroy()V
.locals 0

.prologue
.line 277
invoke-super {p0}, Lcom/disney/common/BaseActivity;->onDestroy()V

.line 279
return-void
.end method

这里是onDestroy()函数.local(),这句话很重要,表明你在这个函数中至少要用到本地寄存器的个数。

在这里,由于只需要调用一个父类的onDestroy()处理,所以只需要用到P0,所以使用的本地寄存器数为0

如果不清楚这个规则,很容易在植入代码后忘记修改.local的值,那么回编译后运行时将会得到一个VerifyError错误。
如果我在onDestroy()增加一句:this.existed = true;那么注意修改.local的值为1——使用到了v0这一个本地寄存器)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: