由於最近有需求寫windows平臺下的發外掛模塊,須要實現對進程的監控,其中一個線程須要匹配進程名,那麼問題來了,這就須要獲取全部進程名稱。
在用戶層ring3下,枚舉進程的方法主要有:
1.CreateToolhelp32Snapshot 經過快照枚舉,x86和x64,winxp-win10 都可獲取到進程名稱。
2.經過 Psapi.dll,LoadLibrary("PSAPI.DLL"),調用其EnumProcesses()枚舉進程,x86和x64,winxp-win10 都可獲取到進程名稱,可是這個方法會OpenProcess打開進程,在ring3層打開進程,很大機率遇到訪問權限問題,因此慎用。
3.經過Wtsapi32.dll, WTSOpenServer()和WTSEnumerateProcess()函數來枚舉進程,可是這個函數須要首先傳入NetBios名稱,並且要打開服務來執行,就怕遇到獲取不到NetBios名稱或者服務打開失敗的狀況,因此定時枚舉循環進程的話慎用。
4.就是最穩定也最經常使用的方法了,經過ntdll.dll 導出的ZwQuerySystemInformation實現進程枚舉。固然這是在ring3層,須要注意寬字符轉換ANSI, 建議使用這種方法。
以上都是ring3層,用戶層枚舉進程的方法。
但是咱們的遊戲保護,不能在用戶層,否則隨便一個SSDT表修改或者Hook jmp 跳轉,就能夠繞過,必須使用驅動來保護遊戲,不過驅動保護涉及到驅動簽名的問題,不過有國外的大牛寫了驅動僞造簽名的工具,咱們僞造微軟的驅動簽名,而後就能夠悄無聲息的保護遊戲了。
不廢話 vs2010 vc++ 驅動枚舉進程ios
DriverProtect.h c++
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endifwindows
/ SSDT表 /
typedef struct ServiceDescriptorEntry
{api
unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase;
}ServiceDescriptorEntry_t, *PServiceDescriptorEntry;ide
typedef struct _PROCESS_INFO
{函數
ULONG_PTR eprocess; ULONG pid; ULONG ppid; UNICODE_STRING pathName; UNICODE_STRING ImageFileName;
}PROCESSINFO,*PPROCESSINFO;工具
typedef struct _SYSTEM_THREADS
{spa
LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientID; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; ULONG Reserved; //Add
}SYSTEM_THREADS,*PSYSTEM_THREADS;線程
typedef struct _SYSTEM_PROCESSES
{調試
ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters;
} _SYSTEM_PROCESSES,*PSYSTEM_PROCESSES;
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;
DriverProtect.cpp
#include "ntddk.h"
#include "ntdef.h"
#include "DriverProtect.h"
#define SystemProcessesAndThreadsInformation 5
extern "C" NTSTATUS ZwQuerySystemInformation(
IN ULONG SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );
VOID UnLoadDriver(PDRIVER_OBJECT DriverObject)
{
KdPrint(("驅動成功卸載!"));
}
VOID EnmuProcess()
{
ULONG cbBuffer = 0x8000; PVOID pBuffer = NULL; NTSTATUS rc; LPWSTR pszProcessName; PSYSTEM_PROCESSES pInfo; do { pBuffer = ExAllocatePool (NonPagedPool, cbBuffer); if (pBuffer == NULL) { return; } rc = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL); if ( rc == STATUS_INFO_LENGTH_MISMATCH) //緩衝區不足 { ExFreePool(pBuffer); cbBuffer *= 2; } else if (!NT_SUCCESS(rc)) { ExFreePool(pBuffer); return; } }while (rc == STATUS_INFO_LENGTH_MISMATCH); pInfo = (PSYSTEM_PROCESSES)pBuffer; while (1) { pszProcessName = pInfo->ProcessName.Buffer; if (pszProcessName == NULL) { pszProcessName = L"NULL"; } if (pInfo->ProcessId == 0) { DbgPrint("PID %5d System Idle Process", pInfo->ProcessId); } else { DbgPrint("PID %5d %ws/r/n", pInfo->ProcessId, pInfo->ProcessName.Buffer); } if (pInfo->NextEntryDelta == 0) { break; } pInfo = (PSYSTEM_PROCESSES)(((PUCHAR)pInfo) + pInfo->NextEntryDelta); } ExFreePool(pBuffer);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = UnLoadDriver; EnmuProcess(); return STATUS_SUCCESS;
}
生成了驅動,咱們跑到虛擬機上,複製驅動文件和符號到虛擬機。
咱們使用的 visualDDK + windbg 經過虛擬機調試
內核映射
打開windbg , 而後遠程鏈接虛擬機。
若是windbg 顯示 Debuggee is running...,表示沒有斷點,內核是跑起來的,此時咱們加載剛纔生成的驅動,instdrv,加載,啓動
此時觀察windbg, DbgPrint打印信息就是枚舉驅動的pid和進程名
既然已經進入內核了,並且也獲取到進程名稱和PID了,此時操做內核和殺軟是在同一個級別,因此殺軟沒有任何提示的,固然你就能夠進行模塊枚舉或者hook 內存讀寫函數或者進程打開函數,而後保護你想保護的進程。