在筆者上一篇文章《驅動開發:內核注冊并監控物件回呼》介紹了如何運用ObRegisterCallbacks注冊行程與執行緒回呼,并通過該回呼實作了攔截指定進行運行的效果,本章LyShark將帶大家繼續探索一個新的回呼注冊函式,PsSetLoadImageNotifyRoutine常用于注冊LoadImage映像監視,當有模塊被系統加載時則可以第一時間獲取到加載模塊資訊,需要注意的是該回呼函式內無法進行攔截,如需要攔截則需寫入回傳指令這部分內容將在下一章進行講解,本章將主要實作對模塊的監視功能,
監視模塊加載與卸載需要費別使用兩個函式,這兩個函式的引數傳遞都是自己的回呼地址,
- PsSetLoadImageNotifyRoutine 設定回呼
- PsRemoveLoadImageNotifyRoutine 移除回呼
此處MyLySharkLoadImageNotifyRoutine回呼地址必須有三個引數傳遞組成,其中FullImageName代表完整路徑,ModuleStyle代表模塊型別,一般來說ModuleStyle=0表示加載SYS驅動,如果ModuleStyle=1則表示加載的是DLL,最后一個引數ImageInfo則是映像的詳細引數結構體,
VOID MyLySharkLoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ModuleStyle, PIMAGE_INFO ImageInfo)
那么如何實作監視映像加載呢,來看如下完整代碼片段,首先PsSetLoadImageNotifyRoutine注冊回呼,當有模塊被加載則自動執行MyLySharkLoadImageNotifyRoutine回呼函式,其內部首先判斷ModuleStyle得出是什么型別的模塊,然后再通過GetDriverEntryByImageBase拿到當前行程詳細引數并列印輸出,
// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#include <ntddk.h>
#include <ntimage.h>
// 未匯出函式宣告
PUCHAR PsGetProcessImageFileName(PEPROCESS pEProcess);
// 獲取到鏡像裝載基地址
PVOID GetDriverEntryByImageBase(PVOID ImageBase)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS64 pNTHeader;
PVOID pEntryPoint;
pDOSHeader = (PIMAGE_DOS_HEADER)ImageBase;
pNTHeader = (PIMAGE_NT_HEADERS64)((ULONG64)ImageBase + pDOSHeader->e_lfanew);
pEntryPoint = (PVOID)((ULONG64)ImageBase + pNTHeader->OptionalHeader.AddressOfEntryPoint);
return pEntryPoint;
}
// 獲取當前行程名
UCHAR* GetCurrentProcessName()
{
PEPROCESS pEProcess = PsGetCurrentProcess();
if (NULL != pEProcess)
{
UCHAR *lpszProcessName = PsGetProcessImageFileName(pEProcess);
if (NULL != lpszProcessName)
{
return lpszProcessName;
}
}
return NULL;
}
// 設定自己的回呼函式
VOID MyLySharkLoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ModuleStyle, PIMAGE_INFO ImageInfo)
{
PVOID pDrvEntry;
// MmIsAddress 驗證地址可用性
if (FullImageName != NULL && MmIsAddressValid(FullImageName))
{
// ModuleStyle為零表示加載sys
if (ModuleStyle == 0)
{
// 得到裝載主行程名
UCHAR *load_name = GetCurrentProcessName();
pDrvEntry = GetDriverEntryByImageBase(ImageInfo->ImageBase);
DbgPrint("[LyShark SYS加載] 模塊名稱:%wZ --> 裝載基址:%p --> 鏡像長度: %d --> 裝載主行程: %s \n", FullImageName, pDrvEntry, ImageInfo->ImageSize, load_name);
}
// ModuleStyle非零表示加載DLL
else
{
// 得到裝載主行程名
UCHAR *load_name = GetCurrentProcessName();
pDrvEntry = GetDriverEntryByImageBase(ImageInfo->ImageBase);
DbgPrint("[LyShark DLL加載] 模塊名稱:%wZ --> 裝載基址:%p --> 鏡像長度: %d --> 裝載主行程: %s \n", FullImageName, pDrvEntry, ImageInfo->ImageSize, load_name);
}
}
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
PsRemoveLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)MyLySharkLoadImageNotifyRoutine);
DbgPrint("[LyShark.com] 驅動卸載完成...");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark.com \n");
PsSetLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)MyLySharkLoadImageNotifyRoutine);
DbgPrint("[LyShark.com] 驅動加載完成...");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
運行這個驅動程式,則會輸出被加載的驅動詳細引數,

文章出處:https://www.cnblogs.com/LyShark/p/16818943.html
著作權宣告:本博客文章與代碼均為學習時整理的筆記,文章 [均為原創] 作品,轉載請 [添加出處] ,您添加出處是我創作的動力!
轉載文章請遵守《中華人民共和國著作權法》相關法律規定或遵守《署名CC BY-ND 4.0國際》規范,合理合規攜帶原創出處轉載,如果不攜帶文章出處,并惡意轉載多篇原創文章被本人發現,本人保留起訴權!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519210.html
標籤:其他
上一篇:JDK中自帶的JVM分析工具
下一篇:JDK中自帶的JVM分析工具
