Python ctypes - 尝试 ReadProcessMemory 时收到 ERROR_PARTIAL_COPY

Python ctypes - Receiving ERROR_PARTIAL_COPY when trying to ReadProcessMemory

我的程序,运行 在 Windows 10:

上提升
import ctypes
from ctypes import wintypes
import win32process
import psutil

targetProcess = "notepad.exe"
PROCESS_ALL_ACCESS = 0x1F0FFF
BUFFER_SIZE = 200

def getpid():
    for proc in psutil.process_iter():
        if proc.name() == targetProcess:
            return proc.pid

def main():
    status = ctypes.windll.ntdll.RtlAdjustPrivilege(20, 1, 0, ctypes.byref(ctypes.c_bool()))
    if(status == -1073741727):
        print("STATUS_PRIVILEGE_NOT_HELD - A required privilege is not held by the client.")

    hProcess = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, getpid())                        # handle to process
    lpBuffer = ctypes.create_string_buffer(BUFFER_SIZE)                                                       # Buffer we want to write results to
    targetProcessBaseAddress = None                                                                           # base address of the target processes entry module

    modules = win32process.EnumProcessModules(hProcess)                                                       # Retreive modules of target process
    for module in modules:
        name = str(win32process.GetModuleFileNameEx(hProcess, module))
        if targetProcess in name:
            targetProcessBaseAddress = hex(module)                                                                         

    count = ctypes.c_ulong(0)
    res = ctypes.windll.kernel32.ReadProcessMemory(hProcess, targetProcessBaseAddress, ctypes.byref(lpBuffer), BUFFER_SIZE, ctypes.byref(count))
    if res == 0:
        err = ctypes.windll.kernel32.GetLastError()
        if (err == 299):
            print("ERROR_PARTIAL_COPY - Only part of a ReadProcessMemory or WriteProcessMemory request was completed.")
        else:
            print(err)
    else:
        print(lpBuffer.raw)

if __name__ == '__main__':
    main()

以上是通过 python3.8 使用本机 ctypes 库完成的。

我期待看到 hexdump 或 0x00,0x00 以外的任何数据。但似乎我的错误出现在提供给 ReadProcessMemory 的参数中,这是由于错误 299 而假定的从 GetLastError() 返回,表示:

"ERROR_PARTIAL_COPY - Only part of a ReadProcessMemory or WriteProcessMemory request was completed."

不确定我哪里搞砸了,非常感谢您的建议和帮助!

  1. ReadProcessMemory second argument is a LPCVOID (long pointer to const void*) but you're passing the result of hex 其中 returns 一个字符串(然后将转换为指向 ctypes 上下文中的字符串的指针)。

  2. 关注@CristiFati 评论并使用 ctypes argtypes and restype,这会立即发现问题。

  3. 不要直接从 win32 API 使用 GetLastError。解释器在其生命周期中可以自由调用任何 Windows API,因此当您调用此 API 时,您不知道它是脚本的结果还是 API解释器出于自己的目的调用它。为此,ctypes 提出了一个特定的变量,它以 ctypes.get_last_error.

    的形式缓存结果。

最好的方法是用类似的东西开始你的脚本:

import ctypes

# obtain kernel32 WinDLL ensuring that we want to cache the last error for each API call.
kernel32 = ctypes.WinDLL("kernel32", use_last_error = True)

# start prototyping your APIs
OpenProcess = kernel32.OpenProcess
OpenProcess.argtypes = [ ... ]
OpenProcess.restype = ...

# then call the api
res = OpenProcess( ... )

#ensure you check the result by calling the cached last error
if not res:
    err = ctypes.get_last_error()
    # you might also raise
    raise ctypes.WinError(err)