android Smali静态分析(一)

来源:互联网 发布:linux nvidia 驱动 编辑:程序博客网 时间:2024/06/01 09:17
文件头
.class <访问权限> [修饰关键字] <类名>.super <父类名>.source <源文件名>

示例

.class public Lcom/yiji/test/MainActivity;.super Landroid/app/Activity;.source "MainActivity.java"
字段
# static fields.field <访问权限> static [修饰关键字] <字段名>:<字段类型># instance fields.field <访问权限> [修饰关键字] <字段名>:<字段类型>

示例

# static fields.field public static final ARGS_KEY:Ljava/lang/String;# instance fields.field private btnOk:Landroid/widget/Button;
方法
# direct methods.method <访问权限> [修饰关键字] <方法原型>    <.locals>    [.parameter]    [.prologue]    [.line]    <代码体>.end method# virtual methods.method <访问权限> [修饰关键字] <方法原型>    <.locals>    [.parameter]    [.prologue]    [.line]    <代码体>.end method

.locals 局部变量个数
.parameter 参数个数,每条指令声明一个参数
.prologue 代码开始
.line 行号

接口
# interfaces.implements <接口名>
注解
# annotations.annotation [注解属性] <注解类名>    [注解字段=值].end annotation

示例

# instance fields.field public sayWhat:Ljava/lang/String;    .annotation runtime Lcom/droider/anno/MyAnnoField;        info = "Hello my friend"    .end annotation.end field

对应java代码

@com.droider.anno.MyAnnoField(info = "Hello my friend")public String sayWhat;

内部类

内部类有自己独立的smali文件,命名方式为“[外部类]$[内部类].smali”
示例

.class public Lcom/yiji/test/MainActivity$SNChecker;.super Ljava/lang/Object;.source "MainActivity.java"# annotations.annotation system Ldalvik/annotation/EnclosingClass;    value = Lcom/yiji/test/MainActivity;.end annotation.annotation system Ldalvik/annotation/InnerClass;    accessFlags = 0x1    name = "SNChecker".end annotation# instance fields.field private sn:Ljava/lang/String;.field final synthetic this$0:Lcom/yiji/test/MainActivity;# direct method.method public constructor <init>(Lcom/yiji/test/MainActivity;Ljava/lang/String;)V....end method# virtual methods.method public isRegistered()Z....end method

其中包含字段this0init()this0是指向外部类的引用,0表示层数,如下

public class Outer {               //this$0    public class FirstInner {      // this$1        public class SecondInner { // this$2            public class ThreadInner {            }        }    }}

synthetic属性表明是编译器合成

# direct methods.method public constructor <init>(Lcom/yiji/test/MainActivity;Ljava/lang/String;)V    .locals 0    .parameter # 第一个参数MainActivity引用    .parameter # 第二个参数sn    .progolue    iput-object p1, p0, Lcom/yiji/test/MainActivity$SNChecker;->this$0:Lcom/yiji/test/MainActivity; # 将MainActivity引用赋值给this$0    invoke-direct {p0}, Ljava/lang/Object;-><init>()V # 调用默认构造函数    iput-object p2, p0, Lcom/yiji/test/MainActivity$SNCheck;->sn:Ljava/lang/String; # 赋值sn.end method

这段代码使用了两条“.parameter”指令,却用到了p0-p2共3个寄存器,因为对非静态方法,会隐含p0寄存器指向this引用。

监听器
btn.setOnClickListener(new android.view.View.OnClickListener() {    @Override    public void onClick(View v) {        ...    }});
.method public onCreate(Landroid/os/Bundle;)V    .locals 2    .parameter "savedInstanceState"    ...    iget-object v0, p0, Lcom/yiji/test/MainActivity;->btn:Landroid/widget/Button;    new-instance v1, Lcom/yiji/test/MainActivity$1; # 新建MainActivity$1实例    invoke-direct {v1, p0}, Lcom/yiji/test/MainActivity$1;-><init>(Lcom/yiji/test/Mainactivity;)V # 初始化MainActivity$1实例    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V # 设置按钮点击事件

MainActivity$1.smali文件

.class Lcom/yiji/test/MainActivity$1.super Ljava/lang/Object;.source "MainActivity.java"# interfaces.implements Landroid/view/View$OnClickListener;# annotations.annotation system Ldalvik/annotation/EnclosingMethod;    value = Lcom/yiji/test/MainActivity;->onCreate(Landroid/os/Bundles;)V.end annotation.annotation system Ldalvik/annotation/InnerClass;    accessFlag = 0x0    name = null.end annotation# instance fields.field final synthetic this$0:Lcom/yiji/test/MainActivity;# direct methods.method constructor <init>(Lcom/yiji/test/MainActivity;)V    ....end method# virtual methods.method public onClick(Landroid/view/View;)V    ....end method
注解类

MemberClasses注解
在MainActivity.smali中有如下代码:

# annotations.annotation system Ldalvik/annotation/MemberClasses;    value = {        Lcom/yiji/test/MainActivity$SNChecker;    }.end annotations

MemberClasses是编译时自动加上的,查看MemberClasses注解类源码,如下:

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)@interface MemberClasses { }

