Android安全学习笔记2-Dalvik虚拟机
2018-02-22 00:47
309 查看
Dalvik虚拟机学习
一、Dalvik虚拟机特点:
1)体积小,占用内存小2)使用DEX可执行文件,执行速度快
3)常量池32位,寻址类方法名、字段、常量更快
4)基于寄存器,并拥有完整的指令系统
5)提供对象生命周期、堆栈、线程、安全、异常、垃圾回收等重要功能
6)每个Android程序对应一个Dalvik虚拟机实例
与JAVA虚拟机的区别
1)Dalvik字节码与JAVA字节码的不同
2)dx工具对class文件中方法签名、常量池等进行压缩精简
实验
构造这样的代码:
public class Java_Dalvik_Byte_Code_Compare{ public int foo(int a, int b){ return (a+b)*(a-b); } public static void main(String[] args) { Java_Dalvik_Byte_Code_Compare first = new Java_Dalvik_Byte_Code_Compare(); System.out.println(first.foo(5, 3)); } }
使用
javac xxx.java编译生成class文件
使用
dx --dex --output=xxx.dex xxx.class生成dex文件
使用
javap -c xxx.class反编译Java字节码
Compiled from "Java_Dalvik_Byte_Code_Compare.java" public class Java_Dalvik_Byte_Code_Compare { public Java_Dalvik_Byte_Code_Compare(); 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 public static void main(java.lang.String[]); Code: 0: new #2 // class Java_Dalvik_Byte_Code_Compare 3: dup 4: invokespecial #3 // Method "<init>":()V 7: astore_1 8: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 11: aload_1 12: iconst_5 13: iconst_3 14: invokevirtual #5 // Method foo:(II)I 17: invokevirtual #6 // Method java/io/PrintStream.println:(I)V 20: return }
使用
dexdump.exe -d xxx.dex反编译dex文件
Processing '.\Java_Dalvik_Byte_Code_Compare.dex'... Opened '.\Java_Dalvik_Byte_Code_Compare.dex', DEX version '035' Class #0 - Class descriptor : 'LJava_Dalvik_Byte_Code_Compare;' Access flags : 0x0001 (PUBLIC) Superclass : 'Ljava/lang/Object;' Interfaces - Static fields - Instance fields - Direct methods - #0 : (in LJava_Dalvik_Byte_Code_Compare;) name : '<init>' type : '()V' access : 0x10001 (PUBLIC CONSTRUCTOR) code - registers : 1 ins : 1 outs : 1 insns size : 4 16-bit code units 00014c: |[00014c] Java_Dalvik_Byte_Code_Compare.<init>:()V 00015c: 7010 0400 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004 000162: 0e00 |0003: return-void catches : (none) positions : 0x0000 line=1 locals : 0x0000 - 0x0004 reg=0 this LJava_Dalvik_Byte_Code_Compare; #1 : (in LJava_Dalvik_Byte_Code_Compare;) name : 'main' type : '([Ljava/lang/String;)V' access : 0x0009 (PUBLIC STATIC) code - registers : 5 ins : 1 outs : 3 insns size : 17 16-bit code units 000164: |[000164] Java_Dalvik_Byte_Code_Compare.main:([Ljava/lang/String;)V 000174: 2200 0100 |0000: new-instance v0, LJava_Dalvik_Byte_Code_Compare; // type@0001 000178: 7010 0000 0000 |0002: invoke-direct {v0}, LJava_Dalvik_Byte_Code_Compare;.<init>:()V // method@0000 00017e: 6201 0000 |0005: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000 000182: 1252 |0007: const/4 v2, #int 5 // #5 000184: 1233 |0008: const/4 v3, #int 3 // #3 000186: 6e30 0100 2003 |0009: invoke-virtual {v0, v2, v3}, LJava_Dalvik_Byte_Code_Compare;.foo:(II)I // method@0001 00018c: 0a00 |000c: move-result v0 00018e: 6e20 0300 0100 |000d: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(I)V // method@0003 000194: 0e00 |0010: return-void catches : (none) positions : 0x0000 line=6 0x0005 line=7 0x0010 line=8 locals : Virtual methods - #0 : (in LJava_Dalvik_Byte_Code_Compare;) name : 'foo' type : '(II)I' access : 0x0001 (PUBLIC) code - registers : 5 ins : 3 outs : 0 insns size : 6 16-bit code units 000198: |[000198] Java_Dalvik_Byte_Code_Compare.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=3 locals : 0x0000 - 0x0006 reg=2 this LJava_Dalvik_Byte_Code_Compare; source_file_idx : 3 (Java_Dalvik_Byte_Code_Compare.java)
对比两边foo()函数的代码,可以很明显看出基于寄存器的Dalvik虚拟机执行步骤相较于基于栈的JVM精简了很多。
另外注意,Dalvik反编译的汇编中参数顺序与入栈顺序一致。
Dalvik虚拟机执行程序流程
Zygote
系统启动
init进程运行
读取inic.rc并启动重要孵化器进程Zygote
Zygote初始化Dalvik虚拟机
启动system_server并进入Zygote模式,通过socket等待命令
当执行应用程序时,system_server通过socket通知Zygote,Zygote立刻fork自身创建一个Dalvik虚拟机实例来执行目标程序的入口函数。
Dalvik
Dalvik虚拟机运行loadClassFromDec()完成类装载,类数据结构为ClassObject
使用gDvm.loadedClasses全局哈希表来存储/查询装载进来的类
字节码验证器使用dvmVerifyCodeFlow()函数对载入的代码进行校验
调用FindClass()函数查找并装载main方法类
调用dvmInterpret()初始化解释器并执行字节码
相关文章推荐
- android开发学习笔记(5)DalVik虚拟机简介
- Android(java)学习笔记156:Java虚拟机和Dalvik虚拟机的区别
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- android 学习--Dalvik虚拟机与Java虚拟机
- android安全学习笔记(三)
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Android笔记--对缓存、三级缓存和Android的Dalvik虚拟机和java编译过程的理解
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Android 虚拟机学习总结Dalvik虚拟机介绍
- Android 虚拟机学习总结Dalvik虚拟机介绍
- Android逆向学习笔记---逆向腾讯2016游戏安全挑战赛Tencent2016A.apk
- Android笔记四 虚拟机Dalvik、Android各种java包功能、Android相关文件类型、应用程序结构分析、ADB
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Android应用安全学习笔记前言
- android安全学习笔记(一)
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】