Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call to GetModuleHandle on kernel32 using Python C-types

I'm trying to use Python's C-Types to call GetModuleHandleA on the kernel32 library. I'd like to get a handle to the library so I can use it to call GetProcAddress for LoadLibraryA. Below is my code...

import sys
from ctypes

kernel32 = windll.kernel32
print("The kernel32 is %s" % kernel32)
#The kernel32 is <WinDLL 'kernel32', handle 765b0000 at 1c2a9f0>

h_kernel32 = kernel32.GetModuleHandleA("C:\\Windows\\System32\\kernel32.dll")
if h_kernel32 == False:
        error = GetLastError()
        print("ERROR: %d - %s" % (error, FormatError(error)))

I'm getting an error, "ERROR: 126 - The specified module could not be found". I've also tried "C:/Windows/System32/kernel32.dll" and just "kernel32". I'm using Python 3.2 and this is on a Windows 7 machine. I've verified that the dll is there and in the path that I have set in the code above. I've been doing some research and can't seem to find out what the issue is. Any help is greatly appreciated. Thanks!

like image 828
User4679 Avatar asked Jun 10 '13 22:06

User4679


1 Answers

The handle is stored in kernel32._handle. Calling GetModuleHandle should return the same value, but make sure you set restype and argtypes for type safety [*]:

import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

kernel32.GetModuleHandleW.restype = wintypes.HMODULE
kernel32.GetModuleHandleW.argtypes = [wintypes.LPCWSTR]

hMod = kernel32.GetModuleHandleW('kernel32.dll')

Notice the 'W' suffix instead of 'A'. Python 3 uses Unicode strings, for which ctypes creates a c_wchar_p (LPCWSTR). There's no reason to call the [A]NSI version since it's just a wrapper around the [W]ide string version. But if you must, then you need to use bytes:

kernel32.GetModuleHandleA.restype = wintypes.HMODULE
kernel32.GetModuleHandleA.argtypes = [wintypes.LPCSTR]

hMod = kernel32.GetModuleHandleA(b'kernel32.dll')

[*] I recommend using kernel32 = WinDLL('kernel32', use_last_error=True) instead of windll.kernel32. This avoids conflicts with other modules that use windll. It also enables protection for the thread's LastErrorValue. In this case, use ctypes.get_last_error() and ctypes.set_last_error(err) instead of directly calling WinAPI GetLastError and SetLastError.

like image 181
Eryk Sun Avatar answered Sep 28 '22 14:09

Eryk Sun