<<第二部分:调用ToolHelp API枚举本地系统进程>>
在第一部分提到的PSAPI函数只能枚举NT系统的进程,在Windows9x环境下我们可以通过调用ToolHelp API函数来达到枚举系统进程的目的。M$的Windows NT开发小组因为不喜欢ToolHelp函数,所以没有将这些函数添加给Windows NT,所以他们开发了自己的Process Status函数,就是第一部分提到的PSAPI了。但是后来M$已经将ToolHelp函数添加给了Windows 2000。ToolHelp共有12个函数,通过调用这些函数可以方面的取得本地系统进程的详细信息,以下这个简单的例子只调用了三个函数,获取我们所需要系统进程名字和进程ID。程序如下:
/**********************************************************************
Module:ps.c
说明:调用ToolHelp函数枚举本地系统进程名和ID,Only for 9x/2000
**********************************************************************/
int main()
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == (HANDLE)-1)
{
printf("/nCreateToolhelp32Snapshot() failed:%d",GetLastError());
return 1;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
printf("/nProcessName ProcessID");
if (Process32First(hProcessSnap, &pe32))
{
do
{
printf("/n%-20s%d",pe32.szExeFile,pe32.th32ProcessID);
}while (Process32Next(hProcessSnap, &pe32));
}
else
{
printf("/nProcess32Firstt() failed:%d",GetLastError());
}
CloseHandle (hProcessSnap);
return 0;
}
<<第三部分:调用NTDLL.DLL中未公开API枚举本地系统进程>>
第一部分和第二部分说的是调用MS公开的API来枚举系统进程,在NTDLL.DLL中其实有一个未公开API,也可以用来枚举系统进程。此方法是从别处看来的,我可没这本事自己发现哦,出处记不清楚了,好像是pwdump2 中的源代码中的一部分吧。
OK!那个未公开API就是NtQuerySystemInformation,使用方法如下:
////////////////////////////////////////////////////////////////////////////////
typedef unsigned long NTSTATUS;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
typedef long LONG;
typedef __int64 LONGLONG;
typedef struct {
USHORT Length;
USHORT MaxLen;
USHORT *Buffer;
} UNICODE_STRING;
struct process_info {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
ULONG BasePriority;
ULONG ProcessId;
};
typedef NTSTATUS (__stdcall *NtQuerySystemInformation1)(
IN ULONG SysInfoClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG RetLen
);
int main()
{
HINSTANCE hNtDll;
NtQuerySystemInformation1 NtQuerySystemInformation;
NTSTATUS rc;
ULONG ulNeed = 0;
void *buf = NULL;
size_t len = 0;
struct process_info *p ;
int done;
hNtDll = LoadLibrary ("NTDLL");
if (!hNtDll)
return 0;
NtQuerySystemInformation = (NtQuerySystemInformation1)GetProcAddress (hNtDll, "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
return 0;
do {
len += 0x1000;
buf = realloc (buf, len);
if (!buf)
return 0;
rc = NtQuerySystemInformation (5, buf, len, &ulNeed);
} while (rc == 0xc0000004); // STATUS_INFO_LE*_***MATCH
if (rc <0) {
free (buf);
return 0;
}
printf("/nProcessName ProcessID");
p = (struct process_info *)buf;
done = 0;
while (!done) {
if ((p->ProcessName.Buffer != 0))
{
printf("/n%-20S%*",*->*rocessName.Buffer,p->ProcessId);
}
done = p->NextEntryDelta == 0;
p = (struct process_info *)(((char *)p) + p->NextEntryDelta);
}
free (buf);
FreeLibrary (hNtDll);
return 0;
}
在第一部分提到的PSAPI函数只能枚举NT系统的进程,在Windows9x环境下我们可以通过调用ToolHelp API函数来达到枚举系统进程的目的。M$的Windows NT开发小组因为不喜欢ToolHelp函数,所以没有将这些函数添加给Windows NT,所以他们开发了自己的Process Status函数,就是第一部分提到的PSAPI了。但是后来M$已经将ToolHelp函数添加给了Windows 2000。ToolHelp共有12个函数,通过调用这些函数可以方面的取得本地系统进程的详细信息,以下这个简单的例子只调用了三个函数,获取我们所需要系统进程名字和进程ID。程序如下:
/**********************************************************************
Module:ps.c
说明:调用ToolHelp函数枚举本地系统进程名和ID,Only for 9x/2000
**********************************************************************/
int main()
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == (HANDLE)-1)
{
printf("/nCreateToolhelp32Snapshot() failed:%d",GetLastError());
return 1;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
printf("/nProcessName ProcessID");
if (Process32First(hProcessSnap, &pe32))
{
do
{
printf("/n%-20s%d",pe32.szExeFile,pe32.th32ProcessID);
}while (Process32Next(hProcessSnap, &pe32));
}
else
{
printf("/nProcess32Firstt() failed:%d",GetLastError());
}
CloseHandle (hProcessSnap);
return 0;
}
<<第三部分:调用NTDLL.DLL中未公开API枚举本地系统进程>>
第一部分和第二部分说的是调用MS公开的API来枚举系统进程,在NTDLL.DLL中其实有一个未公开API,也可以用来枚举系统进程。此方法是从别处看来的,我可没这本事自己发现哦,出处记不清楚了,好像是pwdump2 中的源代码中的一部分吧。
OK!那个未公开API就是NtQuerySystemInformation,使用方法如下:
////////////////////////////////////////////////////////////////////////////////
typedef unsigned long NTSTATUS;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
typedef long LONG;
typedef __int64 LONGLONG;
typedef struct {
USHORT Length;
USHORT MaxLen;
USHORT *Buffer;
} UNICODE_STRING;
struct process_info {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
ULONG BasePriority;
ULONG ProcessId;
};
typedef NTSTATUS (__stdcall *NtQuerySystemInformation1)(
IN ULONG SysInfoClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG RetLen
);
int main()
{
HINSTANCE hNtDll;
NtQuerySystemInformation1 NtQuerySystemInformation;
NTSTATUS rc;
ULONG ulNeed = 0;
void *buf = NULL;
size_t len = 0;
struct process_info *p ;
int done;
hNtDll = LoadLibrary ("NTDLL");
if (!hNtDll)
return 0;
NtQuerySystemInformation = (NtQuerySystemInformation1)GetProcAddress (hNtDll, "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
return 0;
do {
len += 0x1000;
buf = realloc (buf, len);
if (!buf)
return 0;
rc = NtQuerySystemInformation (5, buf, len, &ulNeed);
} while (rc == 0xc0000004); // STATUS_INFO_LE*_***MATCH
if (rc <0) {
free (buf);
return 0;
}
printf("/nProcessName ProcessID");
p = (struct process_info *)buf;
done = 0;
while (!done) {
if ((p->ProcessName.Buffer != 0))
{
printf("/n%-20S%*",*->*rocessName.Buffer,p->ProcessId);
}
done = p->NextEntryDelta == 0;
p = (struct process_info *)(((char *)p) + p->NextEntryDelta);
}
free (buf);
FreeLibrary (hNtDll);
return 0;
}