How to know the complete memory of another program ?
-
White_Leaf
- New User

- Posts: 5
- Joined: Sat May 05, 2007 12:35 pm
How to know the complete memory of another program ?
Hello
I've read a lot about trainers, and already made own ones. But everytime, you use specific memory adresses to patch (which you have to know of course). But I wonder how can I know the complete range of the memory a program uses ? Some mini-games only ose a few MB memory. How can I get the start and end offset of these memorymaps ?
I've read a lot about trainers, and already made own ones. But everytime, you use specific memory adresses to patch (which you have to know of course). But I wonder how can I know the complete range of the memory a program uses ? Some mini-games only ose a few MB memory. How can I get the start and end offset of these memorymaps ?
-
White_Leaf
- New User

- Posts: 5
- Joined: Sat May 05, 2007 12:35 pm
Ok, now I've read an interesting article about memory scanning, and the author has written that the
programs (can) always use range 0x00000000 - 0x7FFFFFFF (which is the 2GB memory limit).
But wouldn't the end offset be the total memory usage of another program ? For example:
I start notepad. After the program launches, it uses 1304 kb = 1335296 bytes.
So, I think the range of the program would be 0x00000000 - 0x00146000 correct ?
Or maybe I have to add the imagebase of the launches application to the value, too ?
Is there a way in PB to read the total memory usage by another program as well ?
So many questions ^^
programs (can) always use range 0x00000000 - 0x7FFFFFFF (which is the 2GB memory limit).
But wouldn't the end offset be the total memory usage of another program ? For example:
I start notepad. After the program launches, it uses 1304 kb = 1335296 bytes.
So, I think the range of the program would be 0x00000000 - 0x00146000 correct ?
Or maybe I have to add the imagebase of the launches application to the value, too ?
Is there a way in PB to read the total memory usage by another program as well ?
So many questions ^^
-
White_Leaf
- New User

- Posts: 5
- Joined: Sat May 05, 2007 12:35 pm
Maybe that's what you're looking for?:
http://msdn2.microsoft.com/en-us/library/ms682050.aspx
http://msdn2.microsoft.com/en-us/library/ms682050.aspx
Windows 7 & PureBasic 4.4
-
White_Leaf
- New User

- Posts: 5
- Joined: Sat May 05, 2007 12:35 pm
win32.hlp wrote:In the Microsoft® Win32® application programming interface (API), each process has its own 32-bit virtual address space that enables addressing up to 4 gigabytes (GB) of memory.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

-
White_Leaf
- New User

- Posts: 5
- Joined: Sat May 05, 2007 12:35 pm
Hmm...maybe the article I read is a little out of date ^^ But I highly doubt that there are games or other applications which use the maximum of possible memory 
However, the function milan1612 posted works like a charm, and now I'm able to get the current memory usage of the process.
The only question left is now, if I need to add some imagebase to the memoryrange. For example in my test I read the usage of RAM notepad needs. I ended up with that result:
Process memory range: 0x00000000 - 0x298000
Can I now just access those offsets to read from the memory or do I miss something ?
Update: My memory scanner works now. But, I still have a small problem with it: I used a public memory scanner to compare the results, and where the public one finds 8x the searchstring, mine finds it only 7x. The reason is that my scanner search 0x00000000 - memory usage, while the public one finds the last hit outside of that range (dunno why).
But even more problematic is the fact, that my scanner needs 20719ms for the scan of 3324kb while the public one only needs ~100ms!
Also, it does only scans 556kb of that process. So there seems to be some rules to follow (not all memory is available for the process itself etc.)
Maybe someone has some background info about that ?
However, the function milan1612 posted works like a charm, and now I'm able to get the current memory usage of the process.
The only question left is now, if I need to add some imagebase to the memoryrange. For example in my test I read the usage of RAM notepad needs. I ended up with that result:
Process memory range: 0x00000000 - 0x298000
Can I now just access those offsets to read from the memory or do I miss something ?
Update: My memory scanner works now. But, I still have a small problem with it: I used a public memory scanner to compare the results, and where the public one finds 8x the searchstring, mine finds it only 7x. The reason is that my scanner search 0x00000000 - memory usage, while the public one finds the last hit outside of that range (dunno why).
But even more problematic is the fact, that my scanner needs 20719ms for the scan of 3324kb while the public one only needs ~100ms!
Also, it does only scans 556kb of that process. So there seems to be some rules to follow (not all memory is available for the process itself etc.)
Maybe someone has some background info about that ?
Re:
I'm doing a trainer app that needs to know the start/end memory addresses of an app, too, so I can scan the range for specific byte values. The link that milan1612 mentions hasn't helped me much, as I don't know how to convert C to PureBasic. Looking at it though, it doesn't seem to show the start/end addresses anyway?
So, is anyone here able to give a working example of getting the start/end memory locations of a running process, say Calc.exe? Thanks.
So, is anyone here able to give a working example of getting the start/end memory locations of a running process, say Calc.exe? Thanks.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
- netmaestro
- PureBasic Bullfrog

