1. 程式人生 > >遍歷核心驅動模組

遍歷核心驅動模組

PsLoadedModuleList是Windows載入的所有核心模組構成的連結串列的表頭,利用它可以列舉所有這些模組的資訊,下面是WRK中對PsLoadedModuleList的定義:LIST_ENTRY PsLoadedModuleList;

核心在載入驅動時,會為每一個驅動建立一個驅動物件(DRIVER_OBJECT),下面是驅動物件的資料結構:

typedef struct _DRIVER_OBJECT {

CSHORT Type;               

CSHORTSize;

PDEVICE_OBJECT DeviceObject;         //指向裝置物件,所有的裝置物件構成一個連結串列

ULONGFlags;                         //驅動程式標誌

PVOIDDriverStart;                   //驅動程式映像起始地址

ULONGDriverSize;                    //驅動程式映像大小

PVOIDDriverSection;                 //指向驅動程式映像的記憶體區物件

PDRIVER_EXTENSIONDriverExtension;   //指向驅動程式物件的擴充套件部分

UNICODE_STRINGDriverName;           //驅動程式名稱

PUNICODE_STRINGHardwareDatabase

;    //指向登錄檔中包含硬體資訊的路徑

PFAST_IO_DISPATCHFastIoDispatch;    //指向快速I/O的分發結構

PDRIVER_INITIALIZE DriverInit;       //驅動程式的初始化例程

PDRIVER_STARTIO DriverStartIo;       //驅動程式的啟動I/O例程

PDRIVER_UNLOADDriverUnload;         //驅動程式的解除安裝例程

PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT;

typedef

struct _DRIVER_OBJECT *PDRIVER_OBJECT;

DRIVER_OBJECT物件的DriverExtension成員指向的是驅動程式映像的記憶體區物件,它的結構KLDR_DATA_TABLE_ENTRY的定義是:

typedef struct_KLDR_DATA_TABLE_ENTRY {

LIST_ENTRYInLoadOrderLinks;

PVOIDExceptionTable;

ULONG ExceptionTableSize;

PVOIDGpValue;

PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;

PVOID DllBase;                           //指明瞭驅動的載入基址

PVOID EntryPoint;

ULONGSizeOfImage;

UNICODE_STRING FullDllName;              //指明瞭驅動模組檔案的全路徑

UNICODE_STRING BaseDllName;              //指明瞭驅動模組的名稱

ULONGFlags;

USHORTLoadCount;

USHORT__Unused5;

PVOIDSectionPointer;

ULONGCheckSum;

PVOID LoadedImports;

PVOIDPatchInformation;

} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;

這個結構體中的第一個成員InLoadOrderLinks是一個LIST_ENTRY的結構. 每個驅動模組都被加入到這個雙向連結串列中.我們只要遍歷這個雙向連結串列就能枚舉出所有的驅動模組,下面的DbgObjGetSysModuleInfo函式可以遍歷核心所有的驅動模組:

NTSTATUS DbgObjGetSysModuleInfo(PDRIVER_OBJECTlpDriverObject)

{

PKLDR_DATA_TABLE_ENTRY ModuleEntry =NULL;

PLIST_ENTRY PsLoadedModuleList =NULL;

PLIST_ENTRY ListEntry =NULL;

PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)lpDriverObject->DriverSection;

//系統模組連結串列的連結串列頭

PsLoadedModuleList =ldr->InLoadOrderLinks.Flink;

ListEntry =PsLoadedModuleList->Flink;

while (ListEntry != PsLoadedModuleList)

{

ModuleEntry =CONTAINING_RECORD(ListEntry,KLDR_DATA_TABLE_ENTRY,InLoadOrderLinks);

if (&ModuleEntry->BaseDllName.Buffer != 0){

DbgPrint("Nt Module Fileis %wZ\n",&ModuleEntry->BaseDllName);

}

//指向下一個連結串列

ListEntry =ListEntry->Flink;

}

returnSTATUS_SUCCESS;

}

下面的程式碼是將驅動的記憶體區物件的DllBase或FullDllName.buffer填為0,它可以簡單地繞過一些檢測:

PVOID pDllBase =NULL;

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)

{

((PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection)->DllBase = pDllBase;

KdPrint(("Ddvp-> Call DriverUnload \n"));

return;

}

VOID Reinitialize(PDRIVER_OBJECTDriverObject,PVOID Context,ULONGCount)

{

((PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection)->DllBase = NULL;//將DllBase填0

}

NTSTATUS DriverEntry(INPDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegPath)

{

NTSTATUSStatus =STATUS_SUCCESS;

pDllBase = ((PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection)->DllBase;

IoRegisterDriverReinitialization(DriverObject,Reinitialize,NULL);

((PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection)->FullDllName.Buffer = NULL;   //將FullDllName.Buffer填0

DriverObject->DriverUnload = &DriverUnload;

return STATUS_SUCCESS;

}

注:不能直接修改DllBase的值,否則會藍屏。必須使用函式IoRegisterDriverReinitialization的回撥函式來修改,下面是該函式的宣告:

VOID

IoRegisterDriverReinitialization(

INPDRIVER_OBJECT DriverObject,                           //指向驅動的驅動物件

INPDRIVER_REINITIALIZE DriverReinitializationRoutine,    //被呼叫的重初始化例程的地址

INPVOID Context      //指向傳遞給驅動程式的初始化例程上下文指標

)

如果要隱藏某個驅動,就要將它從PsLoadedModuleList這個雙向連結串列中去掉。

下圖是修改前Flink和Blink指標的指向情況


下圖是修改後Flink和Blink指標的指向情況


下面的函式通過修改雙向連結串列來實現驅動的隱藏。

VOID HideDriver(IN PDRIVER_OBJECTpDriverObject)

{

PLIST_ENTRY entry = &((PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection)->InLoadOrderLinks;

PKLDR_DATA_TABLE_ENTRYModuleEntry =CONTAINING_RECORD(entry,KLDR_DATA_TABLE_ENTRY,InLoadOrderLinks);

KdPrint(("隱藏驅動 %ws 成功!\n", ModuleEntry->BaseDllName.Buffer));

//通過RemoveEntryList函式修改連結串列的指標

RemoveEntryList(entry);

entry->Flink = entry;

entry->Blink = entry;

}

在Xuetr中還是可以檢測出來

如果想要隱藏的更隱蔽,還要從以下幾個方面進行處理:

一、從PsLoadedModuleList連結串列中斷開,此方法僅對ZwQuerySystemInformation(SystemModuleInformation)有效

二、從\Driver物件目錄刪除

三、從TypeList中刪除

四、抹PE映象

五、抹DriverObject