Re: How come this is different?

eryk sun <[email protected]> Sat, 10 Dec 2016 23:24:37 +0000
Newsgroups gmane.comp.python.ctypes
Message-ID <CACL+1asyv7UV0KbR4Z3jFJA08rAQbsrT=JGOM-m16_Rap8vDOQ@mail.gmail.com>
On Sat, Dec 10, 2016 at 9:30 PM, Michael C
<[email protected]> wrote:
> I am stuck on which line of information to feed to ReadmemoryProcess with
> this, I think I properly retrieved the information from Virtualqueryex

Here's an example that uses VirtualQueryEx to determine whether the
specified address is allocated and readable. If so, it reads up to
`count` double-precision floats via ReadProcessMemory, but it won't
read past the allocated region size.

    import ctypes
    from ctypes import wintypes

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

    PROCESS_VM_READ           = 0x0010
    PROCESS_QUERY_INFORMATION = 0x0400

    MEM_COMMIT  = 0x00001000
    MEM_RESERVE = 0x00002000
    MEM_FREE    = 0x00010000
    MEM_PRIVATE = 0x00020000
    MEM_MAPPED  = 0x00040000
    MEM_IMAGE   = 0x01000000

    PAGE_NOACCESS          = 0x00000001
    PAGE_READONLY          = 0x00000002
    PAGE_READWRITE         = 0x00000004
    PAGE_WRITECOPY         = 0x00000008
    PAGE_EXECUTE           = 0x00000010
    PAGE_EXECUTE_READ      = 0x00000020
    PAGE_EXECUTE_READWRITE = 0x00000040
    PAGE_EXECUTE_WRITECOPY = 0x00000080
    PAGE_GUARD             = 0x00000100
    PAGE_NOCACHE           = 0x00000200
    PAGE_WRITECOMBINE      = 0x00000400
    PAGE_TARGETS_INVALID   = 0x40000000

    if not hasattr(wintypes, 'PVOID'):
        wintypes.PVOID = wintypes.LPVOID

    if not hasattr(wintypes, 'SIZE_T'):
        wintypes.SIZE_T = ctypes.c_size_t

    if not hasattr(wintypes, 'PSIZE_T'):
        wintypes.PSIZE_T = ctypes.POINTER(wintypes.SIZE_T)

    class MEMORY_BASIC_INFORMATION(ctypes.Structure):
        _fields_ = (('BaseAddress',       wintypes.PVOID),
                    ('AllocationBase',    wintypes.PVOID),
                    ('AllocationProtect', wintypes.DWORD),
                    ('RegionSize',        wintypes.SIZE_T),
                    ('State',             wintypes.DWORD),
                    ('Protect',           wintypes.DWORD),
                    ('Type',              wintypes.DWORD))

    PMEMORY_BASIC_INFORMATION = ctypes.POINTER(MEMORY_BASIC_INFORMATION)

    def _check_zero(result, func, args):
        """ Check for zero or NULL return value. """
        if not result:
            raise ctypes.WinError(ctypes.get_last_error())
        return args

    # https://msdn.microsoft.com/en-us/library/ms683179
    kernel32.GetCurrentProcess.restype = wintypes.HANDLE

    # https://msdn.microsoft.com/en-us/library/ms684320
    kernel32.OpenProcess.errcheck = _check_zero
    kernel32.OpenProcess.restype = wintypes.HANDLE

    # https://msdn.microsoft.com/en-us/library/ms680553
    kernel32.ReadProcessMemory.errcheck = _check_zero
    kernel32.ReadProcessMemory.argtypes = (
        wintypes.HANDLE,  # _In_  hProcess
        wintypes.LPCVOID, # _In_  lpBaseAddress
        wintypes.LPVOID,  # _Out_ lpBuffer
        wintypes.SIZE_T,  # _In_  nSize
        wintypes.PSIZE_T) # _Out_ lpNumberOfBytesRead

    # https://msdn.microsoft.com/en-us/library/aa366907
    kernel32.VirtualQueryEx.errcheck = _check_zero
    kernel32.VirtualQueryEx.restype = wintypes.SIZE_T
    kernel32.VirtualQueryEx.argtypes = (
        wintypes.HANDLE,           # _In_     hProcess
        wintypes.LPCVOID,          # _In_opt_ lpAddress
        PMEMORY_BASIC_INFORMATION, # _Out_    lpBuffer
        wintypes.SIZE_T)           # _In_     dwLength

    if __name__ == '__main__':
        import sys

        dtype = ctypes.c_double

        if len(sys.argv) == 4:
            ph = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION |
                    PROCESS_VM_READ, False, int(sys.argv[1]))
            address = int(sys.argv[2], 16)
            count = int(sys.argv[3])
        elif len(sys.argv) == 1:
            ph = kernel32.GetCurrentProcess()
            count = 10
            source_array = (dtype * count)(*range(10))
            address = ctypes.addressof(source_array)
        else:
            sys.exit('Usage: %s pid address count' % sys.argv[0])

        mbi = MEMORY_BASIC_INFORMATION()
        kernel32.VirtualQueryEx(ph, address, ctypes.byref(mbi),
            ctypes.sizeof(mbi))

        if mbi.State & MEM_FREE:
            sys.exit('Address not allocated')
        if mbi.State & MEM_RESERVE:
            sys.exit('Address reserved but not committed')
        if mbi.Protect & PAGE_NOACCESS:
            sys.exit('Address not accessible')

        block_size = min(mbi.RegionSize - (address - mbi.BaseAddress),
                         ctypes.sizeof(dtype) * count)
        address_list = range(address, address + block_size,
                             ctypes.sizeof(dtype))

        input('Press enter to list %d values, or Ctrl+Break to quit\n'
              % len(address_list))

        data = dtype()
        for address in address_list:
            kernel32.ReadProcessMemory(ph, address, ctypes.byref(data),
                ctypes.sizeof(data), None)
            print('%x: %f' % (address, data.value))

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/xeonphi