tlhelp32.h主要是用于枚举系统中某个时刻的进程,线程,模块,堆。
系统中本身维护着进程链表,线程链表,模块链表和堆链表。而快照是这个模型的某个时候的复制品。
通过CreateToolhelp32Snapshot可以创建快照。通过快照,再利用Process32First和Process32Next。我们能够方便走访进程链表。同理可以走访其他链表。注意走访堆链表,使用HEAPLIST32,Heap32ListFirst(),Heap32ListNext()而非用HEAPENTRY32;
提供简洁的通用的遍历模型:
for(BOOL fOK=Process32First(..,..);fOK;fOK=Process32Next(..,..))
{...}
另外一个比较有趣的函数是:
BOOL WINAPI Toolhelp32ReadProcessMemory(
__in DWORD th32ProcessID,
__in LPCVOID lpBaseAddress,
__out LPVOID lpBuffer,
__in SIZE_T cbRead,
__out SIZE_T lpNumberOfBytesRead
);
此函数可以将进程中某个起始地址开始的内存复制到一块缓冲区中。通过这种方式,我们可以获得某个进程的一些头信息,例如PE文件的DOS头,文件头。
《windows核心编程》中通过读取PE的DOS头,得到文件头的偏移位置,然后通过读取文件头可以得到模块的首选基地址。详细请参考《Windows核心编程》相应代码。
The first bytes of a PE file begin with the traditional MS-DOS header, called an IMAGE_DOS_HEADER<%2
Toolhelp32ReadProcessMemory(dwProcessId, (PBYTE) pvModuleRemote + idh.e_lfanew, &inth, sizeof(inth), NULL); // Verify the NT image header if (inth.Signature == IMAGE_NT_SIGNATURE) { // This is valid NT header, get the image's preferred base address pvModulePreferredBaseAddr = (PVOID) inth.OptionalHeader.ImageBase; } return(pvModulePreferredBaseAddr);
其中有关IAMGE_DOS_HEADER中重要信息如下:
The first bytes of a PE file begin with the traditional MS-DOS header, called anIMAGE_DOS_HEADER. The only two values of any importance are e_magic and e_lfanew. The e_lfanew field contains the file offset of the PE header. The e_magic field (a WORD) needs to be set to the value 0x5A4D. There's a #define for this value, named IMAGE_DOS_SIGNATURE. In ASCII representation, 0x5A4D is MZ, the initials of Mark Zbikowski, one of the original architects of MS-DOS.