1. 程式人生 > >安卓移動逆向(三)-Android Dalvik虛擬機器

安卓移動逆向(三)-Android Dalvik虛擬機器

大家都知道Java程式是執行在Java虛擬機器上,Android程式呢?
雖然Android平臺使用Java語言來開發應用程式,但是Android程式卻不是執行在標準的Java虛擬機器上的. Google為Android平臺專門設計了一套虛擬機器來執行Android程式–Dalvik Virtual Machine,也就是Dalvik虛擬機器了

本篇作用:

  • 掃盲Dalvik虛擬機器
  • 瞭解Smail的語法,能讀懂Smail檔案

Dalvik概述

Dalvik的特點(相對於JVM)

  • 體積小,佔用記憶體小;
  • 專有的DEX可執行檔案格式,體積更小,執行速度更快;
  • 常量池採用32位索引值,定址類方法名,欄位名,常亮更快;
  • 基於暫存器架構,並擁有一套完成的指令系統
  • 提供了物件生命週期管理,堆疊管理,執行緒管理,安全和異常管理以及垃圾回收等重要功能;
  • 所有的Android程式都執行在Android系統程序裡,每個程序對應著一個Dalvik虛擬機器例項;

Dalvik虛擬機器與Java虛擬機器的區別

  1. Java虛擬機器執行的Java位元組碼,Dalvik虛擬機器執行的是Dalvik位元組碼
  2. Dalvik可執行檔案的體積更小
    稍作解析:
    SDK中有一個叫做dx的工具負責將Java位元組碼轉換為Dalvik位元組碼.dx工具對Java類檔案重新排列,消除在類檔案中出現的所有冗餘資訊,避免虛擬機器在初始化時出現重複的檔案載入與解析過程.

    舉個栗子:
    在Java中有大量的字串常量在多個類檔案中被重複使用,這些榮譽資訊會直接增加檔案的體積,同事也會嚴重影響虛擬機器解析檔案的效率.dx工具針對這個問題做了專門的處理,它將所有Java類檔案中的常量池進行分解,消除其中的冗餘資訊,重新組合成一個常量池,所有的類檔案共享同一個常量池.dx工具轉換過程如圖所示,由於dx工具對常量池的壓縮,是的相同的字串,常量在DEX檔案中只出現一次,從而減小了檔案的體積.

dx工具轉換過程
3. Java虛擬機器與Dalvik虛擬機器架構不同

簡單說一下:Java虛擬機器基於棧架構,Dalvik基於暫存器架構;

Dalvik指令格式

一般Dalvik彙編程式碼由一系列的Dalvik指令組成,指令語法由指令的位描述與指令格式標識來決定.位描述約定如下

  • 每16位的字採用空格分割開來;
  • 每個字母表示四位,每個字母按順序從高位元組開始,排列到低位元組.每四位之間可能用豎線”|”來表示不同的內容;
  • 順序採用A-Z的翻個大寫字母作為一個4位的操作碼,op表示一個8位的操作碼;
  • “Ø”來表示這個欄位的所有位為0值;

栗子
“A|B|op BBBB F|E|D|C”
指令中間有兩個空格,每個分開的部分是16位,共有3個16位組成這條指令;
第一個16位是”A|B|op” 高8位由A和B組成,低位元組由操作碼op組成;
第二個16位由BBBB組成,他表示一個16位的偏移值;
第三個16位分別由F,E,D,C共四個位元組組成,在這裡他們表示暫存器的引數.

單獨使用位標識還無法確定一條指令的意思,必須通過指令格式標識來指定指令的格式編碼,約定如下

  • 指令格式標識大多由三個字元組成,前兩個是數字,最後一個是字母;
  • 第一個數字式標識指令由多少個16位的字組成;
  • 第二個數字標識指令最多使用暫存器的個數,特殊標記”r”標識使用一定範圍內的暫存器;
  • 第三個字母為型別碼,標識指令用到的額外資料的型別,見下圖:
  • 還有一種特殊的情況 是末尾可能還會多出另一個字母,如果是”s”表示指令採用靜態連結,如果是”i”表示指令應該被內聯處理.

    指令格式標識的型別碼

栗子

“22x” 有三條資訊可以讀出

  1. 指令由2個16位字組成
  2. 指令使用2個暫存器
  3. 沒有使用到額外的資料

