zoukankan      html  css  js  c++  java
  • Android Dalvik 虚拟机

    简介

    Android 平台虽然是使用java语言来开发应用程序,但Android程序却不是运行在标准java虚拟机上的。谷歌专门为Android平台设计了一套虚拟机来运行Android程序。它就是Dalvik虚拟机。

    特点

    * 体积小,占用内存空间小。

    * 专有的DEX可执行文件格式,体积更小,执行速度更快。

    * 常量池采用32位索引值,寻址类方法名、字段名、常量更快。

    * 基于寄存器架构,并拥有一套完整的指令系统。

    * 提供了对象生命周期管理、堆栈管理、线程管理、安全和异常管理以及垃圾回收等重要功能。

    * 所有的Android程序都运行在Android系统进程里,每个进程对应着一个Dalvik虚拟机实例。

    Dalvik虚拟机与Java虚拟机的区别

    1、Java虚拟机运行的是java字节码,Dalvik虚拟机运行的是Dalvik字节码。

    2、Dalvik 可执行文件体积更小。

    3、Java虚拟机与Dalvik虚拟机架构不同。


    Dalvik 汇编语言

    1、Dalvik指令

    指令大多由三个字符组成,前两个是数字,最后一个是字母。

    第一个数字是表示指令有多少个16位的字组成。

    第二个数字是表示指令最多使用寄存器的个数。特殊标记‘r’标识使用一定范围内的寄存器。

    第三个字母为类型吗,表示指令用到的额外的数据的类型。


    例如:22x   

    第一个2表示 指令有两个16位字组成

    第二个2表示 指令使用到2个寄存器

    第三个x表示没有使用到额外的数据


    2、DEX文件反汇编工具

    目前DEX可执行文件主流的反汇编工具有BakSmali与Dedexer。

    指令如:

    java -jar baksmali.jar -o baksmaliout hello.dex
    java -jar ddx.jar -d ddxout hello.dex


    3、Dalvik 寄存器

    Dalvik虚拟机是作用于特定架构的CPU上运行的,在设计之初采用了ARM架构,ARM架构的CPU本身继承了多个寄存器,Dalvik将部分寄存器映射到了ARM寄存器上,还有一个部分则通过调用栈进行模拟。.

    Dalvik虚拟机又是如何虚拟地使用寄存器的呢?Dalvik虚拟机为每个进程维护一个调用栈,这个调用栈其中一个作用就是用来‘虚拟’寄存器。


    4、两种不同的寄存器表示方法

    v 命名法采用以小写字母 ‘v’开头的方式表示函数中用到的局部变量与参数,所有的寄存器命名从v0开始,依次递增。

    p 命名法对函数的局部变量寄存器命名没有影响,它的命名规则:函数中引入的参数命名从p0开始,依次递增。

    Dalvik字节码的类型、方法与字段

    1、类型

    Dalvik字节码只有两种类型,基本类型与引用类型。

    2、方法

    Dalvik使用方法名、类型参数与返回值来详情描述一个方法。

    方法格式如下: Lpackage/name/ObjectName;->MethodName(III)Z

    3、字段

    Dalvik虚拟机定位字段与字节码静态分析时会用到它。

    格式如下:Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

    Dalvik指令集

    1、空操作指令的助记符为nop。它的值为00,通常nop指令被用来作对齐代码只用。

    2、数据操作指令为move。move 指令根据字节码的大小与类型不同,后面会跟上不同的后缀。

    3、返回指令指的是函数结尾时运行的最后一条指令。return-void、return vAA、return-wide vAA、return-object vAA

    4、数据定义指令用来定义程序中用到的常量、字符串、类等数据。它的基础字节码为const。如:const/4 vA,#+B

    5、锁指令多用在多线程程序中对同一对象的操作。如:

    monitor-enter vAA 锁住

    monitor-exit vAA   释放

    6、实例操作指令包括实例的类型转换、检查以及新建等。

    7、数组操作指令包括获取数组长度、新建数组、数组赋值、数组元素取值与赋值等操作。

    8、异常指令集中有一条指令用来抛出异常。如:throw vAA

    9、跳转指令用于从当前地址跳转到指定的偏移处。如:goto、switch、if

    10、比较指令用于对两个寄存器的值进行比较。如:cmpkind vAA,vBB

    11、字段操作指令用来对对象实例的字段进行读写操作。如:iinstanceop vA,vB,field@CCCC 与sstaticop vAA,field@BBBB

    12、方法调用指令负责调用类实例的方法。它的基础指令为invoke。如:invoke-kind/range {vCCCC..vNNNNN}

    13、数据转换指令用于将一种类型的数值转换成另一种类型。如:unop vA,vB

    14、数据运算指令包括算术运算指令与逻辑运算指令。如:binop vAA,vBB,vCC 、add-type、sub-type……。


    Dalvik指令练习

    写一个Dalvik版的Hello World。

    1、编写smali文件

    .class public LHelloWorld;
    .super Ljava/lang/Object;
    .method public static main([Ljava/lang/String;)V
        .registers 4
    	.parameter
        .prologue
    	#空指令
        nop
        nop
        nop
        nop
    	#数据定义指令
    	const/16 v0, 0x8
    	const/4 v1, 0x5
    	const/4 v2, 0x3
    	#数据操作指令
    	move v1, v2
    	#数组操作指令
    	new-array v0, v0, [I
    	array-length v1, v0
    	#实例操作指令
    	new-instance v1, Ljava/lang/StringBuilder;
    	#方法调用指令
    	invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
    	#跳转指令
    	if-nez v0, :cond_0
    	goto :goto_0
    	:cond_0
    	#数据转换指令
    	int-to-float v2, v2
    	#数据运算指令
    	add-float v2, v2, v2
    	#比较指令
    	cmpl-float v0, v2, v2
    	#字段操作指令
    	sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
    	const-string v1, "Hello World" #构造字符串
    	#方法调用指令
    	invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    	#返回指令
    	:goto_0
        return-void
    .end method


    2、编译smali文件

    java -jar smali.jar -o classes.dex HelloWorld.smali


    3、使用虚拟机测试


    小结

    了解了Android的运行环境Dalvik虚拟机,为以后的Android的逆向分析打下了一个坚实的基础。

    下载

    实例与工具下载

  • 相关阅读:
    c#数据结构与算法
    学习资源---.NET
    怎样完全删除sqlserver
    树,森林 二叉树之间转化 原理
    ref 和out 区别
    GridView批量删除记录、全选及弹出确认对话框
    .NET基础 小记--------2013.8.10
    Xml 读写
    同步 异步 区别
    委托学习
  • 原文地址:https://www.cnblogs.com/james1207/p/3295169.html
Copyright © 2011-2022 走看看