Android逆向学习笔记1:Dalvik字节码规范(1)

1.Dalvik虚拟机

        1.1Dalvik虚拟机特点

                体积小;

                专有DEX(Dalvik Executable)可执行文件格式;

                常量池采用32位索引值,对类方法名,字段名,常量的寻址快;

                基于寄存器架构;

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

                1.运行的字节码不同

                         Java通过编译,生成java字节码保存在class文件中;所有Dalvik字节码都由java字节码转化而来,并打包到一个dex可执行文件中。

                2.Dalvik可执行文件的体积更小

                        dx能够重新排列java类文件,去除其中的冗余信息。

                3.虚拟机架构不同

                        jvm是基于栈架构的,dalvik基于寄存器架构

测试代码:

public class Hello {
    public int foo(int a, int b){
        return (a+b)*(a-b);
    }
    public static void main(String[] args) {
        Hello hello = new Hello();
        System.out.println(hello.foo(5, 3));
    }
}

保存为Hello.java,用javac编译得到Hello.class文件。

注:指定JDK版本低于7(对应1.7)才可用dx命令,

javac -source 1.7 -target 1.7 Hello.java

 使用dx将class文件生成dex文件。

注:dx,dexdump均位于android SDK的platform-tools目录下,将此目录添加到环境变量中即可;

如果dx命令失败,可能是前面代码中自动加了包名,将其删去就好,或者直接复制上面代码保存。

dx --dex --output=Hello.dex Hello.class

使用javap反编译Hello.class 

javap -c -classpath .Hello

得到如下代码:

public class Hello {
  public Hello();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int foo(int, int);
    Code:
       0: iload_1
       1: iload_2
       2: iadd
       3: iload_1
       4: iload_2
       5: isub
       6: imul
       7: ireturn
......

 可以看出foo函数占8字节,每条指令一字节且没有参数。对java程序来说,每个线程执行时都有一个PC计数器和java栈。

iload_1:i是指令前缀,表示类型为int;load表示将局部变量存入Java栈;1表示是哪个局部变量。索引值从0开始计数。

isub:表示从栈顶弹出两个int类型的值并求他们的差,并把结果压回栈顶。

用dexdump查看Dalvik字节码

dexdump -d Hello.dex
Virtual methods   -
    #0              : (in LHello;)
      name          : 'foo'
      type          : '(II)I'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 5
      ins           : 3
      outs          : 0
      insns size    : 6 16-bit code units
000198:                                        |[000198] Hello.foo:(II)I
0001a8: 9000 0304                              |0000: add-int v0, v3, v4
0001ac: 9101 0304                              |0002: sub-int v1, v3, v4
0001b0: b210                                   |0004: mul-int/2addr v0, v1
0001b2: 0f00                                   |0005: return v0
      catches       : (none)
      positions     :
        0x0000 line=4
      locals        :
        0x0000 - 0x0006 reg=2 this LHello;

  source_file_idx   : 1 (Hello.java)

Dalvik字节码只用四条指令即可完成操作,

第一条指令是将v3,v4相加,结果存到v0寄存器中,add是加,int表明是整数类型。

mul-int/2addr v0, v1:表示将v0,v1寄存器的值相乘,结果保存到v0寄存器中。

Dalvik虚拟机运行时也为每个线程维护了一个PC计数器和一个调用栈,但是这个调用栈维护了一个寄存器列表。

        1.3虚拟机的执行流程

Android启动流程:

1、启动电源,引导芯片代码执行。加载BootLoader程序到RAM中执行。

2、在系统文件中寻找init.rc文件,并启动init进程。init进程是Android系统中用户空间的第一个进程,进程号为1。

3、init启动Zygote进程。Zygote创建Java虚拟机并注册JNI方法,创建服务端Socket,启动SystemServer进程。

4、SystemServer启动Binder线程池和SystemServiceManager,并启动各种线程服务。

5、被SystemServer启动的AMS(ActivityManagerService)会启动Launcher,Launcher会将已安装应用的图标显示到界面上。

Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]_IngresGe的博客-CSDN博客 ...

 Zygote有三种创建进程的方法:

fork():创建一个Zygote进程(实际上不被调用)

forkAndSpecialize():创建一个非Zygote进程

forkSystemServer():创建一个SystemServer进程

参考书目:《Android软件安全权威指南》《Android进阶解密》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值