Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html
驅動對象(驅動隱藏技術)
1._DRIVER_OBJECT結構體
2. xx.sys中的INIT節區
3. DriverObject.DriverSection節區
4. 遍歷全部驅動
5. 驅動隱藏
6. 更進一步的驅動隱藏技巧
7. 總結
1._DRIVER_OBJECT結構體
2. xx.sys中的INIT節區
DriverObject.DriverInit 其就啟動該節區中的代碼,但是該節區啟動之后就會自動刪除。
在調試時應該注意,使用IDA查看在節區的函數但是無法動態調試。
3. DriverObject.DriverSection節區
該節區指向 _LDR_DATA_ENTRY_TABLE結構體,保存着該驅動的有關信息。
同時其存在三個雙向鏈表,可以用其來遍歷全部驅動。
//0x50 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x8
struct _LIST_ENTRY InInitializationOrderLinks; //0x10
VOID* DllBase; //0x18
VOID* EntryPoint; //0x1c
ULONG SizeOfImage; //0x20
struct _UNICODE_STRING FullDllName; //0x24
struct _UNICODE_STRING BaseDllName; //0x2c
ULONG Flags; //0x34
USHORT LoadCount; //0x38
USHORT TlsIndex; //0x3a
union
{
struct _LIST_ENTRY HashLinks; //0x3c
struct
{
VOID* SectionPointer; //0x3c
ULONG CheckSum; //0x40
};
};
union
{
ULONG TimeDateStamp; //0x44
VOID* LoadedImports; //0x44
};
VOID* EntryPointActivationContext; //0x48
VOID* PatchInformation; //0x4c
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
4. 遍歷全部驅動
#include <ntddk.h> #include <intrin.h> #include <ntstrsafe.h> //0x50 bytes (sizeof) typedef struct _LDR_DATA_TABLE_ENTRY { struct _LIST_ENTRY InLoadOrderLinks; //0x0 struct _LIST_ENTRY InMemoryOrderLinks; //0x8 struct _LIST_ENTRY InInitializationOrderLinks; //0x10 VOID* DllBase; //0x18 VOID* EntryPoint; //0x1c ULONG SizeOfImage; //0x20 struct _UNICODE_STRING FullDllName; //0x24 struct _UNICODE_STRING BaseDllName; //0x2c ULONG Flags; //0x34 USHORT LoadCount; //0x38 USHORT TlsIndex; //0x3a union { struct _LIST_ENTRY HashLinks; //0x3c struct { VOID* SectionPointer; //0x3c ULONG CheckSum; //0x40 }; }; union { ULONG TimeDateStamp; //0x44 VOID* LoadedImports; //0x44 }; VOID* EntryPointActivationContext; //0x48 VOID* PatchInformation; //0x4c }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY; VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) { DbgPrint("%s\r\n", "驅動卸載成功"); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) { DbgPrint("地址:%x", pDriver); pDriver->DriverUnload = DriverUnload; PLDR_DATA_TABLE_ENTRY pList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection; PLDR_DATA_TABLE_ENTRY pNext = pList->InLoadOrderLinks.Flink; DbgPrint("%wZ\n", &pList->BaseDllName); // 輸出本地驅動名字 // 雙向鏈表,如果到結尾則返回頭部 while (pList != pNext) { DbgPrint("%wZ\n", &pNext->BaseDllName); pNext = pNext->InLoadOrderLinks.Flink; // 輸出下一個驅動名字 } return STATUS_SUCCESS; }
5. 驅動隱藏
我們采用最基本的斷鏈來測試一下:
PLDR_DATA_TABLE_ENTRY pList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
RemoveEntryList((PLIST_ENTRY)pList);
如果我們采用上面那種遍歷方法自然遍歷不到,但是如果使用PcHunter等工具來查看,則明顯無法刪除干凈。
6. 更進一步的驅動隱藏技巧(代碼2-4)
我們下面使用MiProcessLoaderEntry內核函數來實現驅動隱藏效果。
1)在IDA中定位其特征碼
2)特征碼搜索在內核函數中
3)調用內核函數將該鏈表從節區中移除
調用內核函數移除之后,我門將該節區的Section指向下一個,之后再用PcHunter掃描其結果如下。
4)對於節區屬性更進一步清空
上面那步之后,我們還可以發現其有關屬性,我們下面對其屬性進一步清空。
5)在驅動卸載時恢復
我們在發現卸載驅動時,恢復Section節區,然后調用函數在掛在鏈表中,讓系統自動卸載。
7. 總結
首先,我們發現其並沒有完全成功繞過PcHunter,我們之后會利用內存加載,句柄表等知識進一步完善驅動隱藏技術。
對於驅動隱藏,要知道我們分析某些程序時是反PcHunter,其會不斷掃描鏈表發現有PcHunter等工具,然后結束自身進程(另外還有OD等),我們可以利用該策略隱藏自己的PcHunter。