7.1 Windows驅動開發:內核監控進程與線程回調

在前面的文章中LyShark一直在重復的實現對系統底層模塊的枚舉,今天我們將展開一個新的話題,內核監控,我們以監控進程線程創建為例,在Win10系統中監控進程與線程可以使用微軟提供給我們的兩個新函數來實現,此類函數的原理是創建一個回調事件,當有進程或線程被創建或者注銷時,系統會通過回調機制將該進程相關信息優先返回給我們自己的函數待處理結束后再轉向系統層。

PsSetCreateProcessNotifyRoutineEx和PsSetCreateThreadNotifyRoutine是Windows操作系統提供的兩個內核回調函數,它們允許開發者在進程或線程發生創建事件時攔截并處理這些事件。這兩個函數提供的回調機制是操作系統提供的最基本、最常用的內核監控進程與線程的方式。

PsSetCreateProcessNotifyRoutineEx和PsSetCreateThreadNotifyRoutine的使用方式和參數類型類似,它們都需要開發者提供一個回調函數,當進程或線程被創建時,操作系統會調用這個回調函數。這個回調函數需要滿足一定的約束條件,例如不能阻塞或掛起進程或線程的創建或訪問,不能調用一些內核API函數等。

PsSetCreateProcessNotifyRoutineEx和PsSetCreateThreadNotifyRoutine的主要區別在于它們所監控的事件不同。PsSetCreateProcessNotifyRoutineEx用于監控進程的創建事件,當有新的進程被創建時,操作系統會調用注冊的回調函數。而PsSetCreateThreadNotifyRoutine用于監控線程的創建事件,當有新的線程被創建時,操作系統會調用注冊的回調函數。

內核監控進程PsSetCreateProcessNotifyRoutineEx和線程PsSetCreateThreadNotifyRoutine回調在安全軟件、系統監控和調試工具等領域有著廣泛的應用。需要注意的是,在Windows 8及更高版本的操作系統中,微軟推薦開發者使用ExRegisterCallback和ExUnregisterCallback函數進行回調的注冊和注銷。

進程回調默認會設置CreateProcess通知,而線程回調則會設置CreateThread通知,我們來看ARK工具中的枚舉效果。

  • 通常情況下:
    • PsSetCreateProcessNotifyRoutineEx 用于監控進程
    • PsSetCreateThreadNotifyRoutine 用于監控線程

PsSetCreateProcessNotifyRoutineEx

監控進程的啟動與退出可以使用 PsSetCreateProcessNotifyRoutineEx來創建回調,當新進程創建時會優先執行回調,我們看下微軟是如何定義的結構。

// 參數1: 新進程回調函數
// 參數2: 是否注銷
NTSTATUS PsSetCreateProcessNotifyRoutineEx([in] PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine,[in] BOOLEAN                           Remove
);

如上,該函數只有兩個參數,第一個參數是回調函數,第二個參數是是否注銷,通常在驅動退出時可以傳入TRUE對該回調進行注銷,通常情況下如果驅動關閉,則必須要注銷回調,而對于MyLySharkCreateProcessNotifyEx自定義回調來說,則需要指定三個必須要有的參數傳遞。

// 參數1: 新進程的EProcess
// 參數2: 新進程PID
// 參數3: 新進程詳細信息 (僅在創建進程時有效)VOID MyLySharkCreateProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)

根據如上函數定義,就可以實現監控功能了,例如我們監控如果進程名是lyshark.exe則直接CreateInfo->CreationStatus = STATUS_UNSUCCESSFUL禁止該進程打開。

