由于最近有个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;