关于Windows:Python GetModuleHandleW OSError:[WinError 126]找不到指定的模块

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

以下代码生成错误:

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

但是,如果我使用

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

找到了dll,但通过以下代码遇到了另一个错误:

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

生成的错误是:

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

我希望有人会对如何解决这些错误有一个想法。
完整脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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)。 但原则上如下:

1
2
3
4
5
6
7
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等,因此不需要。