kernel32.GetModuleHandleA 返回奇怪的值

kernel32.GetModuleHandleA returning strange value

通过运行下面python的代码加上python main.py wmi.dll,我想得到DLL的加载地址。但是,loadAddr 的值为 0。代码有什么问题?

from ctypes import *
import sys
import string

kernel32 = windll.kernel32
print(kernel32)

if len(sys.argv)!=2:
    print("Usage : dll.py<DLL to resolve>")
    sys.exit(0)
windll.LoadLibrary(sys.argv[1])
loadAddr = kernel32.GetModuleHandleA(sys.argv[1])
print(str(loadAddr)+"\n")
print(sys.argv[1])
print(hex(loadAddr) + " Load Address")
print(hex(loadAddr + int("0x1000",16)) + " Text segment")

清单[Python.Docs]: ctypes - A foreign function library for Python.

您的代码存在一些问题:

  1. 主要的:

    要克服这个问题,您应该使用:kernel32.GetModuleHandleW。示例:

    >>> import ctypes as ct
    >>> # kernel32 is alsready loaded
    >>> ct.windll.kernel32.GetModuleHandleA("kernel32")
    0
    >>> ct.windll.kernel32.GetModuleHandleW("kernel32")
    -1613692928
    
  2. 检查 以获取有关通过 CTypes.dll 调用函数的详细信息(特别是,您应该将 restype 设置为 64bit 值,例如 wintypes.HMODULE)

  3. 不需要 GetModuleHandle(使前 2 个项目符号对这个特殊情况没有实际意义,但我保留了它们,因为它们包含有用的一般信息)。您可以简单地使用 load_addr = windll.LoadLibrary(sys.argv[1])._handle

  4. 参数验证应该在 1st

确保使用 ctypes 定义要使用的函数的 .argtypes.restypeGetModuleHandleA取一个LPCSTR(相当于Python中的一个bytes对象),GetModuleHandleW取一个LPCWSTR(相当于str Python 中的对象)。此外,它们都是return HDMODULE,这是64位系统的64位值,但如果未指定,默认的.restypec_int(32位)。

调用任一版本的正确代码如下:

import ctypes as ct
from ctypes import wintypes as w

k32 = ct.WinDLL('kernel32')
k32.GetModuleHandleA.argtypes = w.LPCSTR,
k32.GetModuleHandleA.restype = w.HMODULE
k32.GetModuleHandleW.argtypes = w.LPCWSTR,
k32.GetModuleHandleW.restype = w.HMODULE

wmi = ct.WinDLL('wmi')

print(k32.GetModuleHandleA(b'wmi'))  # byte string
print(k32.GetModuleHandleW('wmi'))   # Unicode string
print(k32.GetModuleHandleA('wmi'))   # calling with wrong type

下面的示例输出。请注意,此值大于 32 位值可以容纳的值 (>4294967295),如果未设置 .restype,该值将被截断且不正确,如果未设置 .argtypes,则不会出现错误消息设置。

1864530853888
1864530853888
Traceback (most recent call last):
  File "C:\test.py", line 15, in <module>
    print(k32.GetModuleHandleA('wmi'))
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type