另外,Dalvik指令對語法做了一些說明,約定如下

  • 每條指令從操作碼開始,後面緊跟引數,引數個數不定,每個引數之間採用逗號分開;
  • 每條指令的引數從指令的第一部分開始,op位於低8位,高8位可以是一個8位的引數也可以是兩個4位的引數,還可以為空.如果指令超過16位,則後面的部分依次作為引數;
  • 如果引數使用”vX”的方式標識,表明它是一個暫存器,如v0,v1等;
  • 如果引數採用”#+X”的方式,表明它是一個常量數字;
  • 如果引數採用”+X”的方式,表明它是一個相對指令的地址偏移;
  • 如果引數採用”[email protected]”的方式,表明它是一個常量池索引值.其中kind表示常量池型別,例如[email protected],表示的就是字串常量池索引BBBB;

栗子
“op vAA [email protected]
高8位為空,用到1個暫存器引數vAA,還用到一個字串常量池索引BBBB;

Dalvik暫存器

掃盲結束了,開始重點了

Dalvik位元組碼的型別,方法,與欄位表示方法

  1. 型別
    Dalvik位元組碼只有兩種型別,基本與引用,話不多說,看圖;
    型別
    每個Dalvik暫存器都是32位大小,對於小魚或者等於32位長度的型別來說,一個暫存器就可以存放該型別的值,而像J(long),D(double)等64位的型別,它們的值是使用相鄰量個暫存器來儲存的,v0和v1或者vN與vN+1等;
    L就好理解了,表示任何一個Java類,在Dalvik彙編程式碼中,它們以” Lpackage/name/ObjectName; “表示,注意最後一個分號,比如” Ljava/lang/String;”相當於String;
    [型別就是所有的陣列,[後面緊跟基本型別的描述符,如[I表示一個整型一維陣列,->int[],[[I表示int[][]<—> [Ljava/lang/String; 表示物件陣列 String [];
  2. 方法
    Dalvik使用方法名,型別引數與返回值來描述一個方法;
    格式如下:
    Lpackage/name/ObjectName;->MethodName(III)Z
    說明:
    Lpackage/name/ObjectName;是一個型別;
    MethodName方法名
    (III)引數,三個int引數
    Z返回值void
    栗子
    method(I[[IILjava/lang/String;[Ljava/lang/String;)Ljava/lang/String;
    咳咳,按照上面的知識,將其轉換為Java形式的程式碼為:
    String method(int ,int[][],String,String[])
  3. 欄位
    欄位和方法很相似,就是沒有引數和返回值,取而代之的是欄位的型別,格式如下
    Lpackage/name/ObjectName;->FieldName:TYPE
    說明:
    Lpackage/name/ObjectName;是一個型別;
    FieldName欄位名
    TYPE欄位型別
    FieldName與TYPE用冒號隔開
    栗子
    name:Ljava/lang/String;
    轉換:
    String name;
    Dalvik程式碼中的欄位程式碼以.field指令開頭,根據欄位型別不同,在欄位指令的開始,可能會用到井號”#”加以註釋;

Dalvik指令集

指令特點

Dalvik指令在呼叫格式上模仿了C語言的呼叫約定.Dalvik指令語法與助詞符有如下特點:

  • 引數採用從目標(destination)到源(source)的方式;
  • 根據位元組碼的佈局與選項的不同,一些位元組碼添加了位元組碼字尾消除歧義,這些字尾通過在位元組碼主名稱後新增斜槓”/”來分隔開;
  • 在指令集的描述中,寬度值中的每個字母表示寬度為4位;
  • 根據位元組碼的大小與型別的不同,一些位元組碼添加了名稱字尾以消除歧義:
    • 32位常規型別的位元組碼,未新增任何字尾;
    • 64位常規型別的位元組碼以-wide字尾;
    • 特殊型別的位元組碼根據具體型別新增字尾,他們可以是-boolean,-byte,-char,-short,-int,-long,-float,-double,-object,-string,-class,-void之一;

栗子
“move-wide/from16 vAA,vBBBB”

move為基礎位元組碼.標識這是基本操作;
wide為名稱字尾.標識指令操作的資料寬度(64位);
from16位位元組碼字尾.標識源為一個16位的暫存器引用變數;
vAA為目的暫存器,它始終在源的前面 取值範圍為v0-v2^8-1(255);
vBBBB為源暫存器,取值範圍為v0-v2^16-1(65535)

空操作指令

空操作指令的助記符為nop,他的值是00,通常nop指令被用過對齊程式碼用途,沒啥大用;

資料操作指令

資料操作指令為move.move指令的原型為move destination,source或者move destination,move指令根據位元組碼的大小與型別不同,後面會跟上不同的字尾.
栗子(表示太多直接上圖,都差不多)

資料操作指令

返回指令

返回指令指的是函式結尾時執行的最後一條指令.他的基礎位元組碼位return,共有以下四條返回指令
栗子

  1. “return-void” 返回一個void
  2. “return vAA” 返回一個32位非物件型別的值,返回值暫存器位8位的暫存器vAA;
  3. “return-wide vAA” 返回一個64位非物件型別的值,返回值暫存器位8位的暫存器vAA;
  4. “return-object vAA” 返回一個物件型別的值,返回值暫存器位8位的暫存器vAA;

資料定義指令

資料定義指令用來定義程式中用到的變數,字串,類等資料,他的基礎位元組碼為const
栗子(表示太多直接上圖-_-)
這裡寫圖片描述
這裡寫圖片描述

鎖指令

鎖指令多用在多執行緒程式中對同一物件的操作,Dalvik指令集中有兩條鎖指令.

  1. “monitor-enter vAA” 為指定的物件獲取鎖
  2. “monitor-exit vAA”為指定的物件釋放鎖

例項操作指令

與例項相關的操作包括例項的型別傳換,檢查及新建等;

(BBBB)vAA;
  • “instance-of vA,vB,[email protected]” 判斷vB中的物件引用是否能轉成CCCC型別,能vA=1,不能vA=0;
if(vB.instanceof(type@CCCC)){
    vA =1;
}else{
    vA = 0;
}
  • “new-instance vAA,[email protected]” 新建一個BBBB的物件vAA,BBBB不能為陣列
BBBB vAA = new BBBB();

陣列操作指令

陣列操作包括獲取陣列長度(指的是陣列的條目個數),新建陣列,陣列賦值,陣列元素取值與賦值等操作;

  • “array-length vA,vB”
vA = vB.length; //  將vB的長度賦值給vA
vA = CCCC[vB]; //   構建一個vB大的CCCC型別的陣列賦值給vA
  • 其餘的附圖
    這裡寫圖片描述

異常指令

Dalvik 指令集中有一條指令用於丟擲異常

  • “throw vAA” 丟擲vAA暫存器中指定型別的異常

跳轉指令

Dalvik指令集中有三種跳轉指令:無條件跳轉(goto),分支跳轉(switch),條件跳轉(if)

  • “goto +AA” 無條件跳轉到指定偏移處,偏移量AA不能為0;
  • “goto/16+AAAA” 無條件跳轉到指定偏移處,偏移量AAAA不能為0;
  • “goto/32+AAAAAAAA” 無條件跳轉到指定偏移處;
  • “packed-switch vAA,+BBBBBBBB” 分支跳轉指令. vAA暫存器為switch分支中需要判斷的值即(switch(vAA)),BBBBBBBB指向一個packed-switch-payload格式的偏移表,表中的值是規律遞增的.(先這麼記住就好,感興趣可以找百度..)
  • “sparse-switch vAA,+BBBBBBBB”分支跳轉指令,vAA暫存器為switch分支中需要判斷的值即(switch(vAA)),BBBBBBBB指向一個sparse-switch-payload格式的偏移表,表中的值是無規律的偏移量.
  • “if-test vA,vB,+CCCC” 條件跳轉指令,比較vA與vB的值,如果比較結果滿足就跳轉到CCCC指定的偏移處,偏移量CCCC不能為0,if-test型別的指令有以下幾條:
    • “if-eq vA, vB, :cond_xx” 如果vA等於vB則跳轉到:cond_xx
    • “if-ne vA, vB, :cond_xx” 如果vA不等於vB則跳轉到:cond_xx
    • “if-lt vA, vB, :cond_xx” 如果vA小於vB則跳轉到:cond_xx
    • “if-ge vA, vB, :cond_xx” 如果vA大於等於vB則跳轉到:cond_xx
    • “if-gt vA, vB, :cond_xx” 如果vA大於vB則跳轉到:cond_xx
    • “if-le vA, vB, :cond_xx” 如果vA小於等於vB則跳轉到:cond_xx
  • “if-testz vAA,+BBBB”條件跳轉指令,那vAA與0作比較,滿足結果或者不滿足結果就跳轉到BBBB的指定偏移處BBBB不能為0, if-testz型別的指令有以下幾條:
    • “if-eqz vA, :cond_xx” 如果vA等於0則跳轉到:cond_xx
    • “if-nez vA, :cond_xx” 如果vA不等於0則跳轉到:cond_xx
    • “if-ltz vA, :cond_xx” 如果vA小於0則跳轉到:cond_xx
    • “if-gez vA, :cond_xx” 如果vA大於等於0則跳轉到:cond_xx
    • “if-gtz vA, :cond_xx” 如果vA大於0則跳轉到:cond_xx
    • “if-lez vA, :cond_xx” 如果vA小於等於0則跳轉到:cond_xx

比較指令

比較指令用於對兩個暫存器的值(浮點型或者長整型)進行比較格式為:
“cmpkind vAA,vBB,vCC”

Dalvik指令集中共有5條比較指令:

  • “cmpl-float” 比較兩個float值;
if(vBB == vCC){
    vAA =0;
}else if(vBB>vCC){
    vAA = -1;
}else if(vBB<vCC>){
    vAA = 1;
}
  • “cmpg-float” 比較兩個float的值
if(vBB == vCC){
    vAA =0;
}else if(vBB<vCC){
    vAA = -1;
}else if(vBB>vCC>){
    vAA = 1;
}

當cmpg或者cmp時,B > C時A = 1,反之-1;當cmpl時,B > C時A = -1反之1;

  • “cmpg-double” 比較兩個double的值
  • “cmpl-double” 比較兩個double的值
  • “cmp-long” 比較兩個long的值

欄位操作指令

欄位操作指令用來對物件例項的欄位進行讀寫操作.
欄位的型別可以是Java中有效的資料型別,對普通欄位與靜態欄位操作有兩種指令集,分別是”iinstanceop vA,vB,[email protected]”與”sstaticop vAA,[email protected]”.
在Android 4.0系統中,有”iinstanceop /jumbovAAAA,vBBBB,[email protected]”與”sstaticop/jumbo vAAAA,[email protected]”.和上面的兩種作用相同,只是加了jmpbo字尾,暫存器與指令索引取值範圍更大(後面的只會說有/jumbo指令字尾的指令集,作用就不指明瞭)
普通欄位指令的指令字首為i,如.對普通欄位讀操作使用iget指令,寫操作使用iput指令;靜態欄位的指令字首為s,如.對靜態欄位的讀操作為sget,寫操作為sput;
根據訪問的欄位型別不同,欄位操作指令後面會緊跟欄位型別的字尾,如iget-byte指令表示讀取例項欄位的值型別為byte;

方法呼叫指令
方法呼叫指令負責呼叫類例項的方法,它的基礎指令為invoke,方法呼叫指令有”invoke-kind{vC,vD,vE,vF,vG},[email protected]”與”invoke-kind/range{vCCCC…VNNNN},[email protected]”兩類,這兩類指令作用沒啥不同,後者在設定引數暫存器時使用了range來指定暫存器的範圍,根據方法型別的不同,共有如下5條方法呼叫指令:

  1. “invoke-virtual” 呼叫例項的虛方法
  2. “invoke-super” 呼叫例項的父類方法
  3. “invoke-direct” 呼叫例項的直接方法
  4. “invoke-static” 呼叫例項的靜態方法
  5. “invoke-interface” 呼叫例項的介面方法
    Android 4.0有jumbo的指令集;

方法呼叫指令的返回值必須使用move-result*指令來獲取:
invoke-static{},Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
move-result-object v0;

資料轉換指令
資料轉換指令用於將一種型別的數值轉換為另一種型別,他的格式為”unop vA,vB” 把vB中的資料做一定運算(轉換)放在vA中:(比較簡單,直接上圖)

這裡寫圖片描述

資料運算指令

資料運算指令包括算數運算指令與邏輯運算指令:

  • 算數運算指令:加,減,乘,除,模,移位等
  • 邏輯運算指令:間與,或,非,抑或等;
    上個圖吧
    這裡寫圖片描述
    其中基礎位元組碼後面的-type可以是-int,-long,-float,-double,後面3類指令也差不多,就不列了,觸類旁通;

== == == == == == == == == == == == == == == == == == == == == ==

相關推薦

移動逆向()-Android Dalvik虛擬機器

大家都知道Java程式是執行在Java虛擬機器上,Android程式呢? 雖然Android平臺使用Java語言來開發應用程式,但是Android程式卻不是執行在標準的Java虛擬機器上的. Google為Android平臺專門設計了一套虛擬機器來執行Andr

【轉】進入Android Dalvik虛擬機器Dalvik指令集

Dalvik指定在呼叫格式上模仿了C語言的呼叫約定。Dalvik指令的語法與助詞符有如下特點: 引數採用從目標(destination)到源(source)的方式。 根據位元組碼的大小與型別不同,一些位元組碼添加了名稱字尾以消除岐義。

開發問題一:在虛擬機器上執行APP不能執行,即閃退現象

在執行程式時,出現了虛擬機器上開啟自己寫的APP,提示不能執行,也就是閃退的現象。找了好多論壇,基本上是模擬器與API版本不同導致的,我的後來換了一個AVD裝置,莫名其妙的就自己好了 現將解決方法整理如下: 1、project->clean(測試無用) 2、在Mai

模擬器Genymotion 不能啟動虛擬機器的解決方案

首先放一張圖說明本次待解決的核心問題: 1.問題分析        由於Eclipse自帶的模擬器環境啟動和除錯都太過緩慢和卡頓,而諸如夜神、藍疊、逍遙等模擬器又只能實現簡單的apk包安裝,所以選

Android Dalvik虛擬機器記憶體分配問題

       之前遇到一個android上圖片載入不出來的問題,在三星的note3上極容易出現,而在nexus 4上則很難出現。後來通過DDMS觀察發現,是某一個模組一直記憶體洩漏使得記憶體接近上限,導致一些大圖(需要的記憶體比較大)申請記憶體失敗,一直載入不出來。為什麼會

Dalvik虛擬機器學習(1)----Dalvik虛擬機器執行原理

安卓Dalvik虛擬機器相關知識點總結 0x01 Java虛擬機器與Dalvik虛擬機器的區別 Java虛擬機器執行的是Java位元組碼(儲存在class檔案中),Dalvik執行的是Dalvik位元組碼(由Java位元組碼轉化而來,打包到DEX檔案中

Tensorflow lite for 移動開發()——移動端測試自己的模型

Tensorflow-lite官方給的應用是一個攝像頭demo,主要由ImageClassifier類和Camera2BasicFragment類構成,ImageClassifier類為一個抽象類,由浮點類和數字量化類兩類繼承,主要實現讀取,模型和預測的功能。C

Android Dalvik虛擬機和ART虛擬機對比

x文件 開始 過程 優秀 clas 編譯 apk 但是 好的 1.概述  Android4.4以上開始使用ART虛擬機,在此之前我們一直使用的Dalvik虛擬機,那麽為什麽Google突然換了Android運行的虛擬機呢?答案只有一個:ART虛擬機更優秀。 2.Dalvik

移動端軟鍵盤彈出問題解決方案

log logs 情況 sel clas scrollto refs ext 題解 移動端開發難免拿到輸入框居中或者位於底部的情況,ios 端,軟鍵盤能夠按正常預期向上滑動(這裏有個問題,當 input 聚焦時,彈出軟鍵盤,input 上滑,此時屏幕是具有滾動效果的,還沒找

logcat設置 Android logcat Settings

設置 mail auth set src log img 安卓 author 安卓 logcat設置 Android logcat Settings 作者:韓夢飛沙 Author:han_meng_fei_sha 郵箱:[email protected]/

第一課:android studio 的環境搭建與真機運行以及遇到的問題

自己的 安卓 structure 最好 not found 創建過程 cor 虛擬 col AS的下載: https://developer.android.com/studio/index.html AS的安裝: android studio, sdk, virtual

立方穿越(Volume Pass) 蘋果版下載 | iOS版下載 | iPhone版本下載 | 遊戲下載 | 手遊免費下載 | 版免費下載 | Android版本免費下載 - 動作遊戲 跑酷遊戲

tun iphone 立方體 logs order ima tail isp 成功 立方穿越(Volume Pass) 發布了 立方穿越手遊是一款跑酷類的3D遊戲,在立方穿越手遊中,玩家需要操縱立方體不斷的通過各種各樣的道路以及門框,要求立方體的顏色跟形狀要符合立方體才能通

噴氣機器人(Jet Robot) 蘋果版下載 | iOS版下載 | iPhone版本下載 | 遊戲下載 | 手機遊戲免費下載 | 版免費下載 | Android版本免費下載 - 飛行射擊 飛行

幫助 截圖 有趣 app play tap str ace 分表 噴氣機器人(Jet Robot) 遊戲發布了  噴氣機器人是一款休閑飛行類點擊遊戲,遊戲畫面還是比較有趣的,機器人也非常可愛,點擊飛行,讓小機器人飛得越高越好。 遊戲介紹   噴氣機器人:在這個遊戲中,你必

勇闖天塔 (TOTEM) 遊戲下載 | 手機遊戲免費下載 | 版免費下載 | Android版本免費下載 - 解謎遊戲 闖關遊戲 冒險遊戲

下載遊戲 android版本 超時 mage 截圖 img 圖片 oid round 勇闖天塔 (TOTEM) 遊戲發布了 遊戲簡介《勇闖天塔中文版》是一款趣味性解謎遊戲,畫風設計非常復古,玩家在遊戲中除了收集隱藏的卷軸外還要解答謎題闖關,玩法比較簡單沿著往上的梯子往上走,

球球探秘3D(Secret Balls 3D) 蘋果版下載 | iOS版下載 | iPhone版本下載 | 遊戲下載 | 手機遊戲免費下載 | 版免費下載 | Android版本免費下載 - 休閑 益智 解謎 物理小遊戲

小遊戲 post and 帶來 現在 gpo 做的 borde 免費下載 球球探秘3D(Secret Balls 3D) 手機遊戲發布了 《球球探秘3D》是一款休閑類的遊戲,操控簡單,獨具物理效果,考驗玩家的思維和理解能力,眾多的關卡,更你帶來更加復雜的挑戰,喜歡就趕緊來

地牢迷宮(Maze Dungeon) 蘋果版下載 | iOS版下載 | iPhone版本下載 | 遊戲下載 | 手機遊戲免費下載 | 版免費下載 | Android版本免費下載 - 休閑益智 迷宮遊戲 解謎 無限地宮 無限迷宮模式

分享圖片 top 同時 height 好玩 以及 clas cnblogs 排行 地牢迷宮(Maze Dungeon) 手機遊戲發布了 地牢迷宮是一款非常好玩的休閑類手遊,該遊戲有著全新的玩法、精美的畫面以及炫酷的特效,喜歡這款遊戲的玩家你們還在等什麽呢,快來下載試玩吧!

一文了解APP逆向分析與保護機制

dex 也不會 時也 也有 包含 啟動 RM 操作 混亂 “知物由學”是網易雲易盾打造的一個品牌欄目,詞語出自漢·王充《論衡·實知》。人,能力有高下之分,學習才知道事物的道理,而後才有智慧,不去求問就不會知道。“知物由學”希望通過一篇篇技術幹貨、趨勢解讀、人物思考和沈澱給你

混淆之後,android與js互動異常原因

解決方案:需要js互動程式碼不被混淆掉,加入以下程式碼即可 -keepclassmembers class com.taohaohuo365.taohaohuo.activity.H5Activity$AndroidAndJSInterface { public *; } -keepcla

移動應用開發學習日記(一)

首先,自己安好網上的教程安裝好了AndroidStudio,花了n多時間,接下來就開始進行安卓開發學習啦!PS:根據老師上課 + 安卓程式設計權威指南(資源已上傳https://download.csdn.net/download/xingchen007/10645607)來

視訊直播:nginx搭建伺服器

利用nginx與nginx-rtmp-module搭建流媒體伺服器實現直播 1. 下載 nginx 1.7.11.3 Gryphon 下載連結: http://nginx-win.ecsds.eu/download/nginx 1.7.11.3 Gryphon.zip 下載完成後解壓;