- Posts: 8453
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: How to know the complete memory of another program ?
What the heck, I'll convert it since it's good useful code. But I don't really know where you'd get start/end addresses either.
I did find this interesting comment from David Davison: http://c.ittoolbox.com/groups/technical ... nt-2603507
I did find this interesting comment from David Davison: http://c.ittoolbox.com/groups/technical ... nt-2603507
Code: Select all
;================================================================
; Collecting Memory Usage Information For a Process
; netmaestro September 2009
; Converted from the original c published by MSDN at:
; http://msdn.microsoft.com/en-us/library/ms682050(VS.85).aspx
;================================================================
Prototype GetProcessMemoryInfo( hProcess, address, size )
Prototype EnumProcesses( *array, size, *cbneeded )
psapi = OpenLibrary(#PB_Any, "psapi.dll")
Global GetProcessMemoryInfo_.GetProcessMemoryInfo = GetFunction(psapi, "GetProcessMemoryInfo")
Global EnumProcesses_.EnumProcesses = GetFunction(psapi, "EnumProcesses")
Structure PROCESS_MEMORY_COUNTERS
cb.l
PageFaultCount.l
PeakWorkingSetSize.i
WorkingSetSize.i
QuotaPeakPagedPoolUsage.i
QuotaPagedPoolUsage.i
QuotaPeakNonPagedPoolUsage.i
QuotaNonPagedPoolUsage.i
PagefileUsage.i
PeakPagefileUsage.i
EndStructure
Procedure PrintMemoryInfo( processID )
Protected hProcess.i
Protected pmc.PROCESS_MEMORY_COUNTERS
hProcess = OpenProcess_( #PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, processID )
If (hProcess=0)
ProcedureReturn
EndIf
; Print the process identifier.
Debug "\nProcess ID: " + Str(processID)
; Print information about the memory usage of the process.
If GetProcessMemoryInfo_( hProcess, @pmc, SizeOf(pmc))
Debug "\tPageFaultCount: " + Str( pmc\PageFaultCount )
Debug "\tPeakWorkingSetSize: "+ Str(pmc\PeakWorkingSetSize )
Debug "\tWorkingSetSize: " + Str( pmc\WorkingSetSize )
Debug "\tQuotaPeakPagedPoolUsage: " + Str(pmc\QuotaPeakPagedPoolUsage )
Debug "\tQuotaPagedPoolUsage: " + Str( pmc\QuotaPagedPoolUsage )
Debug "\tQuotaPeakNonPagedPoolUsage: " + Str( pmc\QuotaPeakNonPagedPoolUsage )
Debug "\tQuotaNonPagedPoolUsage: " + Str( pmc\QuotaNonPagedPoolUsage )
Debug "\tPagefileUsage: " + Str( pmc\PagefileUsage )
Debug "\tPeakPagefileUsage: " + Str( pmc\PeakPagefileUsage )
Debug ""
EndIf
CloseHandle_( hProcess )
EndProcedure
;Get the List of process identifiers.
Dim aProcesses(1024)
cbNeeded.i
cProcesses.i
i.l
EnumProcesses_( @aProcesses(), ArraySize(aProcesses()), @cbNeeded )
; Calculate how many process identifiers were returned.
cProcesses = cbNeeded / SizeOf(LONG)
; Print the memory usage For each process
For i = 0 To cProcesses-1
PrintMemoryInfo( aProcesses(i))
Next
CloseLibrary(psapi)
BERESHEIT
Re: How to know the complete memory of another program ?
You can only access allocated memory. And yes you can enumerate the allocated memory regions.
This is a procedure i wrote to enumerate the memory regions of a process that contain executable code:
Use VirtualQueryEx if you want to enumerate the memory regions of another process.
If you want a realy fast memory scanner you have to write your scanning code in a DLL and inject it into the process you want to scan. So you can directly access the memory without copieing it.
This is a procedure i wrote to enumerate the memory regions of a process that contain executable code:
Code: Select all
Procedure.l GetExecutableMemRegions(RegionList.Region(1))
Define.l Addr,RetVal,RegionCnt
Define.MEMORY_BASIC_INFORMATION MemoryInfo
RegionCnt = -1
Repeat
Addr = Addr + MemoryInfo\RegionSize
RetVal = VirtualQuery_(Addr,MemoryInfo,SizeOf(MEMORY_BASIC_INFORMATION))
If RetVal > 0
If MemoryInfo\State = #MEM_COMMIT
If MemoryInfo\Protect = #PAGE_EXECUTE Or MemoryInfo\Protect = #PAGE_EXECUTE_READ Or MemoryInfo\Protect = #PAGE_EXECUTE_READWRITE Or MemoryInfo\Protect = #PAGE_EXECUTE_WRITECOPY
RegionCnt = RegionCnt + 1
ReDim RegionList.Region(RegionCnt)
RegionList(RegionCnt)\BaseAddr = MemoryInfo\BaseAddress
RegionList(RegionCnt)\Size = MemoryInfo\RegionSize
EndIf
EndIf
EndIf
Until RetVal < 1
ProcedureReturn RegionCnt
EndProcedure
If you want a realy fast memory scanner you have to write your scanning code in a DLL and inject it into the process you want to scan. So you can directly access the memory without copieing it.
Re: How to know the complete memory of another program ?
@netmaestro:
I found it useful to extend your code by also retrieving the .EXE pathname:
I found it useful to extend your code by also retrieving the .EXE pathname:
Code: Select all
Prototype GetModuleFileNameEx(hProcess, module, *name, size)
Global GetModuleFileNameEx_.GetModuleFileNameEx = GetFunction(psapi, "GetModuleFileNameExA")
; ... Within PrintMemoryInfo(), after getting hProcess: ...
size = 512
name$ = Space(size+2)
If GetModuleFileNameEx_(hProcess, #Null, @name$, size)
name$ = Trim(name$)
Debug "Process pathname: "+name$
EndIf
Anthony Jordan
Re: How to know the complete memory of another program ?
@Thorium:
Please give an example of how to call your procedure GetExecutableMemRegions()
Please give an example of how to call your procedure GetExecutableMemRegions()
Anthony Jordan
Re: How to know the complete memory of another program ?
Ok.akj wrote:@Thorium:
Please give an example of how to call your procedure GetExecutableMemRegions()
I just copied the procedure out of one of my old projects. Now i have reworked it. Works now on x86 and x64, can enumerate the memory regions of another process and enumerates all commited regions, not only executable regions.
Keep in mind that every process runs in it's own address space that starts from 0. You don't need to calculate any position. You just need to use the Win-API to access the address space of another process.
I saw that nobody cared about what ts-soft wrote. This is very basic stuff and if you want to work with other processes than your own you have to know it. Just read about the memory managment on MSDN: http://msdn.microsoft.com/en-us/library/aa366525.aspx
Code: Select all
EnableExplicit
Structure Region
BaseAddr.i
Size.i
EndStructure
Procedure.i GetMemRegions(hProcess.i, Array RegionList.Region(1))
Define.i Addr, RetVal, RegionCnt
Define.MEMORY_BASIC_INFORMATION MemoryInfo
RegionCnt = -1
Repeat
Addr = Addr + MemoryInfo\RegionSize
RetVal = VirtualQueryEx_(hProcess, Addr, MemoryInfo, SizeOf(MEMORY_BASIC_INFORMATION))
If RetVal <> 0 And MemoryInfo\State = #MEM_COMMIT
RegionCnt = RegionCnt + 1
ReDim RegionList.Region(RegionCnt)
RegionList(RegionCnt)\BaseAddr = MemoryInfo\BaseAddress
RegionList(RegionCnt)\Size = MemoryInfo\RegionSize
EndIf
Until RetVal < 1
ProcedureReturn RegionCnt
EndProcedure
Define.i i, RegionCnt, hProcess
Dim RegionList.Region(0)
hProcess = GetCurrentProcess_()
RegionCnt = GetMemRegions(hProcess, RegionList())
Debug "count of memory regions in process address space: " + Str(RegionCnt + 1)
For i = 0 To RegionCnt
Debug "region: " + Str(i + 1)
Debug "base address: " + Hex(RegionList(i)\BaseAddr)
Debug "size: " + Hex(RegionList(i)\Size)
Debug "--------------------------------"
Next


