由于最近有个32位程序需要向64位系统移植,其中程序中使用了ZwQuerySystemInformation函数来枚举系统中的进程与线程信息,但是移植后的程序在Windows x64下工作不正常。现象是获取到的进程/线程信息混乱,不正确。通过查询WRK以及Win2k源码,将结构体中的成员进行了修改,最终编译出的程序可以正常显示。
由于ZwQuerySystemInformation属于Windows的未文档化函数,网络上可以搜索到的结构体都是基于Win32下逆向得到的,因此可能有些偏差。
最明显的问题就是HANDLE与ULONG的区别。在Windows下,HANDLE类型被定义为typedef HANDLE PVOID * 。在32位平台下,sizeof(HANDLE) == sizeof(ULONG) == 4,因此可能是当时逆向的人没有多想就把HANDLE类型写成了ULONG类型,这样写在32位平台下是不会出错的,但是到了64位平台下,HANDLE类型就变成了8字节,而ULONG类型在编译器中被定义为ULONG32类型即32位无符号整数,造成了结构体内成员偏移的偏差。
在Windows下,进程ID是HANDLE类型表示的,而不是ULONG类型。在平台移植的时候是需要注意的!因为太多人喜欢把进程ID用ULONG类型进行表示了
typedef struct _SYSTEM_THREADS
{ 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; HANDLE ProcessId; //Modify HANDLE InheritedFromProcessId;//Modify ULONG HandleCount; ULONG SessionId; ULONG_PTR PageDirectoryBase; VM_COUNTERS VmCounters; SIZE_T PrivatePageCount;//Add IO_COUNTERS IoCounters; //windows 2000 only struct _SYSTEM_THREADS Threads[1]; }SYSTEM_PROCESSES,*PSYSTEM_PROCESSES;