我在使用 std::lock_guard 时遇到了一件奇怪的事情。注意:我正在使用 MSVS 2012 和 std::lock_guard,正如在此版本中包含和发布的新 c++11 标头中的 mutex 标头中声明的那样。
以下是复制此行为的代码,似乎使用此函数会由于某种原因增加 dll LoadCount,我的问题是是否有人可以解释原因,是否有更好的锁定函数可以使用,不会与 LoadCount 混淆?
#include <windows.h>
#include <mutex>
typedef struct _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;
typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef VOID (NTAPI *PPS_POST_PROCESS_INIT_ROUTINE) (VOID);
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _PROCESS_BASIC_INFORMATION
{
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS
{
ProcessBasicInformation = 0,
} PROCESSINFOCLASS, *PPROCESSINFOCLASS;
typedef struct _LDRP_CSLIST
{
PSINGLE_LIST_ENTRY Tail;
} LDRP_CSLIST, *PLDRP_CSLIST;
typedef enum _LDR_DDAG_STATE
{
LdrModulesMerged = -5,
LdrModulesInitError = -4,
LdrModulesSnapError = -3,
LdrModulesUnloaded = -2,
LdrModulesUnloading = -1,
LdrModulesPlaceHolder = 0,
LdrModulesMapping = 1,
LdrModulesMapped = 2,
LdrModulesWaitingForDependencies = 3,
LdrModulesSnapping = 4,
LdrModulesSnapped = 5,
LdrModulesCondensed = 6,
LdrModulesReadyToInit = 7,
LdrModulesInitializing = 8,
LdrModulesReadyToRun = 9
} LDR_DDAG_STATE;
typedef struct _LDR_DDAG_NODE
{
LIST_ENTRY Modules;
PVOID ServiceTagList;
ULONG LoadCount;//this is where its located in windows 8
ULONG ReferenceCount;
ULONG DependencyCount;
union
{
LDRP_CSLIST Dependencies;
SINGLE_LIST_ENTRY RemovalLink;
};
LDRP_CSLIST IncomingDependencies;
LDR_DDAG_STATE State;
SINGLE_LIST_ENTRY CondenseLink;
ULONG PreorderNumber;
ULONG LowestLink;
} LDR_DDAG_NODE, *PLDR_DDAG_NODE;
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT obsoleteLoadCount;//in windows 8 this is obsolete
USHORT TlsIndex;//but we can still use it in win 7 and below
union
{
LIST_ENTRY HashLinks;
struct CheckPtr
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
struct _ACTIVATION_CONTEXT *EntryPointActivationContext;
PVOID PatchInformation;
PLDR_DDAG_NODE DdagNode;
} LDR_MODULE, *PLDR_MODULE;
typedef NTSTATUS (__stdcall *pfnZwQueryInformationProcess) (HANDLE, PROCESSINFOCLASS,
PVOID, ULONG, PULONG);
pfnZwQueryInformationProcess ZwQueryInformationProcess;
DWORD GetModuleLoadCount(HMODULE hmod)
{
HMODULE hModule = LoadLibrary("ntdll.dll");
if(hModule==NULL)
return NULL;
ZwQueryInformationProcess = (pfnZwQueryInformationProcess) GetProcAddress(hModule,
"ZwQueryInformationProcess");
if (ZwQueryInformationProcess == NULL) {
FreeLibrary(hModule)
return NULL; // failed to get PEB
}
PROCESS_BASIC_INFORMATION pbi;
PROCESSINFOCLASS pic = ProcessBasicInformation;
if (ZwQueryInformationProcess(GetCurrentProcess(), pic, &pbi, sizeof(pbi), NULL)
!= STATUS_SUCCESS)
{
// ZwQueryInformationProcess failed...
FreeLibrary(hModule);
return NULL;
}
FreeLibrary(hModule);
LDR_MODULE *peb_ldr_module = (LDR_MODULE
*)pbi.PebBaseAddress->Ldr->InLoadOrderModuleList.Flink;
while((peb_ldr_module = (LDR_MODULE
*)peb_ldr_module->InLoadOrderModuleList.Flink)!=(LDR_MODULE
*)pbi.PebBaseAddress->Ldr->InLoadOrderModuleList.Blink) {
if(peb_ldr_module->BaseAddress==hmod) {
//well this actualy works in windows 8...
//and probably vista with aero enabled as well...
//anyway if it is obsolete its always 6
//so we can if it out like this...
if(peb_ldr_module->obsoleteLoadCount==6)
return peb_ldr_module->DdagNode->LoadCount;
else
return peb_ldr_module->obsoleteLoadCount;
}
}
if(peb_ldr_module->BaseAddress==hmod) {
if(peb_ldr_module->obsoleteLoadCount==6)
return peb_ldr_module->DdagNode->LoadCount;
else
return peb_ldr_module->obsoleteLoadCount;
}
}
mutable std::mutex g_logMutex;
void test()//test is just a function inside of my dll
{ //which is injected and running under low privileges in internet explorer as
//an addon, I dont think that matters, but i dont want to leave any info out
//that might help answer my question.
int loadcount = GetModuleLoadCount((HMODULE)gModule);//its 1 here
std::lock_guard<std::mutex> lock(g_logMutex);
loadcount = GetModuleLoadCount((HMODULE)gModule);//now its 2
}