Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

ReadMemory function


  • Please log in to reply
109 replies to this topic
GeekDude
  • Spam Officer
  • 391 posts
  • Last active: Oct 05 2015 08:13 PM
  • Joined: 23 Nov 2009
I am not sure, but look at evans post, right above mine.

hewul
  • Members
  • 17 posts
  • Last active: Apr 24 2013 06:09 PM
  • Joined: 31 Oct 2011
how to make the address can be customize so i can see other address value just with edit on text ?

nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012
A text is Null Terminated that means to store text you need to loop until the byte is zero e.g. there is an Str stored at 0x40000C
readstr(0x40000C,"MarpleStory.exe") ; just example
readstr(startAddress,Programm)
{
Loop
{
numPut(ReadMemory(startAdress+(A_Index-1)*4,Programm),var,"UInt") ;Use the real memory func(Ihave renamed it)
Loop,4
if !(var2.=chr(numget(var,A_Index-1,Uchar)))
return , var
}
}

Visit the new forum ahkscript.org.

http://ahkscript.org


nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012

I've been using this function to ready memory values, and it works brilliantly. So firstly, thanks!

Secondly, i need to read a memory address which has a stored string (not a 4byte). How would i go about doing this using this function?

Thanks.


Visit the new forum ahkscript.org.

http://ahkscript.org


gummby8
  • Members
  • 120 posts
  • Last active: Nov 30 2018 06:35 PM
  • Joined: 05 Jul 2009

Hello I am using the folowing function to read values from memory addresses.

 


 

