Python Ctypes Read/WriteProcessMemory() - 错误 5/998 帮助!
请不要害怕,但是如果您熟悉 ctypes 或 C,下面的代码应该很容易阅读。
我一直试图让我的 ReadProcessMemory() 和 WriteProcessMemory() 函数正常工作这么长时间,并且尝试了几乎所有可能的方法,除了正确的方法。
它启动目标程序,返回其 PID 和句柄。但我总是收到错误代码 5 - ERROR_ACCESS_DENIED。当我运行读取函数时(暂时忘记写入)。我将此程序作为我认为具有 PROCESS_ALL_ACCESS 或 CREATE_PRESERVE_CODE_AUTHZ_LEVEL 的子进程启动。
当我打开句柄时,我还尝试了 PROCESS_ALL_ACCESS 和 PROCESS_VM_READ 。
我还可以说它是一个有效的内存位置,因为我可以使用 CheatEngine 在运行的程序中找到它。
至于 VirtualQuery() 我收到错误代码 998 - ERROR_NOACCESS,这进一步证实了我对它是某些安全/权限问题的怀疑。
任何帮助或想法将非常感激,再次强调,这是我到目前为止的整个程序,不要让它吓到你=P。
from ctypes import *
from ctypes.wintypes import BOOL
import binascii
BYTE = c_ubyte
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
PVOID = c_void_p
LPVOID = c_void_p
UNIT_PTR = c_ulong
SIZE_T = c_ulong
class STARTUPINFO(Structure):
_fields_ = [("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute",DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),]
class PROCESS_INFORMATION(Structure):
_fields_ = [("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),]
class MEMORY_BASIC_INFORMATION(Structure):
_fields_ = [("BaseAddress", PVOID),
("AllocationBase", PVOID),
("AllocationProtect", DWORD),
("RegionSize", SIZE_T),
("State", DWORD),
("Protect", DWORD),
("Type", DWORD),]
class SECURITY_ATTRIBUTES(Structure):
_fields_ = [("Length", DWORD),
("SecDescriptor", LPVOID),
("InheritHandle", BOOL)]
class Main():
def __init__(self):
self.h_process = None
self.pid = None
def launch(self, path_to_exe):
CREATE_NEW_CONSOLE = 0x00000010
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
security_attributes = SECURITY_ATTRIBUTES()
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb = sizeof(startupinfo)
security_attributes.Length = sizeof(security_attributes)
security_attributes.SecDescriptior = None
security_attributes.InheritHandle = True
if windll.kernel32.CreateProcessA(path_to_exe,
None,
byref(security_attributes),
byref(security_attributes),
True,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL,
None,
None,
byref(startupinfo),
byref(process_information)):
self.pid = process_information.dwProcessId
print "Success: CreateProcess - ", path_to_exe
else:
print "Failed: Create Process - Error code: ", windll.kernel32.GetLastError()
def get_handle(self, pid):
PROCESS_ALL_ACCESS = 0x001F0FFF
PROCESS_VM_READ = 0x0010
self.h_process = windll.kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
if self.h_process:
print "Success: Got Handle - PID:", self.pid
else:
print "Failed: Get Handle - Error code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
def read_memory(self, address):
buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)
bytesRead = c_ulong(0)
if windll.kernel32.ReadProcessMemory(self.h_process, address, buffer, bufferSize, byref(bytesRead)):
print "Success: Read Memory - ", buffer.value
else:
print "Failed: Read Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.CloseHandle(self.h_process)
windll.kernel32.SetLastError(10000)
def write_memory(self, address, data):
count = c_ulong(0)
length = len(data)
c_data = c_char_p(data[count.value:])
null = c_int(0)
if not windll.kernel32.WriteProcessMemory(self.h_process, address, c_data, length, byref(count)):
print "Failed: Write Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
else:
return False
def virtual_query(self, address):
basic_memory_info = MEMORY_BASIC_INFORMATION()
windll.kernel32.SetLastError(10000)
result = windll.kernel32.VirtualQuery(address, byref(basic_memory_info), byref(basic_memory_info))
if result:
return True
else:
print "Failed: Virtual Query - Error Code: ", windll.kernel32.GetLastError()
main = Main()
address = None
main.launch("C:\Program Files\ProgramFolder\Program.exe")
main.get_handle(main.pid)
#main.write_memory(address, "\x61")
while 1:
print '1 to enter an address'
print '2 to virtual query address'
print '3 to read address'
choice = raw_input('Choice: ')
if choice == '1':
address = raw_input('Enter and address: ')
if choice == '2':
main.virtual_query(address)
if choice == '3':
main.read_memory(address)
谢谢!
Please don't get scared but the following code, if you are familiar with ctypes or C it should be easy to read.
I have been trying to get my ReadProcessMemory() and WriteProcessMemory() functions to be working for so long and have tried almost every possibility but the right one.
It launches the target program, returns its PID and handle just fine. But I always get a error code of 5 - ERROR_ACCESS_DENIED. When I run the read function(forget the write for now). I am launching this program as what I believe to be a CHILD process with PROCESS_ALL_ACCESS or CREATE_PRESERVE_CODE_AUTHZ_LEVEL.
I have also tried PROCESS_ALL_ACCESS and PROCESS_VM_READ when I open the handle.
I can also say that it is a valid memory location because I can find it on the running program with CheatEngine.
As for VirtualQuery() I get an error code of 998 - ERROR_NOACCESS which further confirms my suspicion of it being some security/privilege problem.
Any help or ideas would be very appreciated, again, it's my whole program so far, don't let it scare you =P.
from ctypes import *
from ctypes.wintypes import BOOL
import binascii
BYTE = c_ubyte
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
PVOID = c_void_p
LPVOID = c_void_p
UNIT_PTR = c_ulong
SIZE_T = c_ulong
class STARTUPINFO(Structure):
_fields_ = [("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute",DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),]
class PROCESS_INFORMATION(Structure):
_fields_ = [("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),]
class MEMORY_BASIC_INFORMATION(Structure):
_fields_ = [("BaseAddress", PVOID),
("AllocationBase", PVOID),
("AllocationProtect", DWORD),
("RegionSize", SIZE_T),
("State", DWORD),
("Protect", DWORD),
("Type", DWORD),]
class SECURITY_ATTRIBUTES(Structure):
_fields_ = [("Length", DWORD),
("SecDescriptor", LPVOID),
("InheritHandle", BOOL)]
class Main():
def __init__(self):
self.h_process = None
self.pid = None
def launch(self, path_to_exe):
CREATE_NEW_CONSOLE = 0x00000010
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
security_attributes = SECURITY_ATTRIBUTES()
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb = sizeof(startupinfo)
security_attributes.Length = sizeof(security_attributes)
security_attributes.SecDescriptior = None
security_attributes.InheritHandle = True
if windll.kernel32.CreateProcessA(path_to_exe,
None,
byref(security_attributes),
byref(security_attributes),
True,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL,
None,
None,
byref(startupinfo),
byref(process_information)):
self.pid = process_information.dwProcessId
print "Success: CreateProcess - ", path_to_exe
else:
print "Failed: Create Process - Error code: ", windll.kernel32.GetLastError()
def get_handle(self, pid):
PROCESS_ALL_ACCESS = 0x001F0FFF
PROCESS_VM_READ = 0x0010
self.h_process = windll.kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
if self.h_process:
print "Success: Got Handle - PID:", self.pid
else:
print "Failed: Get Handle - Error code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
def read_memory(self, address):
buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)
bytesRead = c_ulong(0)
if windll.kernel32.ReadProcessMemory(self.h_process, address, buffer, bufferSize, byref(bytesRead)):
print "Success: Read Memory - ", buffer.value
else:
print "Failed: Read Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.CloseHandle(self.h_process)
windll.kernel32.SetLastError(10000)
def write_memory(self, address, data):
count = c_ulong(0)
length = len(data)
c_data = c_char_p(data[count.value:])
null = c_int(0)
if not windll.kernel32.WriteProcessMemory(self.h_process, address, c_data, length, byref(count)):
print "Failed: Write Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
else:
return False
def virtual_query(self, address):
basic_memory_info = MEMORY_BASIC_INFORMATION()
windll.kernel32.SetLastError(10000)
result = windll.kernel32.VirtualQuery(address, byref(basic_memory_info), byref(basic_memory_info))
if result:
return True
else:
print "Failed: Virtual Query - Error Code: ", windll.kernel32.GetLastError()
main = Main()
address = None
main.launch("C:\Program Files\ProgramFolder\Program.exe")
main.get_handle(main.pid)
#main.write_memory(address, "\x61")
while 1:
print '1 to enter an address'
print '2 to virtual query address'
print '3 to read address'
choice = raw_input('Choice: ')
if choice == '1':
address = raw_input('Enter and address: ')
if choice == '2':
main.virtual_query(address)
if choice == '3':
main.read_memory(address)
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该尝试为您的进程设置调试权限。
在尝试打开/创建进程之前,请使用以下代码一次。
You should try to set debugging privileges to your process.
Use the following code once before you try to Open / Create a process.
也许这会对您有所帮助: 为C++ 中的新对象
Maybe this will help you: Creating a Security Descriptor for a New Object in C++
导致访问被拒绝错误的一个可能原因是运行 WriteProcessMemory 的用户需要具有 DEBUG 权限。
从 Vista 开始,此权限仅对管理员激活,并且仅在使用“以管理员身份运行”运行应用程序时激活。
您可以将权限添加到任何帐户。
One possible reason for your access denied error is that the user under which you run WriteProcessMemory runs needs to have DEBUG privilege.
Starting with Vista, this privilege is only activated for Administrators, and only when running the application with "Run as Admin".
You can add the privilege to any account.
我发现您的代码存在几个问题,并且很难知道哪一个是导致您的确切问题的根本原因。例如,这一行:
应该是这样的:
正如代码所示,每次通过 ctypes 将
address
传递给函数时,您实际上所做的是创建一个临时缓冲区,其中包含键入的字符串由用户并在 Python 进程中传入该缓冲区的地址。绝对不是你想要的。如果我解决了这个问题,那么你的程序似乎在大多数情况下都能工作。根据我有限的测试,大多数(全部?)其余故障都可以通过为
ReadProcessMemory
设置正确的argtypes
来修复。这是我在 ctypes 代码中看到的最大问题,在 Python 中将ctypes.c_voidp
处理为int
会加剧这个问题。如果未指定argtypes
,则所有参数都被视为ctypes.c_int
。有符号整数范围之外的任何内容(例如,具有高位设置的指针或句柄)都会被静默截断。这不是错误的原因,但不是最理想的:
ctypes 模块提供了创建缓冲区的函数:
希望这能让您走上正确的道路。
I see several problems with your code, and it's difficult to know which one is the underlying cause of your exact problem. For example, the line:
Should probably be something like:
As the code stands, every time you pass
address
to a function via ctypes what you are actually doing is creating a temporary buffer which contains exactly the string typed by the user and passing in the address of that buffer in the Python process. Definitely not what you want. If I fix that issue, then your program seems to work most of the time.From my limited testing, most (all?) of the rest of the failures can be fixed by setting the correct
argtypes
forReadProcessMemory
. This is the single biggest issue I see with ctypes code, a problem exacerbated by handlingctypes.c_voidp
asint
in Python. Ifargtypes
is not specified, then all arguments are considered to bectypes.c_int
. Anything outside of the range of signed integer -- a pointer or handle with high bit set, for example -- is silently truncated.Not the cause of your bugs but suboptimal are the lines:
The ctypes module provides functions for creating buffers:
Hopefully this will get you down the right path.
PROCESS_VM_READ
还不够:尝试同时使用PROCESS_VM_WRITE
+PROCESS_VM_OPERATION
。我还收到了错误违规,但进程内存仍然发生了变化。添加 try catch 让你的程序保持活力。对我来说
PROCESS_VM_WRITE
还不够,我还需要添加PROCESS_VM_OPERATION
。PROCESS_VM_READ
is not enough: Try use bothPROCESS_VM_WRITE
+PROCESS_VM_OPERATION
. I also received an error violation but the process memory still changed. Add try catch to keep your program alive.For me
PROCESS_VM_WRITE
was not enough, I needed to addPROCESS_VM_OPERATION
as well.