Memory scanner for any program in Python - python

I am trying to create a memory scanner. similar to Cheat Engine. but only for extract information.
I know how to get the pid (in this case is "notepad.exe"). But I don't have any Idea about how to know wicht especific adress belong to the program that I am scanning.
Trying to looking for examples. I could see someone it was trying to scan every adress since one point to other. But it's to slow. Then I try to create a batch size (scan a part of memory and not one by one each adress). The problem is if the size is to short. still will take a long time. and if it is to long, is possible to lose many adress who are belong to the program. Because result from ReadMemoryScan is False in the first Adress, but It can be the next one is true. Here is my example.
import ctypes as c
from ctypes import wintypes as w
import psutil
from sys import stdout
write = stdout.write
import numpy as np
def get_client_pid(process_name):
pid = None
for proc in psutil.process_iter():
if proc.name() == process_name:
pid = int(proc.pid)
print(f"Found '{process_name}' PID = ", pid,f" hex_value = {hex(pid)}")
break
if pid == None:
print('Program Not found')
return pid
pid = get_client_pid("notepad.exe")
if pid == None:
sys.exit()
k32 = c.WinDLL('kernel32', use_last_error=True)
OpenProcess = k32.OpenProcess
OpenProcess.argtypes = [w.DWORD,w.BOOL,w.DWORD]
OpenProcess.restype = w.HANDLE
ReadProcessMemory = k32.ReadProcessMemory
ReadProcessMemory.argtypes = [w.HANDLE,w.LPCVOID,w.LPVOID,c.c_size_t,c.POINTER(c.c_size_t)]
ReadProcessMemory.restype = w.BOOL
GetLastError = k32.GetLastError
GetLastError.argtypes = None
GetLastError.restype = w.DWORD
CloseHandle = k32.CloseHandle
CloseHandle.argtypes = [w.HANDLE]
CloseHandle.restype = w.BOOL
processHandle = OpenProcess(0x10, False, int(pid))
# addr = 0x0FFFFFFFFFFF
data = c.c_ulonglong()
bytesRead = c.c_ulonglong()
start = 0x000000000000
end = 0x7fffffffffff
batch_size = 2**13
MemoryData = np.zeros(batch_size, 'l')
Size = MemoryData.itemsize*MemoryData.size
index = 0
Data_address = []
for c_adress in range(start,end,batch_size):
result = ReadProcessMemory(processHandle,c.c_void_p(c_adress), MemoryData.ctypes.data,
Size, c.byref(bytesRead))
if result: # Save adress
Data_address.extend(list(range(c_adress,c_adress+batch_size)))
e = GetLastError()
CloseHandle(processHandle)
I decided from 0x000000000000 to 0x7fffffffffff Because cheat engine scan this size. I am still a begginer with this kind of this about memory scan. maybe there are things that I can do to improve the efficiency.

I suggest you take advantage of existing python libraries that can analyse Windows 10 memory.
I'm no specialist but I've found Volatility. Seems to be pretty useful for your problem.
For running that tool you need Python 2 (Python 3 won't work).
For running python 2 and 3 in the same Windows 10 machine, follow this tutorial (The screenshots are in Spanish but it can easily be followed).
Then see this cheat sheet with main commands. You can dump the memory and then operate on the file.
Perhaps this leads you to the solution :) At least the most basic command pslist dumps all the running processes addresses.

psutil has proc.memory_maps()
pass the result as map to this function
TargetProcess eaxample 'Calculator.exe'
def get_memSize(self,TargetProcess,map):
for m in map:
if TargetProcess in m.path:
memSize= m.rss
break
return memSize
if you use this function, it returns the memory size of your Target Process
my_pid is the pid for 'Calculator.exe'
def getBaseAddressWmi(self,my_pid):
PROCESS_ALL_ACCESS = 0x1F0FFF
processHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, my_pid)
modules = win32process.EnumProcessModules(processHandle)
processHandle.close()
base_addr = modules[0] # for me it worked to select the first item in list...
return base_addr
to get the base address of your prog
so you search range is from base_addr to base_addr + memSize

Related

Why does ReadWriteMemory return two different addresses?

