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軟件安全與逆向分析
轉載于:https://www.cnblogs.com/zhaijiahui/p/8810887.html
總結
以上是生活随笔為你收集整理的Android逆向基础----Android Dalvik虚拟机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF richTextBox 滚动到某
- 下一篇: python如何打开一个大文件?