Python ctypes - 尝试 ReadProcessMemory 时收到 ERROR_PARTIAL_COPY
Python ctypes - Receiving ERROR_PARTIAL_COPY when trying to ReadProcessMemory
我的程序,运行 在 Windows 10:
上提升
- 获取 运行 notepad.exe 进程的 PID
- 通过
OpenProcess
接收到它的句柄
- 枚举名称为notepad.exe的进程模块的baseAddress
- 调用
ReadProcessMemory
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."
不确定我哪里搞砸了,非常感谢您的建议和帮助!
ReadProcessMemory
second argument is a LPCVOID
(long pointer to const void*) but you're passing the result of hex
其中 returns 一个字符串(然后将转换为指向 ctypes 上下文中的字符串的指针)。
关注@CristiFati 评论并使用 ctypes argtypes and restype,这会立即发现问题。
不要直接从 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)
我的程序,运行 在 Windows 10:
上提升- 获取 运行 notepad.exe 进程的 PID
- 通过
OpenProcess
接收到它的句柄
- 枚举名称为notepad.exe的进程模块的baseAddress
- 调用
ReadProcessMemory
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."
不确定我哪里搞砸了,非常感谢您的建议和帮助!
ReadProcessMemory
second argument is aLPCVOID
(long pointer to const void*) but you're passing the result ofhex
其中 returns 一个字符串(然后将转换为指向 ctypes 上下文中的字符串的指针)。关注@CristiFati 评论并使用 ctypes argtypes and restype,这会立即发现问题。
不要直接从 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)