zoukankan      html  css  js  c++  java
  • Android逆向基础----Android Dalvik虚拟机

    Android Dalvik虚拟机的特点:

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

    l  专有DEX可执行文件。

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

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

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

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

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

    Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。Dalvik字节码由Java字节码转换而来,并打包成一个DEX可执行文件,通过虚拟机解释执行。

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

    Android SDK中的dx工具在转换字节码时会消除类文件的冗余信息,避免虚拟机在初始化时出现重复的文件加载与解析过程。另外,dx工具会将所有的Java类文件中的常量池进行分解,消除其中的冗余信息,组合成一个新的共享常量池。这使得文件体积和解析文件的效率都得到了提高。

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

    Java虚拟机的架构及参数传递

    Java虚拟机基于栈架构。需要频繁的从栈上读写数据,在这个过程中需要更多的指令分派与内存访问次数,耗费CPU时间,消耗手机资源。

    Java虚拟机的指令集被称为零地址,是指指令的源参数与目标参数都是隐含的,它通过Java虚拟机中提高的一种数据结构“求值栈”来传递的。

    对于Java程序来说,每个线程在执行时都有一个PC计数器与一个Java栈。PC计数器以字节为单位记录当前运行位置距离方法开头的偏移量,与ARM架构和x86架构类似,通过栈帧对栈中的数据进行操作。

    Java栈用于记录Java方法调用的“活动记录”,Java栈以帧为单位保存线程的运行状态,每调用一个方法就会分配一个新的栈帧压入Java栈上,每从一个方法返回则弹出并撤销响应的栈帧。

    每个栈帧包括局部变量区、求值栈(JVM规范中将其称为“操作数栈”)和其他一些信息。局部变量区用于存储方法的参数与局部变量,其中参数按源码中从左到右顺序保存在局部变量区开头的几个slot中。

    求栈值用于保存求值的中间结果和调用别的方法的参数等,JVM运行时它的状态如下图

    每条指令占用一个字节空间,foo()函数Java字节码左边的偏移量就是程序执行到每一行代码时PC的值,并且Java虚拟机最多只支撑0xff条指令。

    仔细分析第一条指令iload_1的结构

    iload_1可分成两部分,第一部分为下划线左边的iload,属于JVM(Java虚拟机)指令集中load系列中的一条,i是指令前缀,表示操作类型为int类型,load表示将局部变量存入Java栈。第二部分为下划线右边的数字,表示要操作具体哪个变量,索引值从0开始计数,iload_1表示将第二个int类型的局部变量进栈参数。

    Dalvik虚拟机的架构及参数传递

    Dalvik虚拟机基于寄存器架构,数据访问通过寄存器间直接传递。比起Java虚拟机字节码要简洁很多。

    以第一条指令为例简单分析一下。指令add-int将v3与v4寄存器的值相加,然后保存到v0寄存器,v3和v4代表调用函数的所使用的两个参数。这里用到的Dalvik字节码参数表示法是v命名法,另一种是p命名法。

    Dalvik虚拟机运行时同样为每个线程维护一个PC计数器与调用栈,与Java虚拟机不同的是,这个调用栈维护一份寄存器列表,寄存器的数量在方法结构体的registers字段中给出,Dalvik虚拟机会根据这个值来创建一份虚拟的寄存器列表。

    Dalvik虚拟机由于生成的代码指令减少了,程序执行速度会更快一些。

     

    Dalvik是如何执行程序的

    Android系统的架构采用分层思想,这样的好处是拥有减少各层之间的依赖性、便于独立分发、容易收敛问题和错误等优点。

    Android系统由linux内核、函数库、Android运行时、应用程序框架以及应用程序组成。

    Android系统加载完内核后,第一个执行的是init进程,init进程对设备进行初始化,读取init.rc文件并启动系统中重要外部程序Zygote。

    Zygote进程是Android所有进程的孵化器,启动后首先初始化Dalvik虚拟机,然后启动system_server并进入Zygote模式,通过socket等候命令。

    当执行一个Android应用程序时,system_server进程通过socket方式发送命令给Zygote,Zygote收到命令后通过fork自身创建一个Dalvik虚拟机的实例来执行应用程序的入口函数,这就是程序启动的流程。

     

    Zygote提供三种

    fork(),创建一个Zygote进程

    forkAndSpecialize(),创建一个非Zygote进程(不能再fork)

    forkSystemService(),创建一个系统服务进程(子进程跟随父进程终止)

    fork之后,执行的工作交给Dalvik虚拟机。虚拟机通过loadClassFromDex()函数完成类的装载工作,每个类被成功解析后会拥有一个ClassObject类型的数据结构存储在运行时环境中,虚拟机使用gDvm.loadedClasses全局哈希表来存储与查询所有装载进来的类,随后,字节码验证器使用dvmVerifyCodeFlow()函数对装入的代码进行校验,接着虚拟机调用FindClass()函数查找并装载main方法类,随后调用dvmInterpret()函数初始化解释器并执行字节码流。

    Dalvik虚拟机执行程序流程

    虚拟机线程->装载程序类->验证字节码->查找主类->执行字节码流->结束

    关于Dalvik虚拟机JIT

    JIT是即时编译(动态编译),是通过在运行时将字节码翻译为机器码的技术,使得程序的执行速度更快。

    主流的JIT包含两种字节码编译方式:

    method方式:以函数或方法为单位进行编译。

    trace方式:以trace为单位进行编译。

    执行代码分为冷路径(在实践运行过程中很少被执行的)和热路径(执行比较频繁的路径),method会编译整个方法,trace编译的是获取的热路径的代码,节省内存。

     编辑参考:Android软件安全与逆向分析

  • 相关阅读:
    1024X768大图 (Wallpaper)
    (Mike Lynch)Application of linear weight neural networks to recognition of hand print characters
    瞬间模糊搜索1000万基本句型的语言算法
    单核与双核的竞争 INTEL P4 670对抗820
    FlashFTP工具的自动缓存服务器目录的功能
    LDAP over SSL (LDAPS) Certificate
    Restart the domain controller in Directory Services Restore Mode Remotely
    How do I install Active Directory on my Windows Server 2003 server?
    指针与指针变量(转)
    How to enable LDAP over SSL with a thirdparty certification authority
  • 原文地址:https://www.cnblogs.com/zhaijiahui/p/8810887.html
Copyright © 2011-2022 走看看