ReadMemory(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,4,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

 

The following script will return the proper value when run on a win xp x86 OS, but when I run it on a win 7 x64 OS it always returns "Handle Closed"

 


 

valuex:=ReadMemory(0x76eeb084,"calc")


msgbox, %valuex%`n

 

I use cheat engine to find a memory address that has a value each time. This is a snip from the win 7 machine. The memory address does exist and the function should have returned "80" yet it always returns "Handel closed"

 

5exshu.png

 

I have tried entering the address with and without the "0x" prefix and nothing changes.

 

Any help would be great. Thank you.



VxE
  • Moderators
  • 3622 posts
  • Last active: Dec 24 2015 02:21 AM
  • Joined: 07 Oct 2006

That function is not x64 compatible.

 

Does anyone know of a ReadProcessMemory wrapper that does work with x64?



gummby8
  • Members
  • 120 posts
  • Last active: Nov 30 2018 06:35 PM
  • Joined: 05 Jul 2009

That function is not x64 compatible.

 

Does anyone know of a ReadProcessMemory wrapper that does work with x64?

 

I decided to dig a bit further into this. Supposedly there is no way for a 32 bit program to read memory from a 64 bit program. Not sure if that is true or not, but it may be part of the problem these functions don't work well on 64 bit OSs



penguin114
  • Members
  • 8 posts
  • Last active: Aug 10 2013 11:00 AM
  • Joined: 12 Jan 2013

Sorry for being noob but can anybody explain me how to use pointers on this function?



sarger
  • Members
  • 4 posts
  • Last active: Feb 08 2013 11:27 PM
  • Joined: 03 Feb 2013

hey,

I was reading the whole thread.

Im new to AHK and want to read a lvl 7 pointer in AHK.

Just found that thread + that readmemory function, but

I always get "Closed Handle".

I would know how to do that in c++ but not in AHK -_-....

 

Its not even working if I do that:

 

Pointer := 0x03E06254
PointerResult1 := ReadMemory(addr1 , "nameofgame.exe")

ReadMemory(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,4,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

btw Im on 64 bit Win 7. Any help?



gummby8
  • Members
  • 120 posts
  • Last active: Nov 30 2018 06:35 PM
  • Joined: 05 Jul 2009

hey,

I was reading the whole thread.

Im new to AHK and want to read a lvl 7 pointer in AHK.

Just found that thread + that readmemory function, but

I always get "Closed Handle".

I would know how to do that in c++ but not in AHK -_-....

 

Its not even working if I do that:

 

Pointer := 0x03E06254
PointerResult1 := ReadMemory(addr1 , "nameofgame.exe")

ReadMemory(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,4,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

btw Im on 64 bit Win 7. Any help?

 

Hi, this thread is actually full of wrong turns and whatnot.

 

Here are the functions I use for memory reading and writing. Along with one to get a loaded DLL base ID

 

The readmemorystring function has a loop 32 in it. For my purposes the max character length was 32, so change it as you see fit.

 

WriteMemory(WVALUE,MADDRESS,PROGRAM)
{
winget, pid, PID, %PROGRAM%

ProcessHandle := DllCall("OpenProcess", "int", 2035711, "char", 0, "UInt", PID, "UInt")
DllCall("WriteProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "float*", WVALUE, "Uint", 8, "Uint *", 0)

DllCall("CloseHandle", "int", ProcessHandle)
return
}


ReadMemory(MADDRESS,PROGRAM)
{
winget, pid, PID, %PROGRAM%

VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Float*",float,"UInt",8,"UInt *",0)
DllCall("CloseHandle", "int", ProcessHandle)

return, float
}


ReadMemory4byte(MADDRESS,PROGRAM)
{
winget, pid, PID, %PROGRAM%

VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
DllCall("CloseHandle", "int", ProcessHandle)
Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)

return, result 
}


ReadMemory8byte(MADDRESS,PROGRAM)
{
winget, pid, PID, %PROGRAM%

VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",8,"UInt *",0)
DllCall("CloseHandle", "int", ProcessHandle)
Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)

return, result 
}


ReadMemoryString(MADDRESS,PROGRAM) 
{ 
	winget, pid, PID, %PROGRAM% 

			ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "Uint")
			teststr =
			Loop 32
			{
			   Output := "x"  ; Put exactly one character in as a placeholder. used to break loop on null
			   tempVar := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "str", Output, "Uint", 1, "Uint *", 0)
			   if (ErrorLevel or !tempVar)
			   {
				  DllCall("CloseHandle", "int", ProcessHandle)
				  return teststr
			   }
			  ; if Output =
			  ;  break
			
			   teststr = %teststr%%Output%
			   MADDRESS++
			}
			DllCall("CloseHandle", "int", ProcessHandle)
			return, teststr  
}



GetDllBase(DllName, PID = 0)
{
    TH32CS_SNAPMODULE := 0x00000008
    INVALID_HANDLE_VALUE = -1
    VarSetCapacity(me32, 548, 0)
    NumPut(548, me32)
    snapMod := DllCall("CreateToolhelp32Snapshot", "Uint", TH32CS_SNAPMODULE
                                                 , "Uint", PID)
    If (snapMod = INVALID_HANDLE_VALUE) {
        Return 0
    }

    If (DllCall("Module32First", "Uint", snapMod, "Uint", &me32)){
        while(DllCall("Module32Next", "Uint", snapMod, "UInt", &me32)) {
            If !DllCall("lstrcmpi", "Str", DllName, "UInt", &me32 + 32) {
                DllCall("CloseHandle", "UInt", snapMod)
                Return NumGet(&me32 + 20)
            }
        }
    }
    DllCall("CloseHandle", "Uint", snapMod)
    Return 0
}



Wizbaggd
  • Members
  • 15 posts
  • Last active: Jan 18 2014 03:09 AM
  • Joined: 18 Sep 2013

How would this work if I was to want to read the memory data from several instances of the same application that are all running simultanously doing their own things, due to scripts operating? I can communicate with multiple windows, but adapting what I have done to this is proving difficult. I posted more detailed in my own Support post request, but I thought I should ask here also, as it pertains more directly to this topic too.



RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

It should work fine. Just pass the correct process handle to the readprocessmemory call.



Wizbaggd
  • Members
  • 15 posts
  • Last active: Jan 18 2014 03:09 AM
  • Joined: 18 Sep 2013

I have been tinkering a lot today to try to work this out. I now finally worked out how to get the accurate PID from each window (I was using an incorrect value, set by List instead of PID for pulling an ID to work with.

 

Now the issue I am falling into is offsets, I cannot clearly see within any of these snippets where to handle offsets. I am not exactly a genius when it comes to memory reading and manipulation (it's an entirely new field for me).

 

In CheatEngine I have found the Pointers and offsets for certain information I need to be pulling from the applications.

 

If someone could be so kind as to possibly show me an example using an offset using a base pointer?

 

Here is one particularly important pointer I am trying to make work:

 

Program.exe+180AA4

f4 offset

4 Bytes

 

This displays accurately in CE with whatever instance of the process I hook into. I just cannot for the life of me work out how to put the two together.

 

I have a massive feeling I am doing something redundant here, but I believe I am getting an accurate PID as well as maintaining the original List method I have several other snippets I am working with from old code to manage sending keypresses to designated instances of the process. This is the code I am currently using to achieve both PID and List from WinGet:

WinGet,processes_,List,Program
Loop %processes_%
{
	WinGet, PID, PID,% "ahk_id " processes_%A_Index%
        processes_%A_Index%_PID := %PID%
	Process, Exist, %PID%
	procid :=ErrorLevel
	IfNotEqual, procid
	{
		hash:=DllCall("OpenProcess","UInt",0x001F0FFF,"Int",0,"Int",procid)
		DllCall("SetProcessWorkingSetSize", "UInt", hash, "Int", -1, "Int", -1)
		DllCall("CloseHandle", "Int", hash)
	}
}

Any help would be greatly appreciated



RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

Here is one particularly important pointer I am trying to make work:

 

Program.exe+180AA4

f4 offset

4 Bytes

 

 

 

The exact syntax will depend on the function used but it will look like this:

offetAddress := readmemory(program_BaseAddress + 0x180AA4)
pointerValue := readmemory(offetAddress + 0xF4)

You use the term program.exe as your base address. Is this static or dynamic?  You can find the current base address of the program by simply  adding the address " program.exe " to CE. 

If its static the address will remain the same each time you load the program. If this is the case, then you can just use this value as the base address. If it's dynamic, then you will need to write a function to find the base address. I can post mine if required.

 

Cheers. 



Wizbaggd
  • Members
  • 15 posts
  • Last active: Jan 18 2014 03:09 AM
  • Joined: 18 Sep 2013

Wow thank you so much for your awesome and fast reply!

 

 

That is exactly what I needed, I have looked at Base Address stuff, but it evades me also, I'm also trying to keep this part of the code as generic as possible so it can be implemented on several projects and be a useful basic memory reading framework for anyone to use for multi-client memory reads and data tracking.

 

If you have a working snippet for Base Address, that would be amazing.