<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>

    解讀ARM三級流水線概念和ARM編碼編譯為二進制的全過程

    VSole2021-09-27 15:13:58

    前言

    交互式反匯編器,簡稱為IDA。是目前最棒的一個靜態反編譯軟件,為眾多0day世界的成員和ShellCode安全分析人士不可缺少的利器!此章節讓我們熟悉通過IDA修改參數、函數、返回值,同時詳細解讀標志位的概念,熟悉堆棧及詳細解讀ARM三級流水線概念和ARM編碼編譯為二進制的全過程。

    一、環境配置

    首先配置IDA與安卓聯動

    IDA動態調用手機apk,請參考:安卓逆向-從環境搭建到動態調試apk IDA部分https://www.freebuf.com/articles/mobile/285861.html

    1)加載server

    2)端口轉發+執行app(javandk1這個測試app)

    adb install E:\IDA7.0\test\javandk1.apk    #安裝appadb shell am start -D -n com.example.javandk1/.MainActivity    #啟動app
    

    adb forward tcp:23946 tcp:23946    #端口轉發
    

    3)打開啟動DDMS

    DDMS
    

    4)打開IDA 32并調試ndk運行

    5)并勾選三項調試

    6)F9啟動+執行jdb調用DDMS

    jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8600
    

    此時可以看到加載的不是so,而是/arm/base.odex文件,那么此時怎么加載我們需要的so庫,分析JNI_onload呢?

    問題:解決方法無libjavandk1.so庫

    1)在Modules查詢java:

    2)選擇libjavacore.so庫-在搜索JNI_load選擇

    那么此時就進入了libjavacore.so的JNI_onload了

    3)接下來下一個斷點:點擊或F2

    4)F9運行后跳轉到斷點截斷處,此時回到Modules繼續搜索java:

    此時就出現需要調試的so庫文件:libjavandk1.so庫文件

    5)那么繼續選擇進入搜索JNI即可

    此時問題就解決了

    6)繼續來到JNI_onload下斷點,開始分析判斷傳參

    二、參數分析

    1、第一種方法

    這里BLX傳入了幾個參數?

    這里BLX中R3需要跳轉,那么R3也是有規定給地址的,所以我們這里的有4個參數R0-R3

    R0-R3:4個寄存器->參數寄存器

    R0-R3:用于函數參數及返回值的傳遞R4-R6,R8,R10-R11:普通的通用寄存器R7:棧幀指針(Frame Pointer),指向前一個保存的棧幀(stack frame)和鏈接寄存器(link register,lr)在棧上的地址。R9:操作系統保留R12:IP(intra-procedure scratch)R13:SP(stack pointer) 是棧頂指針R14:LR(link register) 存放函數的返回地址R15:PC (program counter),指向當前指令地址
    

    如果R3作為一個地址的存放,當你把一個函數地址存放在R3里面,根據規定R3已經作為地址存放了,如果這個函數要傳參,只能從R0-R2,這個三個寄存器里面進行傳參。

    注:如果想判斷有幾個參數,看這個BLX(指令)后面的值(是不是寄存器,如果是,Rn小于4,參數個數就是當前減1;大于等于4,參數寄存器就是R0-R3)

    此時回到圖中,BLX R3;三個參數,用了R0-R2后,只會依次使用下一個寄存器存放跳轉的地址;

    BLX R4(三個參數:R0,R1,R2,R3)

    現在打開堆棧看看

    在BLX R3處打樁,F9運行到下一個斷點處

    記住此時的棧頂是00000001,這時候SP:FF9ABBE0指向棧頂

    這時候單步F7

    這時候查看,SP的值還是FF9ABBE0是沒有變化的

    2、第二種方法

    靜態調試SO庫,按F5查看偽代碼

    可以查看到偽c代碼(int a1,int a2)就是查看參數個數

    二、修改寄存器-返回值

    我們隨便找的幾個BLX指令的地方。

    BLX R3此時傳入幾個參數 ?三個

    那么BLX R12傳入幾個參數?四個

    按F5進入偽C代碼

    靜態注冊參數怎么修改呢?選擇你要修改的參數,按Y

    如何修改寄存器的值呢

    這時候就可以修改寄存器的值了

    例如:cmp R0,0,那么就執行BEN,意思就是修改了條件為0后,就不執行改條件,反調試會更深入演示

    Y鍵修改C代碼(退出C代碼按ESC)

    R0-R3:用于函數參數及返回值的傳遞R4-R6,R8,R10-R11:普通的通用寄存器R7:棧幀指針(Frame Pointer),指向前一個保存的棧幀(stack frame)和鏈接寄存器(link register,lr)在棧上的地址。R9:操作系統保留R12:IP(intra-procedure scratch)R13:SP(stack pointer) 是棧頂指針R14:LR(link register) 存放函數的返回地址R15:PC (program counter),指向當前指令地址
    

    三、修改寄存器-修改函數

    1、方法1-修改Hex

    如果我要改這條指令

    根據三級流水線,需要在前三個代碼斷點

    不想讓程序執行怎么辦?直接同步下PC寄存器

    現在你想在HEX處找的PC的指令,當鼠標放在PC指令處,hex自動選擇

    然后在Hex View-1處快捷鍵F2操作,修改,

    修改為00 00 00 00后,然后在快捷鍵F2保存下

    這時候指令就沒了

    2、方法2-修改General

    或者直接設置PC(只適合調試時候測試使用)

    例如此刻需求是,跳過大紅框內容,直接執行MOV R0, #0x10004這條指令,此刻PC在F42AA08C

    只需要在General registers處修改PC值為MOV處的指令值即可,那么此時MOV出指令值為:

    F42AA0A4
    

    開始修改,雙擊General registers-PC處,修改為MOV的值:

    直接跳轉mov處

    四、IDA配置堆棧信息

    在PC窗口處配置出堆棧指針和Hex View對應的十六進制的值

    五、IDA標志位詳解

    CPSR標志位詳解

    一邊情況下標志位情況

    斷點后的情況

    用最簡單的理解,這些到底有什么用

    通過圖很好了解,例如BLX進行運算是正數還是負數,經過運算后值是不是為零,可以理解為條件標志位,幫我們記錄一些狀態!

    標志位的結果內容可被算數或邏輯運算的結果所改變,并且可以決定某條指令是否被執行。

    最重要的是N、Z、C、V、Q、T,那么T是什么意思?

    T標志位︰該為反應處理器的運行狀態。當該位為1時,程序運行于THUMB狀態,否則運行于ARM狀態。該信號反映在外部引腳TBIT上。在程序中不得修改CPSR中的TBIT位,否則處理器工作狀態不能確定。

    ARM狀態

    arm處理器工作于32位指令的狀態,所有指令均為32位

    thumb狀態

    arm執行16位指令的狀態,即16位狀態

    六、ARM匯編三級流水線詳解

    1、什么是三級流水線

    前綴

    ARM7處理器采用3級流水線來增加處理器指令流的速度,能提供0.9MIPS/MHz的指令處理速度。MIPS(Million Instruction Per Second)表示每秒多少百萬條指令。比如0.9MIPS,表示每秒九十萬條指令。MIPS/MHz表示CPU在每MHz的運行速度下可以執行多少個MIPS,如0.9MIPS/MHz則表示如果CPU運行在1MHz的頻率下,每秒可執行90萬條指令。
    

    三級流水線使用3個階段,因此指令分為3個階段執行

    1)取指從存儲器裝載一條指令
    2)譯碼識別將要被執行的指令
    3)執行處理指令并將結果寫會寄存器
    

    但是處理實際是這樣的:ARM正在執行第一條指令的同時對第二條指令進行譯碼,并將第三條指令從存儲器中取出

    所以,ARM7流水線只能在取第4條指令時,第1條指令才算完成執行

    無論處理器處于何種狀態,程序計數器R15(PC)總是指向”正在取指“的指令,而不是指向”正在執行“的指令或者正在”譯碼“的指令。

    人們一邊會習慣性的將正在執行的指令作為參考點,即當前第一條指令,所以,pc總是指向第三條指令

    或者說PC總是指向當前正在執行的指令在加2條指令的地址

    2、三級流水線詳解

    處理器處于ARM狀態是,每條指令為4個字節,所以PC指令為正在執行的指令地址加8個字節,即是:

    PC值=當前程序執行位置+8字節

    處理器處于Thumb狀態時,每條指令為2字節,所以PC值為正在執行的指令地址加4字節,即是:

    PC值=當前程序執行位置+4字節

    下面一個列子很好的說明了這個問題

    libjavandk1.so:F42AA090 010 00 C0 90 E5 LDR    R12, [R0]    #正在被執行的指令libjavandk1.so:F42AA094 010 5C C3 9C E5 LDR    R12, [R12,#0x35C]  #正在被編碼的指令libjavandk1.so:F42AA098 010 3C FF 2F E1 BLX    R12   #正在被取指的指令 PC=F42AA098libjavandk1.so:F42AA09C 010 00 00 50 E3 CMP    R0, #0    #PC+4=F42AA09C
    

    另外補充說明就是根據以上描述,流水線只有被指令填滿時才能發揮最大的效能,既每時鐘周期完成一條指令的指向(僅單周期指令)

    如果程序發送跳轉,流水線會被清空,這將需要幾個時鐘才能使流水線被再次填滿。因此,盡量地少使用跳轉指令可以提高程序的指令效率

    PC代表程序計數器,流水線使用三個階段,因此指令為分為三個階段執行:

    1、取指(從存儲器裝載一條指令)
    2、譯碼(識別將要被執行的指令)
    3、執行(處理指令并將結果寫回寄存器)
    

    而R15(PC)總是指向”正在取指“的指令,而不是指向”正在執行“的指令或者正在”譯碼“的指令。一般來說,人習慣性約定將”正在執行“的指令作為參考點,稱之為第一條指令,因此PC總是指向第三條指令,當ARM狀態時,每條指令為4字節長,所以PC始終指向改指令地址加8字節的地址,既:PC值=當前程序執行位置+8;

    ARM指令是三級流水線,取指、譯指、執行是同時執行的,現在PC指向的是正在取值的地址,那么CPU正在譯指的指令地址是PC-4(假設ARM狀態下,一個指令占4個字節),cpu正在執行的指令地址是cpu-8,也就是說PC所指向的地址和現在所執行的指令地址相差8。

    當突然發生中斷的時候,保存的是PC的地址

    這樣你就知道了,如果返回的時候返回PC,那么中間就有一個指令沒有執行,所以用SUB pc lr-irq#4。

    這個需要參考《ARM指令》來學習

    3、案例-ARM指令轉換為機器碼

    下面我們將一個ARM指令轉換為機器碼試試

    00001BD0 BEQ lc04
    BEQ lc04;跳轉指令,執行條件EQ,即相等跳轉到lc04
    

    來計算這條指令

    1)首先ARM指令是32位的,因為這里是BEQ的B的跳轉指令,32位可以拆分為格式如下

    2)前四位:31-28就是cond,這里的意思就是條件碼,例如EQ、NE

    0000
    

    3)緊接著3位:27-25(這里由于B指令是101固定的)

    0000 101
    

    4)在往下24位:(1或者0,具體判斷:帶有連接的如果是BL指 令對應的二進制操作數就是1 無條件跳轉B指令就是0。)

    0000 1010
    

    5)0-23位:偏移地址:目標地址與該指令的相對偏移

    偏移的計算公式:

    (目標跳轉的地址-(當前這條指令的地址+8))/4
    (1c04-(1bd0+8))/4=1011
    1c04:要跳轉的地址
    1bd0:此指令所在的地址
    +8:arm指令有3級流水線的原因,如果執行1c04地址指令,需要加8
    /4:因為要做對 其處理
    

    我們拼接一下計算出來的二進制ARM指令機器碼,因為0-23位算出來的是1011,

    1011對應0-3位置

    4-23用0補齊

    結果

    0000 1010 0000 0000 0000 0000 0000 1011
    

    轉換為16進制就是

    0A 00 00 0B
    

    因為是小端模式,需要換一下位置結果就是

    0B 00 00 0A
    

    我們在IDA中測試一下

    將IDA中hex中隨便一個地方改為0B 00 00 0A

    我們看到指令變為了BEQ loc_F42AA0D4

    我們計算利用偏移公式計算F42AA0D4(目標地址)和F42AA0A0(當前地址)結果是不是1011

    (A0D4-(A0A0+8))/4=1011
    

    我們這里就簡單了解到了ARM指令如何計算為ARM指令機器碼

    七、總結

    此章節我們詳細學習了使用IDA在靜態注冊和動態注冊下分析和修改參數,學習修改返回值、函數,對IDA堆棧功能模塊和標志位功能模塊進行深入解析,同時了解了ARM中三級流水線并利用案例熟悉ARM指令轉換為機器碼的案例。

    arm流水線
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    交互式反匯編器,簡稱為IDA。是目前最棒的一個靜態反編譯軟件,為眾多0day世界的成員和ShellCode安全分析人士不可缺少的利器!此章節讓我們熟悉通過IDA修改參數、函數、返回值,同時詳細解讀標志位的概念,熟悉堆棧及詳細解讀ARM三級流水線概念和ARM編碼編譯為二進制的全過程。
    具體而言,激光故障注入可用于瞄準和修改指令,導致指令被破壞、跳過等。此外,激光源允許獲得可編程延遲,功率范圍為0到3瓦。故障發生機制根據故障指令的數量以及在禁用和啟用緩存時報告的故障行為,嘗試確定指令在哪個階段出現故障。為了檢測和大致分類誘發故障,首先要了解從閃存到核心管道的指令流。本文的結果說明了激光故障注入的空間和時間準確性,指出了易受攻擊的位置并揭示了設備架構的信息。
    近日,中國信通院在2022“3SCON軟件供應鏈安全大會”上正式發布《軟件供應鏈廠商和產品名錄》,深信服入選“軟件供應鏈廠商”,旗下信服云超融合、信服云云計算平臺、信服云數據庫管理平臺等入選“軟件供應鏈產品”。云內建安全2.0以自動安裝代理的方式提供病毒查殺、漏洞修復等主機安全能力,實現業務上線即安全。
    DPU家族大探秘
    2021-12-30 08:49:53
    Nvidia CEO黃仁勛在GTC(GPU技術大會)上提出:“用于通用計算的CPU,用于加速計算的GPU,用于網絡數據處理的DPU,將成為未來計算的三大支柱”。究竟什么是DPU?為什么它將有可能與傳統的CPU、GPU平起平坐呢?
    文中使用的示例代碼可以從 這里 獲取。的功能是在終端打印出hello這6個字符(包括結尾的?編譯它們分別生成libtest.so和?存在嚴重的內存泄露問題,每調用一次say_hello函數,就會泄露1024字節的內存。
    Arm 于 10 月 2 日發布安全公告,表示 Mali GPU 驅動程序中存在漏洞,現有證據表明已經有黑客利用該漏洞發起攻擊。
    Arm 周一警告其 Mali 系列 GPU 驅動漏洞 CVE-2023-4211 正被活躍利用。Mali GPU 被廣泛用于 Google Pixels 等 Android 手機,Chromebook 等 Linux 設備。本地非特權用戶可利用該漏洞訪問已釋放的內存。訪問不再使用的系統內存是將惡意代碼加載到攻擊者可執行位置的一種常見機制。Arm 表示它已在 Bifrost、Valhall 和 Ar
    ARM PWN基礎教程
    2022-07-27 17:29:43
    在CTF比賽中,我們所能接觸到的大部分都是x86 x86_64架構的題目,而在我開始接觸IOT方向的研究以后發現智能設備所用到的則是ARM和MIPS架構為主。本篇文章在介紹前置知識的基礎上通過CTF的ARM架構類型題帶讀者更好的入門ARM PWN的世界。
    在工作中,多多少少會遇到花指令的情況,本系列文章我會慢慢更新,把我學習過程分享給大家,從簡單的構造到如何結合手頭的工具patch。這里為什么沒有研究x86,第一因為我不會第二個原因是x86是非定長指令集,這會導致x86有那種雙字節的花指令不適合線形掃描,要校驗的太多了無法通過定長4字節的方式進行線性掃描。第一章簡單的花指令構造與修正◆example1 _main:
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类