Python Ctypes Read/WriteProcessMemory() - Error 5/998 Help!

Posted by user299805 on Stack Overflow See other posts from Stack Overflow or by user299805
Published on 2010-03-23T10:56:34Z Indexed on 2010/04/03 0:33 UTC
Read the original article Hit count: 620

Filed under:
|
|

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!

© Stack Overflow or respective owner

Related posts about python

Related posts about readprocessmemory