<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    某DEX_VMP安全分析與還原

    VSole2022-01-16 16:40:28

    思路整理

    還原VMP需要哪些鋪墊?

    (1)定位VMP字節碼

    (2)分割VMP字節碼

    (3)還原成SMALI

    (1)為什么要找VMP字節碼的位置?

    因為如果目標方法的字節碼地址,都找不到,還原也就沒法展開了。

    (2)為什么要分割VMP字節碼?

    如果要反匯編成smali,起碼要知道這條smali對應的字節碼一共幾個字節。在確定一條指令占幾個字節后,還要知道這幾個字節中,誰是操作碼,誰是操作數。

    (3)還原為SMALI

     有了前兩步鋪墊,最終我們可以解讀一條完整的smali的含義。

    某安卓VMP入口特征(2021.8月樣本)

    跳板方法

    進入native后的參數處理邏輯。

     為了處理不同類型的返回值, 定義了多個jni方法。

     對應jni函數入口指令情況。

    定位VMP字節碼

    邏輯

    根據上述邏輯,則一定存在函數F,向F輸入index可得到對應codeitem_addr

    F(index) == codeitem_addr。

    我們看一下這個函數,從index到codeitem_addr的過程

    (0x2dce->0xcac85880)。

    如何在十幾萬數量級的匯編中定位到這段代碼的?

    通過Trace記錄REG信息,用到了兩個關鍵數值,0x2dce(index)與0xcac85880(codeitems),標記兩個數值出現的中間區間即可。

    展開上面的定位方式的兩個前提條件:

    我們已經有了關鍵數據0x2dce,但還需要知道另一個提前條件,

    即codeitem是0xcac85880,所以這個信息是從哪得知的?

    這里是本章的關鍵。

    如何分析出codeitem的地址是0xcac85880?

    (1) 已知明文

    (2) 沙箱日志獲取切入點

    (3) JNI參數回溯

    (4) 內存訪問統計

    (1)已知明文

    目標APP內很多的onCreate()方法,其內部普遍調用了,

    NBSTraceEngine.startTracing();以及super.onCreate()

    我們選一個被vmp保護了的onCreate()作為分析目標, ZxWebViewActivity.onCreate()

    (2) 沙箱日志獲取切入點

    ① ZxWebViewActivity.onCreate內必定存在NBSTraceEngine.startTracing();以及super.onCreate()

    ② startTracing為靜態方法,會被編譯器編譯為invoke-static

    ③ super.onCreate()為超類調用,會被編譯器編譯為invoke-super

    ④我們猜測vmp對invoke-static模擬實現借助了JNI函數,

    所以我們觸發ZxWebViewActivity.onCreate()執行,截取其調用序列,效果如下:

     大致邏輯為:

    (3) JNI參數startTracing來源回溯

    我們在trace中找到這條GetStaticMethodID()的出現位置,

    然后作為起點向上展開回溯,希望找到其參數”startTracing”的最早出處,

    如果有自動化的腳本和條件可進行污點分析,由于邏輯不是很復雜,這里人工回溯完成。

    具體過程省略……

    在trace中對參數”startTracing”來源進行一番回溯,最終發現了一個起到決定性作用的偏移值0x000081de。可以簡單理解成,它以base+0x000081de的形式確立的參數”startTracing”。

    結論:

    如果0x000081de是那個起到決定性意義的數值,那么毫無疑問0x000081de來自codeitem。

    在trace中找到0x81de的出現位置,

    發現它來自于內存位置0xcac858a8。

    (4) 內存訪問統計 

    0x81de來自0xcac858a8,由于這個地址可能是codeitem,

    因此我們檢索一下,trace中對這片內存區域的訪問情況。

    0xcac858a8取前5個高位,忽略后3個地位,即檢索對0xcac85???的訪問。

    找到19條指令,而對0xcac85???的訪問,最早的第一條指令,出現在編號5691的位置,對應的內存地址為0xcac85890,說明這里是ZxWebViewActivity.onCreate()第一條字節碼。

    由于codeitem第一條字節碼之前0x10個字節還存在一些固定內容,

    所以0xcac85890-0x10取得codeitem地址0xcac85880,

    即codeitem的地址是0xcac85880。

    分割VMP字節碼

    現在已經有了某廠vmp codeitems全部內容,但是還沒法反匯編成smali,

    因為還不知道,第一條指令一共占幾個字節,第二條指令一共占幾個字節,

    依次......

    dalvik指令是不等長,反匯編成smali的話,起碼要知道這條smali對應的字節碼一共幾個字節。在知道了每條指令占幾個字節后,還要知道這幾個字節中,誰是操作碼,誰是操作數。

    通過觀察codeitem的內存段的讀取情況,可以達到這個目的。

    如何快速區分出操作碼和操作數?

    一般opcode后面會有一個EOR解密指令,以及一串類似定位handle的CMP指令操作,而operand沒有,這就為區分opcode和operand提供了特征依據。

    opcode解密邏輯?

    由eor指令向上回key出現的位置,即可確定key的來源,以及解密邏輯.大致邏輯:off1 = sub( codeitem當前指令地址, codeitem基址 )off2 = lsl( off1, 1)key = load( base + off2 )de_opcode = xor(en_opcode, key)
    

    VMP字節碼還原為SMALI

    1、標準dalvik指令反匯編過程

    2、VMP指令反匯編過程

    由于使用了已知明文條件作為切入點,已知分析目標ZxWebViewActivity.onCreate()中,必定會調用startTracing()方法,

    即必定存在invoke-static {v0}, method@00da6f // ...startTracing

    又通過上面的分析得知關鍵值81de出現在這條invoke-static中,且充當操作數的角色,那么按照我們按照標準invoke-static反匯編規則進行解析,就可以得到結論。

    VMP指令由標準指令基礎上修改而來,有哪些異同?

    3、還原VMP所有指令需要什么?

    4、沒有opcode對照表時如何展開還原?

    (1)接口猜測法

    method相關的invoke系列指令,可以通過JNI執行情況猜測。

    Field相關的get set系列指令,也可以通過JNI執行情況猜測。

    (2)參數推導法

    方法調用前,會先準備參數,通常是聲明類型的指令,可以很大程度縮小猜測的候選指令范圍。

    (3)標準dalvik指令格式的信息利用

    由于vmp指令是由dalvik標準指令略微修改/變異而來,只做了較小的改動,仍然保留了BIT位分布特征這樣信息。在做還原時,可以利用這些信息,一定程度縮小候選范圍。

    https://source.android.com/devices/tech/dalvik/instruction-formats

    https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions


    攻擊面總結

    1、分析路徑

    2、攻擊面總結 && 啟示

    (1) 被VMP的方法內部存在已知明文指令。

    (2) VMP的實現高度依賴JNI函數,通過HOOK拿到其調用信息,是非常有效的切入點與突破口。

    (3) codeitems的連續性,集中存儲的特性,通過內存訪問統計最終被發現。

    (4)某vmp指令由標準dalvik指令基礎上略改而來,整體仍然保留了很多可用信息。

    深入VMP還原的一些問題

    略。

    調試與工具總結

    核心問題:

    獲取程序完整的執行&&數據信息 (trace)。

    目前公開的主流的獲取trace的方案:

    ① GDB調試

    ② FridaStalker編譯執行

    ③ 脫機unicorn模擬執行

    主流的獲取trace的方案的弊端和缺陷:

    ① IDA / GDB

    速度極慢,且會遭遇反調試。

    ② FridaStalker

    不支持arm指令的thumb模式,且BUG多,遭遇vmp.so中的花指令時,基本無法正常使用。

    ③ PC上脫機unicorn模擬執行

    vmp.so中存在大量jni call和system call,需要手動實現它們,unicorn才能完成運行。

    基于以上問題的嘗試:

    實現原始APP進程環境 && 原始context中,通過unicorn構造虛擬化CPU,執行目標function,獲得trace,無已知檢測和對抗手段,簡單過anti。

    基于trace進行離線分析:

    ① trace形態可視化

    文本 / json / 數據庫 / EXCEL可視化表格 / 動態CFG圖

    ② 基本的分析

    地址含義解析 調用符號識別

    ③ 程序分析

    污點分析 相似性分析等

     

    字節碼匯編指令
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    文中使用的示例代碼可以從 這里 獲取。的功能是在終端打印出hello這6個字符(包括結尾的?編譯它們分別生成libtest.so和?存在嚴重的內存泄露問題,每調用一次say_hello函數,就會泄露1024字節的內存。
    匯編語言是一種用于電子計算機、微處理器、微控制器或其他可編程器件的低級語言,亦稱為符號語言。Smali匯編基礎Smali語言最早是由JesusFreke發布在Google Code上的一個開源項目,并不是擁有官方標準的語言。因此也將Smali語言稱作Android虛擬機的反匯編語言。基本類型Smali基本數據類型中包含兩種類型,原始類型和引用類型。而在Smali中則是以LpackageName/objectName的形式表示對象類型。
    前言最近一段時間在研究Android加殼和脫殼技術,其中涉及到了一些hook技術,于是將自己學習的一些hook技術進行了一下梳理,以便后面回顧和大家學習。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。所以動態鏈接是將鏈接過程推遲到了運行時才進行。
    結果分析Hook前Hook后,我們的彈窗本該是hello的但是hook后,程序流程被我們修改了。760D34B2 55 push ebp760D34B3 8BEC mov ebp,esp通過這兩條指令,函數就可以在堆棧中為局部變量分配存儲空間,并在函數執行過程中保存和恢復現場。這樣做的好處是可以避免局部變量和其他函數之間的沖突,同時也可以提高函數的可讀性和可維護性。
    Frida工作原理學習
    2022-07-12 16:28:29
    frida是一款便攜的、自由的、支持全平臺的hook框架,可以通過編寫JavaScript、Python代碼來和frida_server端進行交互,還記得當年用xposed時那種寫了一大堆代碼每次修改都要重新打包安裝重啟手機、那種調試調到頭皮發麻的痛苦,百分之30的時間都是在那里安裝重啟安裝重啟。
    系統安全第44篇介紹經典的靜態特征提取工具CAPA,希望對您有所幫助
    BPF之路二(e)BPF匯編
    2021-12-28 16:18:32
    原始的BPF又稱之為class BPF(cBPF), BPF與eBPF類似于i386與amd64的關系
    VMPWN的入門系列-1
    2023-07-27 09:45:00
    今天的文章有點長,圖片比較多,請耐心閱讀5.1 實驗一 VMPWN15.1.1 題目簡介這是一道基礎的VM相關題目,VMPWN的入門級別題目。
    vmp 相關的問題
    2021-11-19 16:58:50
    為新版本的符合一個叫做寄存器輪轉的問題所以他可能jmp ebp,jmp edi等等的。
    如果要反匯編成smali,起碼要知道這條smali對應的字節一共幾個字節。在確定一條指令占幾個字節后,還要知道這幾個字節中,誰是操作碼,誰是操作數。有了前兩步鋪墊,最終我們可以解讀一條完整的smali的含義。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类