该程序利用系统Native api: NtQuerySystemInformation来获取系统进程列表及其相关信息,从该函数的名字就可以看出,其功能强大,不仅仅能查看系统进程,包括其他进程线程信息,内存页表信息,io读写信息,CPU缓存信息,基本上我们平时所用的任务管理器中的大部分功能就是依靠该函数来实现的.Native api 都位于NTDLL.DLL中,是用户层最底层的逻辑实现方式.
开发环境:VC6.0 + WinXp Sp2
首先,我们需要定义一些相关的结构体和常量:- #ifndef NTQUERY_H
- #define NTQUERY_H
- typedef unsigned long NTSTATUS;
- typedef unsigned long SYSTEM_INFORMATION_CLASS;
- #define NT_PROCESS_LIST 5
- #define BLOCK_SIZE 0x1000
- #define STATUS_SUCCESS 0
- #define STATUS_INFO_LEN_MISMATCH 0xC0000004
- typedef struct{
- USHORT Length;
- USHORT MaxLen;
- USHORT *Buffer;
- }UNICODE_STRING;
- typedef struct _SYSTEM_PROCESSES{
- ULONG NextEntryDelta; //构成结构序列的偏移量;
- ULONG ThreadCount; //线程数目;
- ULONG Reserved1[6];
- LARGE_INTEGER CreateTime; //创建时间;
- LARGE_INTEGER UserTime; //用户模式(Ring 3)的CPU时间;
- LARGE_INTEGER KernelTime; //内核模式(Ring 0)的CPU时间;
- UNICODE_STRING ProcessName; //进程名称;
- ULONG BasePriority; //进程优先权;
- ULONG ProcessId; //进程标识符;
- }SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;
- typedef NTSTATUS (__stdcall * NTQUERYSYSTEMINFORMATION)( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
- #endif
复制代码 关于NTQUERYSYSTEMINFORMATION的定义
typedef NTSTATUS (__stdcall *NTQUERYSYSTEMINFORMATION)
(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
在这里需要查看进程表的CLASS_INFO为5,在头文件中我定义为NT_PROCESS_LIST, 第二个参数为存放返回信息的地址,在此之前需要先为其申请一段内存.如果该段内存小了,则函数会返回STATUS_INFO_LEN_MISMATCH,在头文件中可以见到其值为0xC0000004.如果成果返回,则值为STATUS_SUCCESS即0.下面程序实现的代码:- #include <stdio.h>
- #include <windows.h>
- #include <tchar.h>
- #include "ntQuery.h"
- int _tmain(void)
- {
- size_t blocklen = 0;
- PSYSTEM_PROCESSES bufForProcessesInfo = NULL, bufNext = NULL;
- NTSTATUS ns = 0;
- DWORD dwPcount = 0;
- HANDLE hHeap;
- int i = 2;
- HMODULE hNtdll = LoadLibrary(TEXT("NTDLL.DLL"));
- if(hNtdll == NULL)
- {
- printf("LaodLibrary ntddl.dll error...\n");
- return -1;
- }
- NTQUERYSYSTEMINFORMATION NtQuerySystemInformation =
- (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, TEXT("NtQuerySystemInformation"));
- if(NtQuerySystemInformation == NULL)
- {
- printf("GetProcAddress error...\n");
- return -1;
- }
-
- hHeap = GetProcessHeap();
- if(hHeap == NULL)
- {
- printf("Get heap error...\n");
- FreeLibrary(hNtdll);
- return -1;
- }
- bufForProcessesInfo = (PSYSTEM_PROCESSES)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BLOCK_SIZE);
- if(bufForProcessesInfo == NULL)
- {
- printf("HeapAlloc error...\n");
- FreeLibrary(hNtdll);
- return -1;
- }
- bufNext = bufForProcessesInfo;
- ns = NtQuerySystemInformation(NT_PROCESS_LIST, bufForProcessesInfo, BLOCK_SIZE, NULL);
- while(ns == STATUS_INFO_LEN_MISMATCH)
- {
- bufNext = (PSYSTEM_PROCESSES)HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, bufNext, BLOCK_SIZE * i);
- if(bufForProcessesInfo == NULL)
- {
- printf("Relloc error..\n");
- HeapFree(hHeap, HEAP_ZERO_MEMORY, bufForProcessesInfo);
- FreeLibrary(hNtdll);
- return -1;
- }
- ns = NtQuerySystemInformation(NT_PROCESS_LIST, bufNext, BLOCK_SIZE * i, NULL);
- i++;
- }
-
- while(bufNext->NextEntryDelta != 0)
- {
- wprintf(L"PID:%.4d\tBasePriority:%.2d\t%s\n", bufNext->ProcessId, bufNext->BasePriority, bufNext->ProcessName.Buffer);
- bufNext = (PSYSTEM_PROCESSES)((BYTE*)bufNext + bufNext->NextEntryDelta);
- dwPcount ++;
- }
- _tprintf(TEXT("------------------------------------------------"\
- "\nAll %d processes running...\n"), dwPcount);
- HeapFree(hHeap, HEAP_ZERO_MEMORY, bufForProcessesInfo);
- FreeLibrary(hNtdll);
- Sleep(10000);
- return 0;
- }
复制代码 |