本人在校大学生一枚,技术不太行,各位师傅将就看看。
tlhelp32.h
头文件中,提供了CreateToolhelp32Snapshot
API,可以获取获取指定进程以及这些进程使用的堆、模块和线程的快照。
在进程快照信息中,包含着进程导入模块的信息。因此,我们可以有如下实现思路:
按照微软官方的建议,使用EnumProcessModules
函数枚举进程模块可以确定哪些进程加载了特定的DLL。这个函数在psapi.h
中。以下是微软给出的实例代码。
PEB +0x00c
成员Ldr
指向_PEB_LDR_DATA
结构,此结构的第三成员InMemoryOrderModuleList
包含进程的已加载模块的双向链表的头部。列表中的每个项目都是指向LDR_DATA_TABLE_ENTRY
结构的指针。
因此,这种方法的思路如下:
贴一个大佬的获取PEB代码(原谅我实在忘了在哪找到的,知道的朋友请留言一下)
对目标进程进行DLL注入,Hook GetMoudleHandle
、Loadlibary
等函数,让目标进程自己调用,进行IPC通信。
PEB (winternl.h) - Win32 应用 |Microsoft 学习
PEB_LDR_DATA (winternl.h) - Win32 应用 |Microsoft 学习
PEB及LDR链 - bokernb - 博客园 (cnblogs.com)
远程获取进程DLL模块地址_获取进程模块-CSDN博客
CreateToolhelp32Snapshot 函数 (tlhelp32.h) - Win32 apps | Microsoft Learn
枚举进程的所有模块 - Win32 apps | Microsoft Learn
HANDLE
CreateToolhelp32Snapshot(
[in]
DWORD
dwFlags,
[in]
DWORD
th32ProcessID
);
HANDLE
CreateToolhelp32Snapshot(
[in]
DWORD
dwFlags,
[in]
DWORD
th32ProcessID
);
#include <iostream>
#include <Windows.h>
#include <Tlhelp32.h>
#include <tchar.h>
#include <string>
#include <stdio.h>
HMODULE
GetProcessModuleHandle(
DWORD
pid, CONST
TCHAR
* moduleName) {
MODULEENTRY32 moduleEntry;
HANDLE
handle = NULL;
moudleInfoHandle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if
(!moudleInfoHandle) {
CloseHandle(moudleInfoHandle);
return
NULL;
}
ZeroMemory(&moduleEntry,
sizeof
(MODULEENTRY32));
moduleEntry.dwSize =
sizeof
(MODULEENTRY32);
if
(!Module32First(moudleInfoHandle, &moduleEntry)) {
CloseHandle(moudleInfoHandle);
return
NULL;
}
do
{
if
(_tcscmp(moduleEntry.szModule, moduleName) == 0) {
CloseHandle(moudleInfoHandle);
return
moduleEntry.hModule;
}
}
while
(Module32Next(moudleInfoHandle, &moduleEntry));
CloseHandle(moudleInfoHandle);
return
0;
}
int
main() {
HANDLE
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process = {
sizeof
(PROCESSENTRY32)
};
while
(Process32Next(hProcessSnap, &process)) {
std::string s_szExeFile = process.szExeFile;
if
(s_szExeFile ==
"xxx.exe"
) {
HANDLE
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
if
(hProcess)
{
HMODULE
hMod = GetProcessModuleHandle(process.th32ProcessID,
"xxx.dll"
);
if
(hMod)
{
auto
fnAddress = GetProcAddress(hMod,
"xxFunc"
);
std::cout << fnAddress <<
" "
<< GetLastError();
}
}
}
}
}
#include <iostream>
#include <Windows.h>
#include <Tlhelp32.h>
#include <tchar.h>
#include <string>
#include <stdio.h>
HMODULE
GetProcessModuleHandle(
DWORD
pid, CONST
TCHAR
* moduleName) {
MODULEENTRY32 moduleEntry;
HANDLE
handle = NULL;
moudleInfoHandle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if
(!moudleInfoHandle) {
CloseHandle(moudleInfoHandle);
return
NULL;
}
ZeroMemory(&moduleEntry,
sizeof
(MODULEENTRY32));
moduleEntry.dwSize =
sizeof
(MODULEENTRY32);
if
(!Module32First(moudleInfoHandle, &moduleEntry)) {
CloseHandle(moudleInfoHandle);
return
NULL;
}
do
{
if
(_tcscmp(moduleEntry.szModule, moduleName) == 0) {
CloseHandle(moudleInfoHandle);
return
moduleEntry.hModule;
}
}
while
(Module32Next(moudleInfoHandle, &moduleEntry));
CloseHandle(moudleInfoHandle);
return
0;
}
int
main() {
HANDLE
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process = {
sizeof
(PROCESSENTRY32)
};
while
(Process32Next(hProcessSnap, &process)) {
std::string s_szExeFile = process.szExeFile;
if
(s_szExeFile ==
"xxx.exe"
) {
HANDLE
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
if
(hProcess)
{
HMODULE
hMod = GetProcessModuleHandle(process.th32ProcessID,
"xxx.dll"
);
if
(hMod)
{
auto
fnAddress = GetProcAddress(hMod,
"xxFunc"
);
std::cout << fnAddress <<
" "
<< GetLastError();
}
}
}
}
}
BOOL
EnumProcessModules(
[in]
HANDLE
hProcess,
[out]
HMODULE
*lphModule,
[in]
DWORD
cb,
[out]
LPDWORD
lpcbNeeded
);
BOOL
EnumProcessModules(
[in]
HANDLE
hProcess,
[out]
HMODULE
*lphModule,
[in]
DWORD
cb,
[out]
LPDWORD
lpcbNeeded
);
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
int
PrintModules(
DWORD
processID )
{
HMODULE
hMods[1024];
HANDLE
hProcess;
DWORD
cbNeeded;
unsigned
int
i;
printf
(
"\n进程 ID:%u\n"
, processID );
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if
(NULL == hProcess)
return
1;
if
( EnumProcessModules(hProcess, hMods,
sizeof
(hMods), &cbNeeded))
{
for
( i = 0; i < (cbNeeded /
sizeof
(
HMODULE
)); i++ )
{
TCHAR
szModName[MAX_PATH];
if
( GetModuleFileNameEx( hProcess, hMods[i], szModName,
sizeof
(szModName) /
sizeof
(
TCHAR
)))
{
_tprintf( TEXT(
"\t%s (0x%08X)\n"
), szModName, hMods[i] );
}
}
}
CloseHandle( hProcess );
return
0;
}
int
main(
void
)
{
DWORD
aProcesses[1024];
DWORD
cbNeeded;
DWORD
cProcesses;
unsigned
int
i;
if
( !EnumProcesses( aProcesses,
sizeof
(aProcesses), &cbNeeded ) )
return
1;
cProcesses = cbNeeded /
sizeof
(
DWORD
);
for
( i = 0; i < cProcesses; i++ )
{
PrintModules( aProcesses[i] );
}
return
0;
}
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
int
PrintModules(
DWORD
processID )
{
HMODULE
hMods[1024];
HANDLE
hProcess;
DWORD
cbNeeded;
unsigned
int
i;
printf
(
"\n进程 ID:%u\n"
, processID );
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if
(NULL == hProcess)
return
1;
if
( EnumProcessModules(hProcess, hMods,
sizeof
(hMods), &cbNeeded))
{
for
( i = 0; i < (cbNeeded /
sizeof
(
HMODULE
)); i++ )
{
TCHAR
szModName[MAX_PATH];
if
( GetModuleFileNameEx( hProcess, hMods[i], szModName,
sizeof
(szModName) /
sizeof
(
TCHAR
)))
{
_tprintf( TEXT(
"\t%s (0x%08X)\n"
), szModName, hMods[i] );
}
}
}
CloseHandle( hProcess );
return
0;
}
int
main(
void
)
{
DWORD
aProcesses[1024];
DWORD
cbNeeded;
DWORD
cProcesses;
unsigned
int
i;
if
( !EnumProcesses( aProcesses,
sizeof
(aProcesses), &cbNeeded ) )
return
1;
cProcesses = cbNeeded /
sizeof
(
DWORD
);
for
( i = 0; i < cProcesses; i++ )
{
PrintModules( aProcesses[i] );
}
return
0;
}
typedef
struct
_LDR_DATA_TABLE_ENTRY {
PVOID
Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID
Reserved2[2];
PVOID
DllBase;
PVOID
EntryPoint;
PVOID
Reserved3;
UNICODE_STRING FullDllName;
BYTE
Reserved4[8];
PVOID
Reserved5[3];
union
{
ULONG
CheckSum;
PVOID
Reserved6;
};
ULONG
TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef
struct
_LDR_DATA_TABLE_ENTRY {
PVOID
Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID
Reserved2[2];
PVOID
DllBase;
PVOID
EntryPoint;
PVOID
Reserved3;
UNICODE_STRING FullDllName;
BYTE
Reserved4[8];
PVOID
Reserved5[3];
union
{
ULONG
CheckSum;
PVOID
Reserved6;
};
ULONG
TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <subauth.h>
#pragma region 依赖
#define NT_SUCCESS(x) ((x) >= 0)
#define ProcessBasicInformation 0
typedef
NTSTATUS(WINAPI *pfnNtWow64QueryInformationProcess64)
(
HANDLE
ProcessHandle,
UINT32
ProcessInformationClass,
PVOID
ProcessInformation,
UINT32
ProcessInformationLength,
UINT32
* ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtWow64ReadVirtualMemory64)
(
HANDLE
ProcessHandle, PVOID64 BaseAddress,
PVOID
BufferData,
UINT64
BufferLength,
PUINT64
ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtQueryInformationProcess)
(
HANDLE
ProcessHandle,
ULONG
ProcessInformationClass,
PVOID
ProcessInformation,
UINT32
ProcessInformationLength,
UINT32
* ReturnLength);
template
<
typename
T>
struct
_UNICODE_STRING_T
{
WORD
Length;
WORD
MaximumLength;
T Buffer;
};
template
<
typename
T>
struct
_LIST_ENTRY_T
{
T Flink;
T Blink;
};
template
<
typename
T,
typename
NGF,
int
A>
struct
_PEB_T
{
typedef
T type;
union
{
struct
{
BYTE
InheritedAddressSpace;
BYTE
ReadImageFileExecOptions;
BYTE
BeingDebugged;
BYTE
BitField;
};
T dummy01;
};
T Mutant;
T ImageBaseAddress;
T Ldr;
T ProcessParameters;
T SubSystemData;
T ProcessHeap;
T FastPebLock;
T AtlThunkSListPtr;
T IFEOKey;
T CrossProcessFlags;
T UserSharedInfoPtr;
DWORD
SystemReserved;
DWORD
AtlThunkSListPtr32;
T ApiSetMap;
T TlsExpansionCounter;
T TlsBitmap;
DWORD
TlsBitmapBits[2];
T ReadOnlySharedMemoryBase;
T HotpatchInformation;
T ReadOnlyStaticServerData;
T AnsiCodePageData;
T OemCodePageData;
T UnicodeCaseTableData;
DWORD
NumberOfProcessors;
union
{
DWORD
NtGlobalFlag;
NGF dummy02;
};
LARGE_INTEGER CriticalSectionTimeout;
T HeapSegmentReserve;
T HeapSegmentCommit;
T HeapDeCommitTotalFreeThreshold;
T HeapDeCommitFreeBlockThreshold;
DWORD
NumberOfHeaps;
DWORD
MaximumNumberOfHeaps;
T ProcessHeaps;
T GdiSharedHandleTable;
T ProcessStarterHelper;
T GdiDCAttributeList;
T LoaderLock;
DWORD
OSMajorVersion;
DWORD
OSMinorVersion;
WORD
OSBuildNumber;
WORD
OSCSDVersion;
DWORD
OSPlatformId;
DWORD
ImageSubsystem;
DWORD
ImageSubsystemMajorVersion;
T ImageSubsystemMinorVersion;
T ActiveProcessAffinityMask;
T GdiHandleBuffer[A];
T PostProcessInitRoutine;
T TlsExpansionBitmap;
DWORD
TlsExpansionBitmapBits[32];
T SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
T pShimData;
T AppCompatInfo;
_UNICODE_STRING_T<T> CSDVersion;
T ActivationContextData;
T ProcessAssemblyStorageMap;
T SystemDefaultActivationContextData;
T SystemAssemblyStorageMap;
T MinimumStackCommit;
T FlsCallback;
_LIST_ENTRY_T<T> FlsListHead;
T FlsBitmap;
DWORD
FlsBitmapBits[4];
T FlsHighIndex;
T WerRegistrationData;
T WerShipAssertPtr;
T pContextData;
T pImageHeaderHash;
T TracingFlags;
T CsrServerReadOnlySharedMemoryBase;
};
typedef
_PEB_T<
DWORD
,
DWORD64
, 34> _PEB32;
typedef
_PEB_T<
DWORD64
,
DWORD
, 30> _PEB64;
typedef
struct
_STRING_32
{
WORD
Length;
WORD
MaximumLength;
UINT32
Buffer;
} STRING32, *PSTRING32;
typedef
struct
_STRING_64
{
WORD
Length;
WORD
MaximumLength;
UINT64
Buffer;
} STRING64, *PSTRING64;
typedef
struct
_RTL_DRIVE_LETTER_CURDIR_32
{
WORD
Flags;
WORD
Length;
ULONG
TimeStamp;
STRING32 DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
typedef
struct
_RTL_DRIVE_LETTER_CURDIR_64
{
WORD
Flags;
WORD
Length;
ULONG
TimeStamp;
STRING64 DosPath;
} RTL_DRIVE_LETTER_CURDIR64, *PRTL_DRIVE_LETTER_CURDIR64;
typedef
struct
_UNICODE_STRING_32
{
WORD
Length;
WORD
MaximumLength;
UINT32
Buffer;
} UNICODE_STRING32, *PUNICODE_STRING32;
typedef
struct
_UNICODE_STRING_64
{
WORD
Length;
WORD
MaximumLength;
UINT64
Buffer;
} UNICODE_STRING64, *PUNICODE_STRING64;
typedef
struct
_CURDIR_32
{
UNICODE_STRING32 DosPath;
UINT32
Handle;
} CURDIR32, *PCURDIR32;
typedef
struct
_RTL_USER_PROCESS_PARAMETERS_32
{
ULONG
MaximumLength;
ULONG
Length;
ULONG
Flags;
ULONG
DebugFlags;
UINT32
ConsoleHandle;
ULONG
ConsoleFlags;
UINT32
StandardInput;
UINT32
StandardOutput;
UINT32
StandardError;
CURDIR32 CurrentDirectory;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
UINT32
Environment;
ULONG
StartingX;
ULONG
StartingY;
ULONG
CountX;
ULONG
CountY;
ULONG
CountCharsX;
ULONG
CountCharsY;
ULONG
FillAttribute;
ULONG
WindowFlags;
ULONG
ShowWindowFlags;
UNICODE_STRING32 WindowTitle;
UNICODE_STRING32 DesktopInfo;
UNICODE_STRING32 ShellInfo;
UNICODE_STRING32 RuntimeData;
RTL_DRIVE_LETTER_CURDIR32 CurrentDirectores[32];
ULONG
EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
typedef
struct
_CURDIR_64
{
UNICODE_STRING64 DosPath;
UINT64
Handle;
} CURDIR64, *PCURDIR64;
typedef
struct
_RTL_USER_PROCESS_PARAMETERS_64
{
ULONG
MaximumLength;
ULONG
Length;
ULONG
Flags;
ULONG
DebugFlags;
UINT64
ConsoleHandle;
ULONG
ConsoleFlags;
UINT64
StandardInput;
UINT64
StandardOutput;
UINT64
StandardError;
CURDIR64 CurrentDirectory;
UNICODE_STRING64 DllPath;
UNICODE_STRING64 ImagePathName;
UNICODE_STRING64 CommandLine;
UINT64
Environment;
ULONG
StartingX;
ULONG
StartingY;
ULONG
CountX;
ULONG
CountY;
ULONG
CountCharsX;
ULONG
CountCharsY;
ULONG
FillAttribute;
ULONG
WindowFlags;
ULONG
ShowWindowFlags;
UNICODE_STRING64 WindowTitle;
UNICODE_STRING64 DesktopInfo;
UNICODE_STRING64 ShellInfo;
UNICODE_STRING64 RuntimeData;
RTL_DRIVE_LETTER_CURDIR64 CurrentDirectores[32];
ULONG
EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64;
typedef
struct
_PROCESS_BASIC_INFORMATION64 {
NTSTATUS ExitStatus;
UINT32
Reserved0;
UINT64
PebBaseAddress;
UINT64
AffinityMask;
UINT32
BasePriority;
UINT32
Reserved1;
UINT64
UniqueProcessId;
UINT64
InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION64;
typedef
struct
_PROCESS_BASIC_INFORMATION32 {
NTSTATUS ExitStatus;
UINT32
PebBaseAddress;
UINT32
AffinityMask;
UINT32
BasePriority;
UINT32
UniqueProcessId;
UINT32
InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION32;
#pragma endregion
int
_tmain(
int
argc, _TCHAR* argv[])
{
HANDLE
m_ProcessHandle =
OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
8016
);
BOOL
bSource = FALSE;
BOOL
bTarget = FALSE;
IsWow64Process(
GetCurrentProcess(),
&bSource
);
IsWow64Process(
m_ProcessHandle,
&bTarget
);
if
(bTarget == FALSE && bSource == TRUE)
{
HMODULE
NtdllModule = GetModuleHandle(
"ntdll.dll"
);
pfnNtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (pfnNtWow64QueryInformationProcess64)GetProcAddress(NtdllModule,
"NtWow64QueryInformationProcess64"
);
pfnNtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = (pfnNtWow64ReadVirtualMemory64)GetProcAddress(NtdllModule,
"NtWow64ReadVirtualMemory64"
);
PROCESS_BASIC_INFORMATION64 pbi = {0};
UINT64
ReturnLength = 0;
NTSTATUS Status = NtWow64QueryInformationProcess64(m_ProcessHandle,ProcessBasicInformation,&pbi,(
UINT32
)
sizeof
(pbi),(
UINT32
*)&ReturnLength);
if
(NT_SUCCESS(Status)){
_PEB64* Peb = (_PEB64*)
malloc
(
sizeof
(_PEB64));
RTL_USER_PROCESS_PARAMETERS64* ProcessParameters = (RTL_USER_PROCESS_PARAMETERS64*)
malloc
(
sizeof
(RTL_USER_PROCESS_PARAMETERS64));
Status = NtWow64ReadVirtualMemory64(m_ProcessHandle,(PVOID64)pbi.PebBaseAddress,(_PEB64*)Peb,
sizeof
(_PEB64),&ReturnLength);
std::cout <<
"PEB地址:"
<< std::hex << pbi.PebBaseAddress << std::endl;
}
}
else
if
(bTarget == TRUE && bSource == TRUE)
{
HMODULE
NtdllModule = GetModuleHandle(
"ntdll.dll"
);
pfnNtQueryInformationProcess NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(NtdllModule,
"NtQueryInformationProcess"
);
PROCESS_BASIC_INFORMATION32 pbi = {0};
UINT32
ReturnLength = 0;
NTSTATUS Status = NtQueryInformationProcess(m_ProcessHandle,ProcessBasicInformation,&pbi,(
UINT32
)
sizeof
(pbi),(
UINT32
*)&ReturnLength);
if
(NT_SUCCESS(Status)){
_PEB32* Peb = (_PEB32*)
malloc
(
sizeof
(_PEB32));
ReadProcessMemory(m_ProcessHandle, (
PVOID
)pbi.PebBaseAddress,(_PEB32*)Peb,
sizeof
(_PEB32),NULL);
std::cout <<
"PEB地址:"
<< std::hex << pbi.PebBaseAddress << std::endl;
}
}
getchar
();
return
0;
}
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <subauth.h>
#pragma region 依赖
#define NT_SUCCESS(x) ((x) >= 0)
#define ProcessBasicInformation 0
typedef
NTSTATUS(WINAPI *pfnNtWow64QueryInformationProcess64)
(
HANDLE
ProcessHandle,
UINT32
ProcessInformationClass,
PVOID
ProcessInformation,
UINT32
ProcessInformationLength,
UINT32
* ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtWow64ReadVirtualMemory64)
(
HANDLE
ProcessHandle, PVOID64 BaseAddress,
PVOID
BufferData,
UINT64
BufferLength,
PUINT64
ReturnLength);
typedef
NTSTATUS(WINAPI *pfnNtQueryInformationProcess)
(
HANDLE
ProcessHandle,
ULONG
ProcessInformationClass,
PVOID
ProcessInformation,
UINT32
ProcessInformationLength,
UINT32
* ReturnLength);
template
<
typename
T>
struct
_UNICODE_STRING_T
{
WORD
Length;
WORD
MaximumLength;
T Buffer;
};
template
<
typename
T>
struct
_LIST_ENTRY_T
{
T Flink;
T Blink;
};
template
<
typename
T,
typename
NGF,
int
A>
struct
_PEB_T
{
typedef
T type;
union
{
struct
{
BYTE
InheritedAddressSpace;
BYTE
ReadImageFileExecOptions;
BYTE
BeingDebugged;
BYTE
BitField;
};
T dummy01;
};
T Mutant;
T ImageBaseAddress;
T Ldr;
T ProcessParameters;
T SubSystemData;
T ProcessHeap;
T FastPebLock;
T AtlThunkSListPtr;
T IFEOKey;
T CrossProcessFlags;
T UserSharedInfoPtr;
DWORD
SystemReserved;
DWORD
AtlThunkSListPtr32;
T ApiSetMap;
T TlsExpansionCounter;
T TlsBitmap;
DWORD
TlsBitmapBits[2];
T ReadOnlySharedMemoryBase;
T HotpatchInformation;
T ReadOnlyStaticServerData;
T AnsiCodePageData;
T OemCodePageData;
T UnicodeCaseTableData;
DWORD
NumberOfProcessors;
union
{
DWORD
NtGlobalFlag;
NGF dummy02;
};
LARGE_INTEGER CriticalSectionTimeout;
T HeapSegmentReserve;
T HeapSegmentCommit;
T HeapDeCommitTotalFreeThreshold;
T HeapDeCommitFreeBlockThreshold;
DWORD
NumberOfHeaps;
DWORD
MaximumNumberOfHeaps;
T ProcessHeaps;
T GdiSharedHandleTable;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!