Python- 使用 ctypes 的 GetProcAddress 返回 NULL

Python- GetProcAddress using ctypes returns NULL

提问人:shon 提问时间:8/25/2019 最后编辑:shubermanshon 更新时间:8/25/2019 访问量:1564

问:

问题:

我正在尝试获取地址,但得到.LoadLibraryWNULL

研究工作:

该函数成功检索映射到 python 进程的地址,但返回错误代码为 126 的地址。当我在进程黑客中检查函数地址时(在python进程下),我看到一个有效的地址。kernel32.dllNULLLoadLibraryW

from ctypes import *
kernel32 = windll.kernel32

def resolve_function(dll, func):
    handle = kernel32.GetModuleHandleA(dll.encode("ascii"))
    address = kernel32.GetProcAddress(handle, func.encode("ascii"))
    kernel32.CloseHandle(handle)
    return address


address = resolve_function('kernel32.dll', 'LoadLibraryW')
print(address)

我尝试了其他库和其他函数,但它总是返回.NULL

蟒蛇 python-3.x winapi ctypes getprocaddress

评论

1赞 David Heffernan 8/25/2019
不要在不拥有的句柄上调用 CloseHandle。在调用的函数上设置 argtypes 和 restypes。不要使用 ASCII,请使用 Unicode API。完成这些更改后,请报告发生的情况。
0赞 shon 8/25/2019
@DavidHeffernan谢谢。我更改了函数 - def resolve_function(dll, func): handle = kernel32。GetModuleHandleW(dll) 地址 = kernel32。GetProcAddress(handle, func.encode(“ascii”)) 返回地址 仍然返回 NULL
0赞 David Heffernan 8/25/2019
你没有听从我的指示。

答:

0赞 David Heffernan 8/25/2019 #1

您需要在调用的函数上设置 and 属性,以便能够与原型匹配。我想这是您代码中的主要问题。argtypesrestypectypes

在我看来,您还应该使用 Unicode API 作为一般规则。并且您不能调用 返回的句柄。CloseHandleGetModuleHandle

把它们放在一起,就像这样:

from ctypes import *
kernel32 = windll.kernel32

def resolve_function(dll, func):
    kernel32.GetModuleHandleW.argtypes = [c_wchar_p]
    kernel32.GetModuleHandleW.restype = c_void_p
    kernel32.GetProcAddress.argtypes = [c_void_p, c_char_p]
    kernel32.GetProcAddress.restype = c_void_p
    handle = kernel32.GetModuleHandleW(dll)
    address = kernel32.GetProcAddress(handle, func)
    return address

address = resolve_function('kernel32.dll', b'LoadLibraryW')
print(address)
0赞 CristiFati 8/25/2019 #2

列表 [Python 3.Docs]: ctypes - Python 的外部函数库

它看起来像一个 XY 问题
你不需要调用这 2 个函数中的任何一个,ctypes 会为你做到这一点

这是您的实现的替代方法(请注意,我没有进行异常处理):

import ctypes


def resolve_function(dll_name, func_name, dll_factory=ctypes.CDLL):
    dll = dll_factory(dll_name)
    return getattr(dll, func_name, None)

这是跨平台的(也可以在 Nix 上工作)。