#include <ntifs.h>// 兩個未公開函數導出
NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);// 通過PID獲得進程名
PCHAR GetProcessNameByProcessId(HANDLE ProcessId)
{NTSTATUS st = STATUS_UNSUCCESSFUL;PEPROCESS ProcessObj = NULL;PCHAR string = NULL;st = PsLookupProcessByProcessId(ProcessId, &ProcessObj);if (NT_SUCCESS(st)){string = PsGetProcessImageFileName(ProcessObj);ObfDereferenceObject(ProcessObj);}return string;
}// 繞過簽名檢查
BOOLEAN BypassCheckSign(PDRIVER_OBJECT pDriverObject)
{
#ifdef _WIN64typedef struct _KLDR_DATA_TABLE_ENTRY{LIST_ENTRY listEntry;ULONG64 __Undefined1;ULONG64 __Undefined2;ULONG64 __Undefined3;ULONG64 NonPagedDebugInfo;ULONG64 DllBase;ULONG64 EntryPoint;ULONG SizeOfImage;UNICODE_STRING path;UNICODE_STRING name;ULONG   Flags;USHORT  LoadCount;USHORT  __Undefined5;ULONG64 __Undefined6;ULONG   CheckSum;ULONG   __padding1;ULONG   TimeDateStamp;ULONG   __padding2;} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#elsetypedef struct _KLDR_DATA_TABLE_ENTRY{LIST_ENTRY listEntry;ULONG unknown1;ULONG unknown2;ULONG unknown3;ULONG unknown4;ULONG unknown5;ULONG unknown6;ULONG unknown7;UNICODE_STRING path;UNICODE_STRING name;ULONG   Flags;} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#endifPKLDR_DATA_TABLE_ENTRY pLdrData = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;pLdrData->Flags = pLdrData->Flags | 0x20;return TRUE;
}// 進程回調函數
VOID My_LyShark_Com_CreateProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
{char ProcName[16] = { 0 };if (CreateInfo != NULL){strcpy_s(ProcName, 16, PsGetProcessImageFileName(Process));DbgPrint("[LyShark] 父進程ID: %ld | 父進程名: %s | 進程名: %s | 進程路徑:%wZ \n", CreateInfo->ParentProcessId, GetProcessNameByProcessId(CreateInfo->ParentProcessId), PsGetProcessImageFileName(Process), CreateInfo->ImageFileName);// 判斷是否為指定進程if (0 == _stricmp(ProcName, "lyshark.exe")){// 禁止打開CreateInfo->CreationStatus = STATUS_UNSUCCESSFUL;}}else{strcpy_s(ProcName, 16, PsGetProcessImageFileName(Process));DbgPrint("[LyShark] 進程[ %s ] 退出了, 程序被關閉", ProcName);}
}VOID UnDriver(PDRIVER_OBJECT driver)
{DWORD32 ref = 0;// 注銷進程回調ref = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)My_LyShark_Com_CreateProcessNotifyEx, TRUE);DbgPrint("[lyshark] 注銷進程回調: %d \n", ref);
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{NTSTATUS status;// 繞過簽名檢查// LINKER_FLAGS=/INTEGRITYCHECKBypassCheckSign(Driver);DbgPrint("hello lyshark \n");// 創建進程回調// 參數1: 新進程的EProcess// 參數2: 新進程PID// 參數3: 新進程詳細信息 (僅在創建進程時有效)status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)My_LyShark_Com_CreateProcessNotifyEx, FALSE);if (!NT_SUCCESS(status)){DbgPrint("[lyshark] 創建進程回調錯誤");}Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;
}

編譯并運行這個驅動程序,我們可以在ARK工具中看到這個驅動所加載的CreateProcess的回調事件。

當驅動加載后,如果你嘗試打開lyshark.exe那么會提示連接的設備沒有發揮作用,我們則成功攔截了這次打開,當然如果在打開進程之前掃描其特征并根據特征拒絕進程打開,那么就可以實現一個簡單的防惡意程序,進程監控在防惡意程序中也是用的最多的。

PsSetCreateThreadNotifyRoutine

說完了PsSetCreateProcessNotifyRoutineEx回調的使用方式,LyShark將繼續帶大家看看線程監控如何實現,監控線程創建與監控進程差不多,檢測線程需要調用PsSetCreateThreadNotifyRoutine 創建回調函數,之后就可監控系統所有線程的創建,具體實現代碼如下。

#include <ntifs.h>// 兩個未公開函數導出
NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
NTKERNELAPI NTSTATUS PsLookupThreadByThreadId(HANDLE ThreadId, PETHREAD *Thread);// 繞過簽名檢查
BOOLEAN BypassCheckSign(PDRIVER_OBJECT pDriverObject)
{
#ifdef _WIN64typedef struct _KLDR_DATA_TABLE_ENTRY{LIST_ENTRY listEntry;ULONG64 __Undefined1;ULONG64 __Undefined2;ULONG64 __Undefined3;ULONG64 NonPagedDebugInfo;ULONG64 DllBase;ULONG64 EntryPoint;ULONG SizeOfImage;UNICODE_STRING path;UNICODE_STRING name;ULONG   Flags;USHORT  LoadCount;USHORT  __Undefined5;ULONG64 __Undefined6;ULONG   CheckSum;ULONG   __padding1;ULONG   TimeDateStamp;ULONG   __padding2;} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#elsetypedef struct _KLDR_DATA_TABLE_ENTRY{LIST_ENTRY listEntry;ULONG unknown1;ULONG unknown2;ULONG unknown3;ULONG unknown4;ULONG unknown5;ULONG unknown6;ULONG unknown7;UNICODE_STRING path;UNICODE_STRING name;ULONG   Flags;} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#endifPKLDR_DATA_TABLE_ENTRY pLdrData = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;pLdrData->Flags = pLdrData->Flags | 0x20;return TRUE;
}// 線程回調函數
VOID MyCreateThreadNotify(HANDLE ProcessId, HANDLE ThreadId, BOOLEAN CreateInfo)
{PEPROCESS eprocess = NULL;PETHREAD ethread = NULL;UCHAR *pWin32Address = NULL;// 通過此函數拿到程序的EPROCESS結構PsLookupProcessByProcessId(ProcessId, &eprocess);PsLookupThreadByThreadId(ThreadId, &ethread);if (CreateInfo){DbgPrint("[lyshark] 線程TID: %1d | 所屬進程名: %s | 進程PID: %1d \n", ThreadId, PsGetProcessImageFileName(eprocess), PsGetProcessId(eprocess));/*if (0 == _stricmp(PsGetProcessImageFileName(eprocess), "lyshark.exe")){DbgPrint("線程TID: %1d | 所屬進程名: %s | 進程PID: %1d \n", ThreadId, PsGetProcessImageFileName(eprocess), PsGetProcessId(eprocess));// dt _kthread// 尋找里面的 Win32StartAddress 并寫入retpWin32Address = *(UCHAR**)((UCHAR*)ethread + 0x1c8);if (MmIsAddressValid(pWin32Address)){*pWin32Address = 0xC3;}}*/}else{DbgPrint("[LyShark] %s 線程已退出...", ThreadId);}if (eprocess)ObDereferenceObject(eprocess);if (ethread)ObDereferenceObject(ethread);
}VOID UnDriver(PDRIVER_OBJECT driver)
{NTSTATUS status;// 注銷進程回調status = PsRemoveCreateThreadNotifyRoutine(MyCreateThreadNotify);
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{NTSTATUS status;DbgPrint("hello lyshark \n");// 繞過簽名檢查// LINKER_FLAGS=/INTEGRITYCHECKBypassCheckSign(Driver);// 創建線程回調// 參數1: 新線程ProcessID// 參數2: 新線程ThreadID// 參數3: 線程創建/退出標志status = PsSetCreateThreadNotifyRoutine(MyCreateThreadNotify);if (!NT_SUCCESS(status)){DbgPrint("創建線程回調錯誤");}Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;
}

運行后則可監控到系統總所有線程的創建與退出,效果如下所示:

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

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

相關文章

H3C路由器基本配置命令

1、system-view 進入系統視圖 2、sysname R1 配置路由器名字為R1 3、display clock 查看當前系統時間 4、clock datetime 00:00:00 2/26/2023 用戶模式下修改系統時間 配置控制臺密碼 Console&#xff1a; 1、user-interface aux0 在系統模式下進入圖接口 2、authentication-mo…

2023亞太賽c題完整思路數據 數學建模亞太

Question 1: Analyze the main factors that affect the development of new energy electric vehicles in China, establish a mathematical model, and describe the impact of these factors on the development of new energy electric vehicles in China. 問題1:分析影響…

office 365企業版安裝教程

1.下載所需工具&#xff08;防火墻和防毒軟件記得關閉&#xff09; 下載鏈接&#xff1a;所需文件 2.安裝激活office 1.安裝 office tool plus 2.已安裝過office 先進行office的移除&#xff0c;再進行未安裝office的步驟進行 3.未安裝過office 1.設置部署 按照以下來進行安…

Linux命令(130)之hwclock

linux命令之hwclock 1.hwclock介紹 linux命令hwclock是用來顯示硬件時鐘 2.hwclock用法 hwclock [參數] hwclock參數 參數說明-s讓系統時間同步硬件時間-w讓硬件時間同步系統時間 3.實例 3.1.同步服務器時鐘時間 命令&#xff1a; ntpdate pool.ntp.org [rootrhel77 ~…

【vin 國標正則校驗】

規則一 var checkVINfunction(VIN){if(typeof(VIN)!string) return false;if(VIN.length!17) return false;VINVIN.toUpperCase();RE/^[A-HJ-NPR-Z\d]{8}[X\d][A-HJ-NPR-Z\d]{3}\d{5}$/if(!RE.test(VIN)) return false;let cOT{0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:1,B…

360:流氓or保家衛國的勇士?

你曾用過360嗎&#xff0c;這個在國內名聲不好的殺毒軟件&#xff0c;卻是令國外黑客聞風喪膽的存在。 首先&#xff0c;在電腦病毒剛興起的年代&#xff0c;殺毒軟件是要收費的&#xff0c;當時盛行的瑞星和金山就是采用的付費模式&#xff0c;而就在2006年&#xff0c;奇虎…

C/C++通過位操作實現2個uint32_t合并為uint64_t

#include <iostream> using namespace std;int main() {uint32_t a 10;uint32_t b 600;//先將uint32_t的a轉為uint64_t&#xff0c;此時a前面32位都是0&#xff0c;然后左移32位&#xff0c;此時右32位為0&#xff0c;最后加上uint32_t類型的b&#xff0c;填充右32位的…

解決Activiti5.22流程圖部署在Windows上正常,但在linux上部署后出現中文變方塊的問題

總結/朱季謙 樓主最近在做公司的工作流平臺&#xff0c;發現一個很無語的事情&#xff0c;Activiti5.22的流程圖在Windows環境上部署&#xff0c;是可以正常查看的&#xff0c;但發布到公司的Linux服務器上后&#xff0c;在上面進行流程圖在線部署時&#xff0c;發現中文都變成…

2023亞太杯數學建模C題思路代碼 - 我國新能源電動汽車的發展趨勢

1 賽題 問題C 我國新能源電動汽車的發展趨勢 新能源汽車是指以先進技術原理、新技術、新結構的非常規汽車燃料為動力來源( 非常規汽車燃料指汽油、柴油以外的燃料&#xff09;&#xff0c;將先進技術進行汽車動力控制和驅動相結 合的汽車。新能源汽車主要包括四種類型&#x…

一套開源、強大且美觀的WPF UI控件庫 - HandyControl

前言 今天給大家推薦一套開源、強大且美觀的WPF UI控件庫&#xff1a;HandyControl。 WPF介紹 WPF 是一個強大的桌面應用程序框架&#xff0c;用于構建具有豐富用戶界面的 Windows 應用。它提供了靈活的布局、數據綁定、樣式和模板、動畫效果等功能&#xff0c;讓開發者可以創…

關于Redis底層的兩個問題

1. 為什么Redis不共享包含字符串的對象&#xff1f; 當服務器考慮將一個共享對象設置為鍵的值對象時&#xff0c;程序首先需要檢查給定的共享對象和鍵想要創建的目標對象是否完全相同&#xff0c;只有在共享對象和目標對象完全相同的情況下&#xff0c;程序才會將共享對象用作…

SOEM主站開發篇(3):為APP程序添加命令

0 工具準備 1.SOEM-1.4.0源碼(官網:http://openethercatsociety.github.io/) 2.Linux開發板(本文為正點原子I.MX6U ALPHA開發板) 3.交叉編譯工具(arm-linux-gnueabihf-gcc) 4.cmake(版本不得低于3.9,本文為3.9.2) 5.Ubuntu 16.04(用于編譯生成Linux開發板的可執行文…

【追求卓越06】算法--遞歸

引導 遞歸算法算是我們比較常用的一種算法。但是想用好并不簡單。本章我不再介紹簡單的概念&#xff0c;主要講解遞歸算法的優缺點和如何用遞歸寫代碼。 個人愛好 其實相對于使用while循環&#xff0c;我更喜歡使用遞歸算法。為什么呢&#xff1f; 使用遞歸算法代碼往往會變…

Java語言中的控制流程

控制流程是編程中的重要概念之一&#xff0c;它允許程序根據條件執行不同的代碼塊或重復執行特定的代碼塊。在Java中&#xff0c;控制流程由條件語句和循環語句組成。本文將詳細介紹Java中的條件語句&#xff08;if語句和switch語句&#xff09;和循環語句&#xff08;for循環、…

MySQL用戶與權限管理

快捷查看指令 ctrlf 進行搜索會直接定位到需要的知識點和命令講解&#xff08;如有不正確的地方歡迎各位小伙伴在評論區提意見&#xff0c;博主會及時修改&#xff09; MySQL用戶與權限管理 登錄 #本地登錄 mysql -uroot -p123456#遠程登錄 #客戶端語法&#xff1a;mysql -…

聚觀早報 |快手Q3營收;拼多多殺入大模型;Redmi K70E開啟預約

【聚觀365】11月23日消息 快手Q3營收 拼多多殺入大模型 Redmi K70E開啟預約 華為nova 12系列或下周發布 亞馬遜啟動“AI就緒”新計劃 快手Q3營收 財報顯示&#xff0c;快手第三季度營收279億元&#xff0c;同比增長20.8%&#xff1b;期內盈利21.8億元&#xff0c;去年同期…

貓罐頭多久喂一次?好用的貓罐頭牌子推薦

貓愛吃貓罐頭&#xff0c;包含各種美味&#xff0c;提供營養和口感。但喂貓吃罐頭需技巧和耐心&#xff0c;以確保貓健康快樂成長。 作為一個從業寵物營養師7年的人&#xff0c;可以說對于貓咪的食物很有研究和貓罐頭品牌選購上&#xff0c;我有自己的見解。 一、貓罐頭多久喂…

shell之wc命令

shell之wc命令 Linux中的wc命令是一個用于統計給定文件中的字節數、字數和行數的工具。它也可以從標準輸入讀取數據并統計。 wc命令的語法為&#xff1a; wc [選項] 文件... 如果沒有給出文件名&#xff0c;則從標準輸入讀取。wc同時也給出所有指定文件的總統計數。wc命令的選…

40、Flink 的Apache Kafka connector(kafka source 和sink 說明及使用示例) 完整版

Flink 系列文章 1、Flink 部署、概念介紹、source、transformation、sink使用示例、四大基石介紹和示例等系列綜合文章鏈接 13、Flink 的table api與sql的基本概念、通用api介紹及入門示例 14、Flink 的table api與sql之數據類型: 內置數據類型以及它們的屬性 15、Flink 的ta…

循環神經網絡(RNN)實現股票預測

文章目錄 一、前言二、前期工作1. 設置GPU&#xff08;如果使用的是CPU可以忽略這步&#xff09;2. 導入數據 四、數據預處理1.歸一化2.設置測試集訓練集 五、構建模型六、激活模型七、訓練模型八、結果可視化1.繪制loss圖2.預測3.評估 一、前言 我的環境&#xff1a; 語言環…