9
votes

I'm working on native call bindings for a virtual machine, and one of the features is to be able to look up standard libc functions by name at runtime. On windows this becomes a bit of a hassle because I need to get a handle to the msvcrt module that's currently loaded in the process. Normally this is msvcrt.dll, but it could be other variants as well (msvcr100.dll, etc) and a call to GetModuleHandle("msvcrt") could fail if a variant with a different name is used.

What I would like to be able to do is a reverse lookup, take a function pointer from libc (which I have in abundance) and get a handle to the module that provides it. Basically, something like this:

HANDLE hlibc = ReverseGetModuleHandle(fprintf); // Any func from libc should do the trick
void *vfunc = GetProcAddress(hlibc);

Is there such a thing in the win32 API, without descending into a manual walk of process handles and symbol tables? Conversely, if I am over-thinking the problem, is there an easier way to look up a libc function by name on win32?

3

3 Answers

21
votes

The documented way of obtaining the module handle is by using GetModuleHandleEx.

HMODULE hModule = NULL;

if(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
       GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, // behave like GetModuleHandle
       (LPCTSTR)address, &hModule))
{
    // hModule should now refer to the module containing the target address.
}
10
votes
MEMORY_BASIC_INFORMATION mbi;
HMODULE mod;
if (VirtualQuery( vfunc, &mbi, sizeof(mbi) ))
{
    mod = (HMODULE)mbi.AllocationBase;
}
0
votes

Unfortunately you will have to walk through modules as you feared. It's not too bad though. Here is the idea, some code written in notepad:

MODULEENTRY32 me = {0};
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, 0 );

me.dwSize = sizeof me;
Module32First( hSnapshot, &me );
  if( me.modBaseAddr <= funcPtr &&
      ( me.modBaseAddr + me.modBaseSize ) > funcPtr ) {
    ...
    break;
  }
do {
} while( Module32Next( hSnapshot, &me ) );

CloseHandle( hSnapshot );