Python GetModuleHandleW OSError: [WinError 126] The specified module could not be found

Python GetModuleHandleW OSError: [WinError 126] The specified module could not be found

以下代码生成错误:

OSError: [WinError 126] The specified module could not be found
windll.kernel32.GetModuleHandleW.restype = wintypes.HMODULE
windll.kernel32.GetModuleHandleW.argtypes = [wintypes.LPCWSTR]
KERNEL32 = windll.GetModuleHandleW("C:\Windows\System32\kernel32.dll")

但是,如果我使用

KERNEL32 = windll.LoadLibrary("C:\Windows\System32\kernel32.dll")

找到了 dll,但我遇到了以下代码的不同错误:

LoadLibAddy = windll.kernel32.GetProcAddress(KERNEL32, "LoadLibraryA")

生成的错误是:

ctypes.ArgumentError: argument 1:  Don't know how to convert parameter 1

我希望有人知道如何修复这些错误中的任何一个。 完整脚本:

from ctypes import *
from ctypes import wintypes

def dllinjector(processID, DLL_NAME):
    KERNEL32 = WinDLL('kernel32.dll', use_last_error=True)
    KERNEL32.GetProcAddress.restype = c_void_p
    KERNEL32.GetProcAddress.argtypes = (wintypes.HMODULE, wintypes.LPCSTR)
    PROCESS_CREATE_THREAD = 0x0002
    PROCESS_QUERY_INFORMATION = 0x0400
    PROCESS_VM_OPERATION = 0x0008
    PROCESS_VM_WRITE = 0x0020
    PROCESS_VM_READ = 0x0010
    openHandle = KERNEL32.OpenProcess(PROCESS_CREATE_THREAD|
                                             PROCESS_QUERY_INFORMATION|
                                             PROCESS_VM_OPERATION|
                                             PROCESS_VM_WRITE|
                                             PROCESS_VM_READ, False, processID)
    MEM_RESERVE = 0x00002000
    MEM_COMMIT = 0x00001000
    PAGE_READWRITE = 0x04

    if not openHandle:
        print("OpenProcess failed.")
        print("GetLastError: ", KERNEL32.GetLastError())
        return False
    print("openProcess GetLastError: ", KERNEL32.GetLastError())
    #print("Successfully opened process.")

    LoadLibAddy = KERNEL32.GetProcAddress(KERNEL32._handle, b"LoadLibraryA")
    if not LoadLibAddy:
        raise WinError(ctypes.get_last_error())
    print("LoadLibAddy: ", LoadLibAddy)
    print("LoadLibAddy GetLastError: ", KERNEL32.GetLastError())

    # Allocate space in the process for the dll
    RemoteString = KERNEL32.VirtualAllocEx(openHandle, None, len(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)
    print("RemoteString GetLastError: ", KERNEL32.GetLastError())
    if not RemoteString:
        print("VirtualAllocEx failed.")
        return False

    # Write the string name of the dll in the memory allocated
    if not KERNEL32.WriteProcessMemory(openHandle, RemoteString, DLL_NAME, len(DLL_NAME), None):
        print("WriteProcessMemory failed.")
        return False
    print("WriteProcessMemory GetLastError: ", KERNEL32.GetLastError())

    #Load the dll
    if not KERNEL32.CreateRemoteThread(openHandle, None, None, c_longlong(LoadLibAddy), RemoteString, None, None):
        print("CreateRemoteThread failed.")
        return False
    print("CreateRemotedThread GetLastError: ", windll.kernel32.GetLastError())
    #print("CreateRemoteThread: ", windll.kernel32.CreateRemoteThread(openHandle, None, None, LoadLibAddy, RemoteString, None, None))

    KERNEL32.CloseHandle(openHandle)
    print("CloseHandle GetLastError: ", KERNEL32.GetLastError())

    return True

def main():
    processID = 25408
    DLL_NAME = "mydll32.dll"

    dllinjector(processID, DLL_NAME)

    print("program completed.")

main()

应该是windll.kernel32.GetModuleHandleW("kernel32.dll")。但是请不要在定义函数原型时使用 windll 因为它对所有使用 ctypes 的模块都是全局的,这会导致原型冲突。使用 kernel32 = WinDLL('kernel32', use_last_error=True)。 DLL 句柄是 kernel32._handle

对于您的第二个问题,首先,在使用 ctypes 时没有理由直接调用 GetProcAddress(或 POSIX 系统上的 dlsym)。但原则上是这样的:

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)   
kernel32.GetProcAddress.restype = ctypes.c_void_p
kernel32.GetProcAddress.argtypes = (wintypes.HMODULE, wintypes.LPCSTR)

LoadLibAddy = kernel32.GetProcAddress(kernel32._handle, b'LoadLibraryA')
if not LoadLibAddy:
    raise ctypes.WinError(ctypes.get_last_error())

请注意,函数名称作为 bytes 传递。无论如何,您不需要这个,因为 kernel32.LoadLibraryA(或 kernel32.LoadLibraryW)是一个函数指针,您可以将其作为参数传递或转换为 c_void_p,等等。