Python Ctypes Read/WriteProcessMemory() - 错误 5/998 帮助!

发布于 2024-08-26 09:05:46 字数 6034 浏览 12 评论 0原文

请不要害怕,但是如果您熟悉 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如痴如狂 2024-09-02 09:05:46

您应该尝试为您的进程设置调试权限。
在尝试打开/创建进程之前,请使用以下代码一次。

class TOKEN_PRIVILEGES( Structure ):
    _fields_ = [
            ('PrivilegeCount',  c_uint),
            ('Luid',            LUID),
            ('Attributes',      c_uint) ]

OpenProcessToken = windll.advapi32.OpenProcessToken
OpenProcessToken.argtypes = [
    c_int,      # HANDLE ProcessHandle
    c_uint,     # DWORD DesiredAccess
    c_void_p ]  # PHANDLE TokenHandle
OpenProcessToken.restype = ErrorIfZero

AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
AdjustTokenPrivileges.argtypes = [
    c_int,      # HANDLE TokenHandle
    c_int,      # BOOL DisableAllPrivileges
    c_void_p,   # PTOKEN_PRIVILEGES NewState
    c_uint,     # DWORD BufferLength
    c_void_p,   # PTOKEN_PRIVILEGES PreviousState
    c_void_p ]  # PDWORD ReturnLength
AdjustTokenPrivileges.restype = ErrorIfZero

LookupPrivilegeValue = windll.advapi32.LookupPrivilegeValueA
LookupPrivilegeValue.argtypes = [
c_char_p,   # LPCTSTR lpSystemName
c_char_p,   # LPCTSTR lpName
c_void_p ]  # PLUID lpLuid
LookupPrivilegeValue.restype = ErrorIfZero

access_token = c_int(0)
privileges = TOKEN_PRIVILEGES()

OpenProcessToken( GetCurrentProcess(), win32con.TOKEN_QUERY | win32con.TOKEN_ADJUST_PRIVILEGES, byref(access_token) )
access_token = access_token.value
LookupPrivilegeValue( None, "SeDebugPrivilege", byref(privileges.Luid) )
privileges.PrivilegeCount = 1
privileges.Attributes = 2
AdjustTokenPrivileges(
        access_token,
        0,
        byref(privileges),
        0,
        None,
        None )
CloseHandle( access_token )

You should try to set debugging privileges to your process.
Use the following code once before you try to Open / Create a process.

class TOKEN_PRIVILEGES( Structure ):
    _fields_ = [
            ('PrivilegeCount',  c_uint),
            ('Luid',            LUID),
            ('Attributes',      c_uint) ]

OpenProcessToken = windll.advapi32.OpenProcessToken
OpenProcessToken.argtypes = [
    c_int,      # HANDLE ProcessHandle
    c_uint,     # DWORD DesiredAccess
    c_void_p ]  # PHANDLE TokenHandle
OpenProcessToken.restype = ErrorIfZero

AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
AdjustTokenPrivileges.argtypes = [
    c_int,      # HANDLE TokenHandle
    c_int,      # BOOL DisableAllPrivileges
    c_void_p,   # PTOKEN_PRIVILEGES NewState
    c_uint,     # DWORD BufferLength
    c_void_p,   # PTOKEN_PRIVILEGES PreviousState
    c_void_p ]  # PDWORD ReturnLength
AdjustTokenPrivileges.restype = ErrorIfZero

LookupPrivilegeValue = windll.advapi32.LookupPrivilegeValueA
LookupPrivilegeValue.argtypes = [
c_char_p,   # LPCTSTR lpSystemName
c_char_p,   # LPCTSTR lpName
c_void_p ]  # PLUID lpLuid
LookupPrivilegeValue.restype = ErrorIfZero

access_token = c_int(0)
privileges = TOKEN_PRIVILEGES()

OpenProcessToken( GetCurrentProcess(), win32con.TOKEN_QUERY | win32con.TOKEN_ADJUST_PRIVILEGES, byref(access_token) )
access_token = access_token.value
LookupPrivilegeValue( None, "SeDebugPrivilege", byref(privileges.Luid) )
privileges.PrivilegeCount = 1
privileges.Attributes = 2
AdjustTokenPrivileges(
        access_token,
        0,
        byref(privileges),
        0,
        None,
        None )
CloseHandle( access_token )
很快妥协 2024-09-02 09:05:46

也许这会对您有所帮助: 为C++ 中的新对象

金橙橙 2024-09-02 09:05:46

导致访问被拒绝错误的一个可能原因是运行 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.

泡沫很甜 2024-09-02 09:05:46

我发现您的代码存在几个问题,并且很难知道哪一个是导致您的确切问题的根本原因。例如,这一行:

address = raw_input('Enter and address: ')

应该是这样的:

address = long(raw_input('Enter and address: '), 0)

正如代码所示,每次通过 ctypes 将 address 传递给函数时,您实际上所做的是创建一个临时缓冲区,其中包含键入的字符串由用户并在 Python 进程中传入该缓冲区的地址。绝对不是你想要的。如果我解决了这个问题,那么你的程序似乎在大多数情况下都能工作。

根据我有限的测试,大多数(全部?)其余故障都可以通过为 ReadProcessMemory 设置正确的 argtypes 来修复。这是我在 ctypes 代码中看到的最大问题,在 Python 中将 ctypes.c_voidp 处理为 int 会加剧这个问题。如果未指定argtypes,则所有参数都被视为ctypes.c_int。有符号整数范围之外的任何内容(例如,具有高位设置的指针或句柄)都会被静默截断。

这不是错误的原因,但不是最理想的:

buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)

ctypes 模块提供了创建缓冲区的函数:

bufferSize = 32
buffer = ctypes.create_string_buffer(bufferSize)

希望这能让您走上正确的道路。

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:

address = raw_input('Enter and address: ')

Should probably be something like:

address = long(raw_input('Enter and address: '), 0)

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 for ReadProcessMemory. This is the single biggest issue I see with ctypes code, a problem exacerbated by handling ctypes.c_voidp as int in Python. If argtypes is not specified, then all arguments are considered to be ctypes.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:

buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)

The ctypes module provides functions for creating buffers:

bufferSize = 32
buffer = ctypes.create_string_buffer(bufferSize)

Hopefully this will get you down the right path.

月寒剑心 2024-09-02 09:05:46

PROCESS_VM_READ 还不够:尝试同时使用 PROCESS_VM_WRITE + PROCESS_VM_OPERATION。我还收到了错误违规,但进程内存仍然发生了变化。添加 try catch 让你的程序保持活力。

PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008
PROCESS_ALL_ACCESS = 0x1F0FFF

对我来说 PROCESS_VM_WRITE 还不够,我还需要添加 PROCESS_VM_OPERATION

PROCESS_VM_READ is not enough: Try use both PROCESS_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.

PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008
PROCESS_ALL_ACCESS = 0x1F0FFF

For me PROCESS_VM_WRITE was not enough, I needed to add PROCESS_VM_OPERATION as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文