I need to determine the caller code whether is coming from EXE or DLL.
DLL
#ifdef DLL_EXPORTS
__declspec(dllexport) void say_hello();
__declspec(dllexport) void getCurrentModuleName();
#else
__declspec(dllimport) void say_hello();
__declspec(dllexport) void getCurrentModuleName();
#endif
#include <cstdio>
#include <windows.h>
#include <Dbghelp.h>
#include <iostream>
#include <tchar.h>
#include "dll.h"
#i开发者_StackOverflownclude "Psapi.h"
__declspec(naked) void *GetStackPointer()
{
__asm
{
mov eax, esp
ret
}
}
void getCurrentModuleName()
{
BOOL result = SymInitialize(GetCurrentProcess(), NULL , TRUE);
DWORD64 dwBaseAddress = SymGetModuleBase64(GetCurrentProcess(), (DWORD64)GetStackPointer());
TCHAR szBuffer[50];
GetModuleBaseName(GetCurrentProcess(), (HMODULE) dwBaseAddress, szBuffer, sizeof(szBuffer));
std::wcout << _T("--->") << szBuffer << std::endl;
}
void say_hello() {
getCurrentModuleName();
}
EXE
#include <windows.h>
#include <cstdio>
#include "dll.h"
int main() {
printf ("ENTERING EXE CODE...\n");
getCurrentModuleName();
printf ("ENTERING DLL CODE...\n");
say_hello();
getchar();
}
Here is the output.
ENTERING EXE CODE...
--->exe.exe
ENTERING DLL CODE...
--->exe.exe
I wish I can get
ENTERING EXE CODE...
--->exe.exe
ENTERING DLL CODE...
--->dll.dll
As the last caller code are from DLL itself (say_hello in DLL)
Is there any way I can achieve this?
GetStackAddress is returning the value of ESP, which is a reference to the stack. The stack is allocated per thread, independently of any modules loaded in the process. What you need to do is extract from the stack, the value of the return address - which will be an address in the calling module.
Given that the usual prefix code in a function is:
push ebp
mov ebp,esp
sub esp, bytes_of_local_variables
esp is going to be somewhat random, but [ebp] should be pointing at the previous ebp, and [ebp+4] should be pointing at the current frames return address.
So, you could try this:
__declspec(naked) void *GetReturnAddressAssumingStandardFramePointers()
{
__asm
{
mov eax, [ebp+4]
ret
}
}
Just make sure that functions that call that arn't compiled with /Oy
In that case use the return address of the function, which you can figure out by looking directly at the stack. The rest of the answer still applies.
You get stack pointer inside getCurrentModuleName()
which is in DLL, but you need to get returning address from stack at the beginning of getCurrentModuleName()
which shows you where getCurrentModuleName()
was called from.
Use EnumProcessModules(). For each one call GetModuleInformation(). Compare the address of the function that you're executing (using a function pointer) to the lpBaseOfDll and SizeOfImage members of the MODULEINFO struct. If it falls within the range, you know that's the current module. If so, use GetModuleBaseName to retrieve the name of the module.
Here is the solution. The limitation is that, it is only able to trace up to 62 frames.
// Must have in order for us to turned address into module name.
SymInitialize(GetCurrentProcess(), NULL , TRUE);
// Limitation of RtlCaptureStackBackTrace.
const int kMaxCallers = 62;
void* callers[kMaxCallers];
int count = RtlCaptureStackBackTrace(0, kMaxCallers, callers, NULL);
for (int i = 0; i < count; i++) {
TCHAR szBuffer[50];
DWORD64 dwBaseAddress = SymGetModuleBase64(GetCurrentProcess(), (DWORD64)callers[i]);
GetModuleBaseName(GetCurrentProcess(), (HMODULE) dwBaseAddress, szBuffer, sizeof(szBuffer));
std::wcout << _T("--->") << szBuffer << std::endl;
}
精彩评论