Android 逆向分析(一) 之 Smali语法

Smali 语法

引言

  • 你们都知道apk安装包其实就是个zip包,咱们经过解压软件解压出来会看到里面的架构java

    • assets数组

    • META_INF 存放签名信息缓存

    • lib架构

      • arm
      • ...
    • res性能

    • AndroidManifest.xml优化

    • classes.dex Java代码编译获得的Dalvik VM能直接执行的文件编码

    • resources.arsc翻译

asset和res资源目录的不一样在于:设计

1. res目录下的资源文件在编译时会自动生成索引文件(R.java),assets的资源文件不须要生成索引,在Java代码中须要用AssetManager来访问

 2. 通常来讲,除了音频和视频资源(须要放在raw或asset下),使用Java开发的Android工程使用到的资源文件都会放在res下;使用C++游戏引擎(或使用Lua binding等)的资源文件均须要放在assets下。

Dalvik

  • Dalvik虚拟机是Google等厂商合做开发的Android移动设备平台的核心组成部分之一。 它能够支持已转换为 .dex格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。 Dalvik 通过优化,容许在有限的内存中同时运行多个虚拟机的实例,而且每个Dalvik 应用做为一个独立的Linux 进程执行。独立的进程能够防止在虚拟机崩溃的时候全部程序都被关闭。

Dalvik和JVM 的关系

  • Dalvik是基于寄存器的,而JVM是基于栈的。Dalvik运行dex文件,而JVM运行java字节码自Android 2.2开始,Dalvik支持JIT(just-in-time,即时编译技术)。优化后的Dalvik较其余标准虚拟机存在一些不一样特性: 
    • 1.占用更少空间 
    • 2.为简化翻译,常量池只使用32位索引  
    • 3.标准Java字节码实行8位堆栈指令,Dalvik使用16位指令集直接做用于局部变量。局部变量一般来自4位的“虚拟寄存器”区。这样减小了Dalvik的指令计数,提升了翻译速度。 当Android启动时,Dalvik VM 监视全部的程序(APK),而且建立依存关系树,为每一个程序优化代码并存储在Dalvik缓存中。Dalvik第一次加载后会生成Cache文件,以提供下次快速加载,因此第一次会很慢。Dalvik解释器采用预先算好的Goto地址,每一个指令对内存的访问都在64字节边界上对齐。这样能够节省一个指令后进行查表的时间。为了强化功能, Dalvik还提供了快速翻译器(Fast Interpreter)。

ART

  • Android Runtimecode

    ART 的机制与 Dalvik 不一样。在Dalvik下,应用每次运行的时候,字节码都须要经过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫作预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。

  • 优缺点

    优势:

    - 一、系统性能的显著提高。
      - 二、应用启动更快、运行更快、体验更流畅、触感反馈更及时。
      - 三、更长的电池续航能力。
      - 四、支持更低的硬件。

    缺点:

    - 1.机器码占用的存储空间更大,字节码变为机器码以后,可能会增长10%-20%(不过在应用包中,可执行的代码经常只是一部分。好比最新的 Google+ APK 是 28.3 MB,可是代码只有 6.9 MB。)
      - 2.应用的安装时间会变长。

一 Smali语法:Registers(寄存器)

  • 引言

    在Dalvik字节码中,寄存器都是32位的,可以支持任何类型。64位类型(Long和Double型)用2个寄存器表示。有两种方式指定一个方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的总数。.locals指令代表了方法中非参寄存器的数量。

  • 寄存器命名方式

    V命名方式和P命名方式。P命名方式中的第一个寄存器就是方法中的第一个参数寄存器。

    • 敲黑板 举例说明: 若是一个方法有3个参数,5个寄存器 表示方法以下

      - v0                 the first local Register
        - v1				 the second local Register
        - v2		p1       the first parameter Register
        - v3		p2       the second parameter  Register
        - v4		p3       the thrid parameter  Register

    你能够用任何一种方式来引用参数寄存器——他们没有任何差异。

Smali 语法

  • 数据类型

    JAVA 对比 Smali

    - byte					B
      - boolean               Z
      - int                   I
      - float                 F
      - long                  J   64bit  两个寄存器
      - double                D   64bit  两个寄存器
      - short                 S
      - char                  C
      - void                  V
      - Object                L    L 表明对象 注意区别 long
      - Array                 [

    对象类型

    L能够表示java类型中的任何类.在java代码中以package.name.ObjectName的方式引用,而在Davilk中其描述则是以Lpackage/name/ObjectName;的形式表示.L即上面定义的JAVA类类型,表示后面跟着的是类的全限定名.好比java中的java.lang.String对应的描述--> Ljava/lang/String

    数组类型

    "[" 类型用来表示全部基本类型的数组,"["后跟着是基本类型的描述符.每一维度使用一个前置的"[", 好比java中的int[] 用汇编码表示即是**[I**;二维数组int[][][[I,三维数组则用**[[[I**表示.

    对于对象数组来讲,"["后跟着对应类的全限定符.好比java当中的String[]对应的是[java/lang/String;.

  • 字段描述

    基本类型和引用类型,不过两种类型引用格式类型相同

    - 对象类型描述符->字段名:类型描述符
      - eg:好比org.professor.demo 里面个Test类,该类中有两个变量,一个为int  一个为String
      Lorg/professor/demo/Test;->name:Ljava/lang/String;
      Lorg/professor/demo/Test;->age:I
  • 方法描述

    JAVA中方法的签名包括方法名,参数及返回值,在Smali相应的描述规则为:

    对象类型描述符->方法名(参数类型描述符)返回值类型描述符
      eg:
      java方法:public char charAt(int index){...}
      Davilk描述:Ljava/lang/String;->charAt(I)C
    
      java方法:public void getChars(int srcBegin,int srcEnd,char dst[],int dstBegin){...}
      Davilk描述:Ljava/lang/String;->getChars(II[CI)V
    
      java方法:public boolean equals(Object anObject){...}
      Davilk描述:Ljava/lang/String;->equals(Ljava/lang/Object)Z
相关文章
相关标签/搜索