標籤:

AtomBombing利用分析

0x00 前言

2016年10月,網路安全公司EnSilo的研究團隊公開了一個支持所有Windows系統的代碼注入方法,將其命名為AtomBombing。據說該方法能夠繞過大多數的安全軟體,並且利用的系統缺陷很難被修復。

於是,本文將要根據開源代碼和資料,學習原理,測試功能,分析利用思路,總結防禦方法

學習資料:

blog.ensilo.com/atombom

作者:Tal Liberman

POC:

github.com/BreakingMalw

0x01 簡介

本文將要介紹以下內容:

· AtomBombing實現方法

· 關鍵技術

· 防禦思路

0x02 基礎知識

1、Atom Table

是一個存儲字元串和相應標識符的系統定義表

應用程序將一個字元串放入一個Atom表中,並接收一個16位整數(WORD)作為標識(稱為Atom),可通過該標識訪問字元串內容,實現進程間的數據交換

分類:

(1) Global Atom Table

所有應用程序可用

當一個進程將一個字元串保存到Global Atom Table時,系統生成一個在系統範圍內唯一的atom,來標示該字元串。在系統範圍之內所有的進程都可以通過該atom(索引)來獲得這個字元串,從而實現進程間的數據交換

(2) Local Atom Table

只有當前程序可用,相當於定義一個全局變數,如果程序多次使用該變數,使用Local Atom Table僅需要一次內存操作

參考資料:

msdn.microsoft.com/en-u

常用API:

添加一個Global Atom:

ATOM WINAPI GlobalAddAtom(_In_ LPCTSTR lpString);n

刪除一個Global Atom:

ATOM WINAPI GlobalDeleteAtom(_In_ ATOM nAtom);n

查找指定字元串對應的Global Atom:

ATOM WINAPI GlobalFindAtom(_In_ LPCTSTR lpString);n

獲取指定atom對應的字元串:

UINT WINAPI GlobalGetAtomName(n _In_ ATOM nAtom,n _Out_ LPTSTR lpBuffer,n _In_ int nSizen);n

註:

使用實例可參考如下連接:

github.com/sinmx/Window

2、APC注入

APC全稱asynchronous procedure call,即非同步過程調用

APC注入原理:

當線程處於警戒狀態時,會檢查APC隊列,如果APC隊列被插入函數指針,該函數將會得到執行

APC注入細節:

(1) 當線程調用SleepEx、SignalObjectAndWait、MsgWaitForMultipleObjectsEx,WaitForMultipleObjectsEx或者WaitForSingleObjectEx函數時,會切換到警戒狀態(alertable state)

註:

警戒狀態可參考:

msdn.microsoft.com/en-u

(2) 當線程進入警戒狀態時,會循環檢查線程中的APC隊列,如果APC隊列中存在函數指針,那麼就會調用該函數

(3) 使用QueueUserAPC函數向APC隊列插入函數指針Loadlibrary(),實現載入DLL

(4) 注入成功後,警戒狀態結束,程序繼續運行,有可能造成程序不穩定,導致程序崩潰

(5) 如果沒有刪除APC隊列,不能反覆注入同一函數

(6) 使用APC注入,需要目標進程中至少有一個線程處於警戒狀態或者能夠進入警戒狀態,否則無法實現APC注入

註:

大部分系統進程都滿足條件,支持APC注入

可供參考的APC注入代碼:

github.com/3gstudent/In

3、shellcode

在漏洞利用中,shellCode是指輸入到存在漏洞的程序中的代碼

相當於一個二進位代碼框架,最終會將程序的流程跳轉到payload

4、payload

主要功能代碼(常見的如下載執行、反彈shell、新建用戶等),包含在shellCode中

0x03 實現方法

1、將任意數據寫入目標進程地址空間中的任意位置(Write-What-Where)

通過讀寫atom向目標進程傳遞shellcode

自身進程通過GlobalAddAtom將shellcode添加到Global Atom Table中,目標進程調用GlobalGetAtomName即可從Global Atom Table中獲取shellcode

所以接下來的關鍵是如何使目標進程調用GlobalGetAtomName

