Python Readprocessmemory Not Reading Enough Bytes
Solution 1:
The expression b'.'*4
created the constant '....'
in the code object for your module. This constant is an object like any other in Python, except it's supposed to be immutable. You violated that assumption by using ctypes. For example:
>>>from ctypes import *>>>deff():... s = b'.'*4... buf = c_char_p(s)... memset(buf, 0, 1)...>>>f.__code__.co_consts
(None, '.', 4, 0, 1, '....')
>>>c_char_p(f.__code__.co_consts[5]).value
'....'
>>>f() # set the first character to "\x00">>>f.__code__.co_consts
(None, '.', 4, 0, 1, '\x00...')
>>>c_char_p(f.__code__.co_consts[5]).value
''
The value
descriptor of a c_char_p
expects the buffer to be a null-terminated string. With the first byte mutated to 0, value
returns an empty string. Now look at the value of 191 packed as a little-endian, unsigned long
:
>>>import struct>>>struct.pack("<L", 191)
'\xbf\x00\x00\x00'
That should explain why bufferSize
became 1 on the 2nd pass.
If the string had been interned, you could either crash the interpreter or render it unusable. Most strings used within the CPython API are interned, as are names of modules, classes, functions, attributes, and variables. For example:
>>>from ctypes import *>>>import numbers>>>s = 'numbers'>>>b = c_char_p(s)>>>r = memset(b, 100, 1)>>>s
'dumbers'
>>>numbers.Number
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'numbers' is not defined
>>>globals()[s].Number
<class 'numbers.Number'>
create_string_buffer
is a convenience function to create and set a char
array in one pass:
>>>b1 = create_string_buffer('test1')>>>type(b1)
<class 'ctypes.c_char_Array_6'>
>>>b1.value
'test1'
>>>b2 = (c_char * 6)()>>>b2.value = 'test2'>>>type(b2)
<class 'ctypes.c_char_Array_6'>
>>>b2.value
'test2'
>>>b2.raw
'test2\x00'
You could also have passed a reference to an unsigned long
instead:
value = c_ulong()
bytesRead = c_ulong()
rpm(ph, addy, byref(value), sizeof(value), byref(bytesRead))
Another example violating the immutability assumption. Integers less than 256 are cached, i.e. code that uses them always refers to the same set of objects. So if you mutate one of them, it affects the entire system:
>>>offset = sizeof(c_size_t)*2>>>addr = id(200) + offset>>>n = c_int.from_address(addr)>>>n
c_long(200)
>>>n.value = 2000000>>>>>>200 + 1
2000001
Solution 2:
Okay, well I figured it out. I needed to use ctypes.create_string_buffer(init_or_size[, size])
instead of the c_char_p
that I tried.
The working code:
from time import sleep
from ctypes import *
from struct import *
pid = 0x0D50
op = windll.kernel32.OpenProcess
rpm = windll.kernel32.ReadProcessMemory
ch = windll.kernel32.CloseHandle
PAA = 0x1F0FFF
addy = 0x543A88F0
ph = op(PAA,False,int(pid)) #program handle
lastvalue = 0whileTrue:
buff = create_string_buffer(4)
bufferSize = (sizeof(buff))
bytesRead = c_ulong(0)
if rpm(ph,addy,buff,bufferSize,byref(bytesRead)):
value = unpack('I',buff)[0]
if lastvalue != value:
print value
print bytesRead
lastvalue = value
sleep(.01)
Post a Comment for "Python Readprocessmemory Not Reading Enough Bytes"