【舊文章搬運】ZwQuerySystemInformation列舉進執行緒資訊
阿新 • • 發佈:2018-12-26
原文發表於百度空間,2008-10-15
==========================================================================
很古老的東西了,寫一寫,權當練手吧.
本來以為沒什麼難度,很科普很傻瓜的東西,但是寫的時候還是遇到一些問題,程序資訊正確,得到的執行緒資訊總是不正確,後來分析了一下,發現這個ntdll sdk中定義的程序資訊結構和執行緒資訊結構都有點問題,可能它是來自《Win2000 Native API》一書,不適用於Windows XP。後來參考WRK修正了一下。執行緒資訊結構也有問題,和WRK中的一樣,但是結果仍然不正確,簡單分析了一下,得出結構大小應為0x40,最終還是修正了一下,才有正確結果。
最終確定的程序結構如下:
typedef struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; LARGE_INTEGER Reserved1[3]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG SessionId; ULONG_PTR PageDirectoryBase; VM_COUNTERS VmCounters; ULONG PrivatePageCount;// add by achillis IO_COUNTERS IoCounters; SYSTEM_THREADS Threads[1]; } SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
執行緒資訊結構如下:
typedef struct _SYSTEM_THREADS{ LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitches; ULONG ThreadState; ULONG WaitReason; ULONG Reversed;//add by achillis } SYSTEM_THREAD_INFORMATION,*PSYSTEM_THREADS;
紅色部分是我增加的,也不知道到底對不對,但是目前為止在我的XP SP2上可以得到正確結果。
列舉程序和執行緒資訊的程式碼如下:
int ShowProcess(void) { NTSTATUS status; DWORD retlen,truelen; char *buf=NULL,*p=NULL; ANSI_STRING ansiStr; int cnt=0; PSYSTEM_PROCESSES pSysProcess; PSYSTEM_THREADS pSysThread; status=ZwQuerySystemInformation(SystemProcessInformation,NULL,0,&retlen); truelen=retlen; status=ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&buf,0,&retlen,MEM_COMMIT,PAGE_READWRITE); printf("Size of SYSTEM_THREAD:%d\n",sizeof(SYSTEM_THREADS)); p=buf; status=ZwQuerySystemInformation(SystemProcessInformation,buf,truelen,&retlen); do { cnt++; pSysProcess=(PSYSTEM_PROCESSES)buf; RtlUnicodeStringToAnsiString(&ansiStr,&pSysProcess->ProcessName,TRUE); printf("Name:%s\n",ansiStr.Buffer); RtlFreeAnsiString(&ansiStr); printf("ThreadCnt:%d\t",pSysProcess->ThreadCount); printf("Priority:%d\t",pSysProcess->BasePriority); printf("PID:%4d\t",pSysProcess->ProcessId); printf("PPID:%d\n",pSysProcess->InheritedFromProcessId); printf("HandleCnt:%d\n",pSysProcess->HandleCount); //在每一項SYSTEM_PROCESS結構的最後是一個接一個的SYSTEM_THREAD結構 //輸出每個執行緒的資訊 if (pSysProcess->ThreadCount&&pSysProcess->ProcessId) { DWORD i=0; pSysThread=pSysProcess->Threads; for (;i<pSysProcess->ThreadCount;i++) { printf("Thread[%d] StartAddr:0x%08x\t",i+1,pSysThread->StartAddress); printf("TID:%d\t",pSysThread->ClientId.UniqueThread); printf("SwitchCnt:%d\n",pSysThread->ContextSwitchCount); pSysThread++; } } //若NextEntryDelta為0,則表明已結束 if (pSysProcess->NextEntryDelta==0) { break; } buf=buf+pSysProcess->NextEntryDelta; printf("===============================================================\n"); }while (1); printf("Total:%d\n",cnt); status=ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&p,&truelen,MEM_RELEASE); return 0; }
寫到這兒又想起了經典的Hook ZwQuerySystemInfoamation隱藏程序,其實SYSTEM_PROCESS結構中的NextEntryDelta作為指向下一個結構的偏移量,其作用類似於指標,使整體構成了一個單鏈表,要隱藏就是從連結串列中刪除一個元素而已,簡單的資料結構知識,呵呵~