1
votes

I am having a problem with calling GetModuleHandleA() using Python. I have a module that attaches as debugger to the process. I'm working on a function that would return address of the function in the specific DLL module. GetModuleHandleA("msvcr100") fails all of the time.

from ctypes import *
kernel32 = windll.kernel32

Function declared as part of a bigger debug class. That's the part of function declaration:

   def resolve_function(self,dll,function): 
        handle = kernel32.GetModuleHandleA(dll)
        if handle == False:
            print "kernel32.GetModuleNameA() failed!!!"
            return False
        address = kernel32.GetProcAddress(handle, function)
        if address == False:
            print "kernel32.GetProcAddress() failed!!!"
            return False
        kernel32.CloseHandle(handle)
        return address

Call the function made as:

function_address = debug.resolve_function("msvcr100", "printf")

I run separate process that uses printf() and then attach to it. Everything works fine until I get to GetModuleHandleA() that returns False all of the time.

Code that runs printf():

from ctypes import *
import time
msvcr100 = cdll.msvcr100
counter = 0
while 1:
    msvcr100.printf("Counter = %d\n" % counter)
    time.sleep(1)
    counter += 1

Any ideas?

4
Have you verified that msvcr100 is actually loaded into the process? GetModuleHandle() doesn't actually do any loading itself...Shog9
And, uh... You might find this useful: How to printf in Python?Shog9
I have. It does load msvcr100.dll, because it prints stuff on the screen.PSS

4 Answers

5
votes

You've found the solution to your problem, but I'm answering anyway to explain why your original effort failed (and why your fix worked).

First, msvcrt/msvcr100 are two different versions of Microsoft's C runtime library. There are other versions as well, and all of them contain their own definitions for printf(). A given process may have any one of them loaded, or multiple versions loaded, or no versions loaded - it's possible to produce console output using only WinAPI functions! In short, if it's not your process, you can't depend on any given version of the C runtime being available.

Second, GetModuleHandle() doesn't load anything. It returns a handle to the named module only if it has already been loaded. msvcr100.dll can be sitting right there on disk, but if the process hasn't already loaded it then GetModuleHandle won't give a handle to you. LoadLibrary() is the function you'd call if you wanted to both load and retrieve a handle to a named module... But you probably don't want to do this in a process you don't own.

FWIW, Process Explorer is a handy tool for viewing the DLLs already loaded by a process.

1
votes

After modifying:


...

handle = kernel32.GetModuleHandleA(dll) if handle == False: error = GetLastError() print "ERROR: %d - %s" % (error, FormatError(error)) return False

...

I get: ERROR: 126 - The specified module could not be found

I actually replaced msvcr100.dll with msvcrt.dll in my code and it worked perfect. I found out that msvcrt.dll is system dll. msvcr100.dll ships with Studio 2010. They are both located in C:\Windows\system32. It is still a mystery for me why msvcr100.dll did not work.

0
votes

Use GetLastError() (or WinError) from ctypes to find out why you're getting a NULL return, then add that information to your error message. Even after you figure out this specific problem, you'll want that more robust error reporting.

See the ctypes docs for details: http://docs.python.org/library/ctypes.html

0
votes

Try calling:

msvcr100 = cdll.msvcr100

before calling:

function_address = debug.resolve_function("msvcr100", "printf")

to make sure the DLL is loaded in your process. msvcrt might work because it was already loaded.