I am trying to get the 64-bit memory address of a variable, using a pointer created with CheatEngine.
Here are the pointers:
from ReadWriteMemory import ReadWriteMemory
from numpy import int64
import win32api
import win32process
import win32con
import ctypes as c
rwm = ReadWriteMemory()
process = rwm.get_process_by_name("NAME.exe")
process.open()
def get_process_by_namee(process_name):
"""Finds the process id of the given
process name and returns the process id and its base address."""
process_name = process_name.lower()
# Enumerate all processes
processes = win32process.EnumProcesses()
for process_id in processes:
# If process_id is the same as this program, skip it
if process_id == -1:
continue
# Try to read the process memory
try:
h_process = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, True, process_id)
# Try to read the modules of the process
try:
# modules is an array of base addresses of each module
modules = win32process.EnumProcessModules(h_process)
for base_address in modules:
# Get the name of the module
name = str(win32process.GetModuleFileNameEx(h_process, base_address))
# Compare it to the name of your program
if name.lower().find(process_name) != -1:
return process_id, base_address
finally:
win32api.CloseHandle(h_process)
except:
pass
# this is the prefered imagebase + specific offset for the variable
baseaddress = c.c_uint64(0x00007FF7BBE80000 + 0x0218F138)
boostPointer1 = process.get_pointer(c.c_uint64(baseaddress), offsets=[0x3F0, 0x0, 0x60, 0x178, 0x0, 0xC0, 0xA8C])
boostPointer2 = process.get_pointer(c.c_uint64(0x1B8CC0FFC24))
boost_count = process.read(boostPointer1)
print (boost_count)
When i create a pointer in CheatEngine with the offsets and stuff of boostPointer1, i get the address, which i put into boostpointer2 (0x1B8CC0FFC24)
However, when i read boostPointer1 and boostPointer2, i get different results, leading to a different memory spot being read. Why does boostPointer1 return a different Pointer, than boostPointer2, and how can this be fixed?

Reading Memory Address from a process with a Static Address and Offsets in Python

I'm trying to read another process' memory in Python and I have the static address of the program and all the offsets. I'm using the win32api to do this. I can already read a process' memory with an address without offsets but I don't know how to use offsets.
I've already tried the script in this answer but it returns -1. I've changed the PROCESS_ALL_ACCESS to win32con.PROCESS_VM_READ and even then it returns -1.
How do I use the offsets with ReadProcessMemory?
Here is the code I'm using:
import win32api
import win32process
import win32con
import ctypes
import ctypes.wintypes as wintypes
def get_process_by_name(process_name):
"""Find the process id of the given
process name and returns the process id."""
process_name = process_name.lower()
# Enumerate all processes
processes = win32process.EnumProcesses()
for process_id in processes:
# If process_id is the same as this program, skip it
if process_id == -1:
continue
# Try to read the process memory
try:
p_handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, True, process_id)
# Try to read the modules of the process
try:
modules = win32process.EnumProcessModules(p_handle)
for module_id in modules:
name = str(win32process.GetModuleFileNameEx(p_handle, module_id))
if name.lower().find(process_name) != -1:
return process_id
finally:
win32api.CloseHandle(p_handle)
except:
pass
def read_process_memory(process_id, address, offsets, size_of_data=4):
p_handle = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_VM_READ, False, p_id)
data = ctypes.c_uint(size_of_data)
bytesRead = ctypes.c_uint(size_of_data)
current_address = address
if offsets:
# Do something to the offsets
ctypes.windll.kernel32.ReadProcessMemory(p_handle, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))
else:
ctypes.windll.kernel32.ReadProcessMemory(p_handle, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))
# Close the handle to the process
ctypes.windll.kernel32.CloseHandle(p_handle)
return data.value
p_id = get_process_by_name("program.exe")
# Without offsets it works fine
address = 0x2ADB1818
val = read_process_memory(p_id, address, None)
print(val)
# Does not point to the correct address
address = 0x00571160
offsets = [0xD84, 0x1B8, 0x38, 0x5C, 0x24, 0xF4, 0x1D08]
for offset in offsets:
address += offset
val = read_process_memory(p_id, address, offsets)
print(val)
I've figured out what I was missing. I've been interpreting the addresses wrong. They are pointers to the addresses and so, when using offsets I need to read them, and add them to one another to get access to the value I want to read. Also, I needed to use the base address of the program, for which I just needed to return the value of the module.
Here is the above script with the necessary changes to read a process' memory with offsets:
import win32api
import win32process
import win32con
import ctypes
def get_process_by_name(process_name):
"""Finds the process id of the given
process name and returns the process id and its base address."""
process_name = process_name.lower()
# Enumerate all processes
processes = win32process.EnumProcesses()
for process_id in processes:
# If process_id is the same as this program, skip it
if process_id == -1:
continue
# Try to read the process memory
try:
h_process = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, True, process_id)
# Try to read the modules of the process
try:
# modules is an array of base addresses of each module
modules = win32process.EnumProcessModules(h_process)
for base_address in modules:
# Get the name of the module
name = str(win32process.GetModuleFileNameEx(h_process, base_address))
# Compare it to the name of your program
if name.lower().find(process_name) != -1:
return process_id, base_address
finally:
win32api.CloseHandle(h_process)
except:
pass
def read_process_memory(process_id, address, offsets=[]):
"""Read a process' memory based on its process id, address and offsets.
Returns the address without offsets and the value."""
# The handle to the program's process
# This will allow to use ReadProcessMemory
h_process = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_VM_READ, False, p_id)
# This is a pointer to the data you want to read
# Use `data.value` to get the value at this pointer
# In this case, this value is an Integer with 4 bytes
data = ctypes.c_uint(0)
# Size of the variable, it usually is 4 bytes
bytesRead = ctypes.c_uint(0)
# Starting address
current_address = address
if offsets:
# Append a new element to the offsets array
# This will allow you to get the value at the last offset
offsets.append(None)
for offset in offsets:
# Read the memory of current address using ReadProcessMemory
ctypes.windll.kernel32.ReadProcessMemory(h_process, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))
# If current offset is `None`, return the value of the last offset
if not offset:
return current_address, data.value
else:
# Replace the address with the new data address
current_address = data.value + offset
else:
# Just read the single memory address
ctypes.windll.kernel32.ReadProcessMemory(h_process, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))
# Close the handle to the process
ctypes.windll.kernel32.CloseHandle(h_process)
# Return a pointer to the value and the value
# The pointer will be used to write to the memory
return current_address, data.value
# Open the process
p_id, base_address = get_process_by_name("program.exe")
# The static address needs the program base_address
address = base_address + 0x00571160
offsets = [0xD84, 0x1B8, 0x38, 0x5C, 0x24, 0xF4, 0x1D08]
pointer_value, value = read_process_memory(p_id, address, offsets)
print(f"(Static Address) Value: {value}")
# Re-reading the memory with the last pointer
pointer_value, value = read_process_memory(p_id, pointer_value, None)
print(f"(Dynamic Address) Value: {value}")