Tal Liberman的思路是通過APC注入,使目標進程調用GlobalGetAtomName

但是這裡遇到了一個難題,QueueUserAPC函數只能向目標進程傳入一個參數,而GlobalGetAtomName需要三個參數

於是Tal Liberman調試了QueueUserAPC函數,發現通過NtQueueApcThread函數能夠傳遞三個參數

該問題得到解決

2、執行shellcode

目標進程調用GlobalGetAtomName從Global Atom Table中獲取shellcode後,需要先保存shellcode再執行

第一種實現方法: 找到一段RWX的內存存儲並執行

不通用,目前的系統保護機制很難找到這樣的內存空間

第二種實現方法: 調用VirtualAllocEx分配一段內存

常用方法

注:

其他常見方法如通過VirtualProtect將shellcode的內存屬性設置為可讀可寫可執行,然後跳到shellcode繼續執行在這裡的效果並不好,因為需要考慮使用QueueUserAPC函數傳入參數的問題

所以Tal Liberman嘗試了第三種方法: 找到一段RW的內存寫入數據,構造ROP鏈實現shellcode的執行

尋找一段RW的內存並不難,Tal Liberman選擇了KERNELBASE數據段後未使用的空間

ROP鏈實現了以下功能:

1.申請RWX內存

2.將shellcode從RW內存處拷貝到RWX內存儲

3.執行

註:

在ROP鏈的構造上,Tal Liberman提供了自己的思路,儘可能簡化ROP鏈,優化思路值得學習

3、恢復執行

注入後需要恢複目標進程的執行,使用未公開的函數ZwContinue

0x04 實際測試

測試系統: Win7 x86

安裝python,安裝pefile(easy_install pefile)

編譯生成AtomBombing.exe、AtomBombingShellcode.exe和AtomBombingShellcode.h

註:

AtomBombingShellcode.h由AtomBombingShellcodeScriptsPost_Link.py生成,可在AtomBombingShellcode工程中的後期生成事件中查看具體參數,如下圖

啟動chrome.exe,執行AtomBombing.exe,注入成功,如下圖

補充:

Windows 8.1 update 3和Windows 10添加了一個新的保護機制CFG(Control Flow Guard),CFG的繞過可參考如下鏈接:

blog.ensilo.com/atombom

0x05 利用分析

綜合公開資料和實際測試,可以將AtomBombing理解為一個APC注入的升級版: 利用Atom Table傳遞shellcode,通過NtQueueApcThread實現APC注入,shellcode採用構造ROP鏈的方式,實現了申請內存、寫入payload(彈出計算器)並執行的功能

Atom Table支持Windows全平台,並且短期內該功能不會被取消,也不存在修復措施,所以可以在某種程度上理解為不存在修復AtomBombing的補丁

但是,想實現AtomBombing的利用,需要綜合考慮多個問題(如獲取處於警戒狀態的線程、通過NtQueueApcThread傳入參數、尋找RX內存,構造ROP鏈等),利用門檻較高

並不適用於所有進程(目標進程中至少有一個線程處於警戒狀態或者能夠進入警戒狀態)

能繞過部分殺毒軟體,但不能繞過所有的殺毒軟體(使用NtQueueApcThread進行注入)

0x06 檢測防禦

將AtomBombing理解為APC注入的升級版,所以參照APC注入的防禦方法即可,攻擊者首先需要獲得系統的執行許可權,並找到符合條件的進程

檢測:

監控NtQueueApcThread函數的調用

0x07 小結

本文介紹了AtomBombing的實現思路和關鍵技術,經過實際測試,得出最終結論,AtomBombing是一種新的DLL注入方法,可以理解為一個APC注入的升級版: 利用Atom Table傳遞shellcode,通過NtQueueApcThread實現APC注入,shellcode採用構造ROP鏈的方式,實現了申請內存、寫入payload(彈出計算器)並執行的功能

本文為 3gstudent 原創稿件, 授權嘶吼獨家發布,如若轉載,請聯繫嘶吼編輯: 4hou.com/system/9724.ht 更多內容請關注「嘶吼專業版」——Pro4hou

推薦閱讀:

TAG:信息安全 |