可以看出MemberClasses是“系统注解”,记录一个内部类列表。

EnclosingMethod注解
在MainActivity$1.smali中有一段代码如下:

# annotations.annotation system Lcom/dalvik/annotation/EnclosingMethod;    value = Lcom/yiji/test/MainActivity;->onCreate(Landroid/os/Bundle;)V.end annotation

EnclosingMethod注解用来说明MainActivity$1类的作用范围,其中的Method说明它作用于一个方法,而value表明它位于MainActivity的onCreate()方法中。

EnclosingClass注解
在MainActivity$SNChecker.smali文件中,有如下代码:

# annotations.annotation system Ldalvik/annotation/EnclosingClass;    value = Lcom/yiji/test/MainActivity;.end annotation

EnclosingClass表明MainActivity$SNChecker作用于一个类,value表明这个类是MainActivity。

InnerClass注解

.annotation system Ldalvik/annotation/InnerClass;    accessFlags = 0x1    name = "SNChecker".end annotation

InnerClass表明是一个内部类,name表示内部类的名称,accessFlags访问标志,声明如下:

enum {    kDexVisibilityBuild    = 0x00,  /* annotation visibility */    kDexVisibilityRuntime  = 0x01,    kDexVisibilitySystem   = 0x02,};

AnnotationDefault注解
如果注解在声明时提供了默认值,那么会用到AnnotationDefault注解,示例:

# annotations.annotation system Ldalvik/annotation/AnnotationDefault;    value = .subannotation Lcom/yiji/test/anno/MyAnnoClass;        value = "MyAnnoClass"    .end subannotation.end annotation

可以看出MyAnnoClass类有一个默认值”MyAnnoClass”。

Signature注解
用于验证方法的签名

.method pubilc onItemClick(Landroid/widget/AdapterView;Landroid/view/View;IJ)V    .locals 6    .parameter    .parameter "v"    .parameter "position"    .parameter "id"    .annotation system Ldalvik/annotation/Signature;        value = {            "(",            "Landroid/widget/AdapterView",            "<*>;",            "Landroid/view/View;",            "IJ)V"        }    .end annotation    ....end method

Throws注解
如果方法抛出异常则生成相应的Throws注解

.method public final get()Ljava/lang/Object;    .locals 1    .annotation system Ldalvik/annotation/Throws;        value = {            Ljava/lang/InterruptedException;            Ljava/util/concurrent/ExcutionException;        }    .end annotation    ....end method

其他注解
- SuppressLint注解:去掉代码检查器的警告信息
- TargetApi注解:去掉代码版本检查的错误信息
- SdkConstant注解:被标记为@hide,指定sdk中可以被导出的常量
- Widget注解:被标记为@hide,表明是UI类

0 0