disorder in multiprocessing subprocess

After running some compuations nicely in linear fashion with a moderator script (cf. below) calling an inner one performing the computation, I struggle
to bring it to execution when trying it with multiprocessing. It seems that each CPU core is running through this list set (testRegister) and launches a computation even if an other core already performed this task earlier (in the same session). How can I prevent this chaotic behaviour? It is my first time attempting calling multiple processors by Python.
Correction: The initial post did not show that the test is a string consisting calling "the inner script" with varying parameters m1 and m2 beside fixed arguments arg1 and arg2 belonging solely to this "inner script".
#!/usr/bin/env python3
import os
import subprocess as sub
import sys
import multiprocessing
fileRegister = []
testRegister = []
def fileCollector():
for file in os.listdir("."):
if file.endswith(".xyz"):
fileRegister.append(file)
fileRegister.sort()
return fileRegister
def testSetup():
data = fileRegister
while len(data) > 1:
for entry in fileRegister[1:]:
m0 = str(fileRegister[0])
m1 = str(entry)
test = str("python foo.py ") + str(m1) + str(" ") + str(m2) +\
str(" --arg1 --arg2") # formulate test condition
testRegister.append(test)
testRegister.sort()
del data[0]
return testRegister
def shortAnalysator():
for entry in testRegister:
print(str(entry))
sub.call(entry, shell=True)
del testRegister[0]
def polyAnalysator():
# apparently each CPU core works as if the register were not shared
# reference: https://docs.python.org/3.7/library/multiprocessing.html
if __name__ == '__main__':
jobs = []
for i in range(3): # safety marging to not consume all CPU
p = multiprocessing.Process(target=shortAnalysator)
jobs.append(p)
p.start()
fileCollector()
testSetup()
shortAnalysator() # proceeding expectably on one CPU (slow)
# polyAnalysator() # causing irritation
sys.exit()```
Your polyAnalysator is running the shortAnalysator three times. Try changing your polyAnalysator as follows, and add the f method. This uses the multiprocessing Pool:
from multiprocessing import Pool
def f(test):
sub.call(test, shell=True)
def polyAnalysator():
# apparently each CPU core works as if the register were not shared
# reference: https://docs.python.org/3.7/library/multiprocessing.html
with Pool(3) as p:
p.map(f, testRegister)

How do I gather performance metrics for GDI and user Objects using python

Think this is my first question I have asked on here normally find all the answers I need (so thanks in advance)
ok my problem I have written a python program that will in threads monitor a process and output the results to a csv file for later. This code is working great I am using win32pdhutil for the counters and WMI, Win32_PerfRawData_PerfProc_Process for the CPU %time. I have now been asked to monitor a WPF application and specifically monitor User objects and GDI objects.
This is where I have a problem, it is that i can't seem to find any python support for gathering metrics on these two counters. these two counters are easily available in the task manager I find it odd that there is very little information on these two counters. I am specifically looking at gathering these to see if we have a memory leak, I don't want to install anything else on the system other than python that is already installed. Please can you peeps help with finding a solution.
I am using python 3.3.1, this will be running on a windows platform (mainly win7 and win8)
This is the code i am using to gather the data
def gatherIt(self,whoIt,whatIt,type,wiggle,process_info2):
#this is the data gathering function thing
data=0.0
data1="wobble"
if type=="counter":
#gather data according to the attibutes
try:
data = win32pdhutil.FindPerformanceAttributesByName(whoIt, counter=whatIt)
except:
#a problem occoured with process not being there not being there....
data1="N/A"
elif type=="cpu":
try:
process_info={}#used in the gather CPU bassed on service
for x in range(2):
for procP in wiggle.Win32_PerfRawData_PerfProc_Process(name=whoIt):
n1 = int(procP.PercentProcessorTime)
d1 = int(procP.Timestamp_Sys100NS)
#need to get the process id to change per cpu look...
n0, d0 = process_info.get (whoIt, (0, 0))
try:
percent_processor_time = (float (n1 - n0) / float (d1 - d0)) *100.0
#print whoIt, percent_processor_time
except ZeroDivisionError:
percent_processor_time = 0.0
# pass back the n0 and d0
process_info[whoIt] = (n1, d1)
#end for loop (this should take into account multiple cpu's)
# end for range to allow for a current cpu time rather that cpu percent over sampleint
if percent_processor_time==0.0:
data=0.0
else:
data=percent_processor_time
except:
data1="N/A"
else:
#we have done something wrong so data =0
data1="N/A"
#endif
if data == "[]":
data=0.0
data1="N/A"
if data == "" :
data=0.0
data1="N/A"
if data == " ":
data=0.0
data1="N/A"
if data1!="wobble" and data==0.0:
#we have not got the result we were expecting so add a n/a
data=data1
return data
cheers
edited for correct cpu timings issue if anyone tried to run it :D
so after a long search i was able to mash something together that gets me the info needed.
import time
from ctypes import *
from ctypes.wintypes import *
import win32pdh
# with help from here http://coding.derkeiler.com/Archive/Python/comp.lang.python/2007-10/msg00717.html
# the following has been mashed together to get the info needed
def GetProcessID(name):
object = "Process"
items, instances = win32pdh.EnumObjectItems(None, None, object, win32pdh.PERF_DETAIL_WIZARD)
val = None
if name in instances :
tenQuery = win32pdh.OpenQuery()
tenarray = [ ]
item = "ID Process"
path = win32pdh.MakeCounterPath( ( None, object, name, None, 0, item ) )
tenarray.append( win32pdh.AddCounter( tenQuery, path ) )
win32pdh.CollectQueryData( tenQuery )
time.sleep( 0.01 )
win32pdh.CollectQueryData( tenQuery )
for tencounter in tenarray:
type, val = win32pdh.GetFormattedCounterValue( tencounter, win32pdh.PDH_FMT_LONG )
win32pdh.RemoveCounter( tencounter )
win32pdh.CloseQuery( tenQuery )
return val
processIDs = GetProcessID('OUTLOOK') # Remember this is case sensitive
PQI = 0x400
#open a handle on to the process so that we can query it
OpenProcessHandle = windll.kernel32.OpenProcess(PQI, 0, processIDs)
# OK so now we have opened the process now we want to query it
GR_GDIOBJECTS, GR_USEROBJECTS = 0, 1
print(windll.user32.GetGuiResources(OpenProcessHandle, GR_GDIOBJECTS))
print(windll.user32.GetGuiResources(OpenProcessHandle, GR_USEROBJECTS))
#so we have what we want we now close the process handle
windll.kernel32.CloseHandle(OpenProcessHandle)
hope that helps
For GDI count, I think a simpler, cleaner monitoring script is as follows:
import time, psutil
from ctypes import *
def getPID(processName):
for proc in psutil.process_iter():
try:
if processName.lower() in proc.name().lower():
return proc.pid
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return None;
def getGDIcount(PID):
PH = windll.kernel32.OpenProcess(0x400, 0, PID)
GDIcount = windll.user32.GetGuiResources(PH, 0)
windll.kernel32.CloseHandle(PH)
return GDIcount
PID = getPID('Outlook')
while True:
GDIcount = getGDIcount(PID)
print(f"{time.ctime()}, {GDIcount}")
time.sleep(1)

Use Python to extract ListView items from another application

I have an application with a ListView ('SysListView32') control, from which I would like to extract data. The control has 4 columns, only textual data.
I have been playing around the following lines (found online somewhere):
VALUE_LENGTH = 256
bufferlength_int=struct.pack('i', VALUE_LENGTH)
count = win32gui.SendMessage(TargetHwnd, commctrl.LVM_GETITEMCOUNT, 0, 0)
for ItemIndex in range(count):
valuebuffer = array.array('c',bufferlength_int + " " * (VALUE_LENGTH - len(bufferlength_int)))
ListItems = win32gui.SendMessage(TargetHwnd, commctrl.LVM_GETITEMTEXT, ItemIndex, valuebuffer)
[The above code may not be entirely executable, as I stripped it from irrelevant stuff. but the gist is certainly here.]
This seems to run ok but I must be doing something wrong - I get all sorts of mostly-zeroed data buffers in return, and none of the actual text contents I was looking for.
Any suggestions?
Thanks,
Yonatan
Well, it turns out I was wrong on several points there. However it is possible to do by allocating memory inside the target process, constructing the required struct (LVITEM) there, sending the message and reading back the result from the buffer allocated in said process.
For the sake of completeness, I attach a code example for reading SysListView32 items from a foreign process, given a window handle of the control.
from win32con import PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE, MEM_RELEASE,\
PROCESS_ALL_ACCESS
from commctrl import LVM_GETITEMTEXT, LVM_GETITEMCOUNT
import struct
import ctypes
import win32api
import win32gui
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx
OpenProcess = ctypes.windll.kernel32.OpenProcess
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
memcpy = ctypes.cdll.msvcrt.memcpy
def readListViewItems(hwnd, column_index=0):
# Allocate virtual memory inside target process
pid = ctypes.create_string_buffer(4)
p_pid = ctypes.addressof(pid)
GetWindowThreadProcessId(hwnd, p_pid) # process owning the given hwnd
hProcHnd = OpenProcess(PROCESS_ALL_ACCESS, False, struct.unpack("i",pid)[0])
pLVI = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
pBuffer = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
# Prepare an LVITEM record and write it to target process memory
lvitem_str = struct.pack('iiiiiiiii', *[0,0,column_index,0,0,pBuffer,4096,0,0])
lvitem_buffer = ctypes.create_string_buffer(lvitem_str)
copied = ctypes.create_string_buffer(4)
p_copied = ctypes.addressof(copied)
WriteProcessMemory(hProcHnd, pLVI, ctypes.addressof(lvitem_buffer), ctypes.sizeof(lvitem_buffer), p_copied)
# iterate items in the SysListView32 control
num_items = win32gui.SendMessage(hwnd, LVM_GETITEMCOUNT)
item_texts = []
for item_index in range(num_items):
win32gui.SendMessage(hwnd, LVM_GETITEMTEXT, item_index, pLVI)
target_buff = ctypes.create_string_buffer(4096)
ReadProcessMemory(hProcHnd, pBuffer, ctypes.addressof(target_buff), 4096, p_copied)
item_texts.append(target_buff.value)
VirtualFreeEx(hProcHnd, pBuffer, 0, MEM_RELEASE)
VirtualFreeEx(hProcHnd, pLVI, 0, MEM_RELEASE)
win32api.CloseHandle(hProcHnd)
return item_texts
If the control is in the same process as your code, it should work. If it's in a different process (as "another application" suggests), then this doesn't work (or at least it shouldn't). Check the error codes, you should get something along the lines of "permission denied": Applications can't see into each others memory.

Categories