Re: How come this is different?

eryk sun <[email protected]> Sat, 10 Dec 2016 14:30:10 +0000
Newsgroups gmane.comp.python.ctypes
Message-ID <CACL+1av-n1Ug5Ecx3HJ-seuH=_VU3rxJbGs-0iDfTXjZKA7xsw@mail.gmail.com>
On Sat, Dec 10, 2016 at 12:12 AM, Michael C
<[email protected]> wrote:
> Here is my entire current work in progress:
>
> #import modules
> import ctypes
> import time

[snip]

Here's a working example for ReadProcessMemory.

    import ctypes
    from ctypes import wintypes

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

    PROCESS_VM_READ           = 0x0010
    PROCESS_QUERY_INFORMATION = 0x0400

    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)

    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

    if __name__ == '__main__':
        import sys

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

        address_list = range(base_address, base_address + block_size,
                             ctypes.sizeof(wintypes.DWORD))
        data = wintypes.DWORD()

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

This script defaults to a demo that reads an array of DWORD values
from its own process. You can also provide it the PID, base address,
and block size to read from another process. You could extend this
with another option to configure the type of data read (e.g. char,
float) based on simple ctypes format codes, e.g. "L" for a DWORD,
where "L" is the value of `wintypes.DWORD._type_`. Or instead follow
WinDbg conventions (e.g. db, dw, dd).

Note that I assign an errcheck function for the OpenProcess and
ReadProcessMemory function pointers. In this case both use the same
_check_zero function, which raises an OSError (or WindowsError in 2.x)
when the call fails. Idiomatic Python programming uses exceptions for
error handling and resource management (i.e. try/except/finally). Get
the error code from the exception's `winerror` attribute when handling
it. Here's the complete list of WinAPI error codes:

https://msdn.microsoft.com/en-us/library/ms681381

------------------------------------------------------------------------------
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