AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

ReadMemory function
Goto page 1, 2, 3, 4  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
evan
Guest





PostPosted: Thu Oct 23, 2008 2:01 am    Post subject: ReadMemory function Reply with quote

Its not my first time using ReadProcessMemory functions to read 4byte value in a game client at certain memory address, but i always have difficulties copy and paste this and that... declaring the functions
so today, i made up my mind and wrap it up together into a library function

Here:
Code:
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,"Str",MVALUE,"UInt",4,"UInt *",0)

Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)

return, result 
}

(put this in "C:\Program Files\AutoHotkey\lib" folder with "ReadMemory.ahk" as name)

example usage:
Code:
Run calc.exe
winwait, Calc
StartTime := A_TickCount

loop 1000
value:=ReadMemory(0x41000C,"Calc")

ElapsedTime := A_TickCount - StartTime
msgbox, Memory address 0x41000C = %value%`nTake %ElapsedTime% ms to loop 1000 times




this function will refresh PID and process every time
but as shown in the results, ~5000 times per second isnt bad at all, because usually we only need like 1-2 times per second in reading a game client value

welcome for any suggestions
i really appreciated if i can improve this, as i use memory address often
Back to top
evan
Guest





PostPosted: Thu Oct 23, 2008 2:31 am    Post subject: WriteMemory function Reply with quote

of course, i do have the write memory address function too:
Code:
WriteMemory(WVALUE,MADDRESS,PROGRAM)
{
winget, pid, PID, %PROGRAM%

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

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


(put this in "C:\Program Files\AutoHotkey\lib" folder with "WriteMemory.ahk" as name)

example usage:
Code:
WriteMemory(10, 0x41000C,"Calc")
;(InputValue, Address, Program)
Back to top
Ice_Tea



Joined: 12 Jan 2008
Posts: 131

PostPosted: Thu Oct 23, 2008 3:17 am    Post subject: Reply with quote

Hey

Well you should make 4 separate functions.
OpenHandle
ReadMemory
WriteMemory
CloseHandle

You're putting 3 functions into 1, which causes the whole thing to slow down.


As you see, it's way more efficient.


Last edited by Ice_Tea on Sun Aug 29, 2010 3:51 pm; edited 1 time in total
Back to top
View user's profile Send private message
evan
Guest





PostPosted: Thu Oct 23, 2008 4:05 am    Post subject: Reply with quote

can u show me the script u using to produce that result?
i assume it is:
OpenHandle
loop1000, ReadMemory
CloseHandle

i appreciate the suggestions, but i am aiming for all-in-one
if not all-in-one, why in the first place i need to make a function library
each for the 4 functions is just 1 line anyways
Back to top
[VxE]



Joined: 07 Oct 2006
Posts: 3254
Location: Simi Valley, CA

PostPosted: Thu Oct 23, 2008 5:14 am    Post subject: Reply with quote

If you still want to have it 'all-in-one', then you could have a static variable in the function to hold the ProcessHandle, then use a special flag (in the processname parameter) to know when to close the handle.

Also, it might be nice to have the option for users who want to read chars one at a time, not 4 at a time Wink

(also, for the readmemory function, the first param of the OpenProcess call only needs to be 16. Similarly, using PROCESS_ALL_ACCESS for the writememory function is definitely overkill)
_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!
Back to top
View user's profile Send private message
evan
Guest





PostPosted: Thu Oct 23, 2008 5:54 am    Post subject: Reply with quote

o i see what u meant
but i dont quite get how it can be done to check should the program open/close handle from a library function
actually i dont really know what it meant by close, as it shows no difference with/without it
so lets say if i have a settimer every 1 second to check my current HP in a game client, the program will press certain key if HP low, or winKill the client when its 0
how should my open, read, close function approach?
usually i will just open the process from the beginning of my script and keep reading it until program exitapp
Back to top
Ice_Tea



Joined: 12 Jan 2008
Posts: 131

PostPosted: Thu Oct 23, 2008 4:20 pm    Post subject: Reply with quote

Hmm, Evan I'd like to write the function for you but atm I'm busy with another project...

It seems like you haven't understood that you can put multiple functions into 1 "library", meaning that you could put Openprocess,read/write-memory,Closeprocess into 1 single file...

Well the way you should build the script is like this:
Code:
;*When starting the script*
OpenProcess ;*Make sure that ur process exists*
OnExist, Close ;goes to the label "close" when the script is terminated
Settimer, updateHP, 1000
return

updateHP:
ReadMemory
return

Close:
CloseProcess
Return


btw I might clean it up for you later...Sorry about not being able to share that script, as you see it was run as "~acc.tmp" it's a command console for AHK (it's made by Titan), it only saves 1 script and I've already overwritten it... well all I did was stripping your function, putting openprocess outside, and close outside, leaving readmemory alone in the function.

Btw about closing the handle, I dunno if that's necessary, the whole thing works fine without it... but just incase, it would be good to unload it when you shutdown the script, it's just another additional line...
Back to top
View user's profile Send private message
evan
Guest





PostPosted: Fri Oct 24, 2008 2:18 am    Post subject: Reply with quote

if i use this in library, it doesnt work
i guess because the ProcessHandle can not work outside the function so it wont react with ReadMemory()

Code:
OpenProcess(PROGRAM)
{
winget, pid, PID, %PROGRAM%
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
}

ReadMemory(MADDRESS)
{
VarSetCapacity(MVALUE,4,0)

DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)

Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)

return, result
}
Back to top
ahklerner



Joined: 26 Jun 2006
Posts: 1381
Location: USA

PostPosted: Fri Oct 24, 2008 2:21 am    Post subject: Reply with quote

you need to set ProcessHandle as a global var in each func it is used.
_________________

ʞɔпɟ əɥʇ ʇɐɥʍ
Back to top
View user's profile Send private message
Ice_Tea



Joined: 12 Jan 2008
Posts: 131

PostPosted: Fri Oct 24, 2008 3:51 am    Post subject: Reply with quote

I'm on my way to bed, so I'll have to keep this short:
as ahklerner said, just put Processhandle as a global variable:

Code:
Global ProcessHandle := DLLcallBLABLABLABLA

(Not sure if you can declear a variable as global like that, I think that it should work)

Regarding the library with many functions, you need to give them specific index for the variables or simply "#include LIBRARYNAME.ahk"... and it should solve your problems.

nitenite
*sry about the poor explanation*


Last edited by Ice_Tea on Sun Aug 29, 2010 3:51 pm; edited 1 time in total
Back to top
View user's profile Send private message
evan
Guest





PostPosted: Fri Oct 24, 2008 5:28 am    Post subject: Reply with quote

thanks for the suggestion on globe var
i come out with this:
Code:
ReadMemory(MADDRESS,PROGRAM)
{
static Count = 0
   
if Count = 0
{
winget, pid, PID, %PROGRAM%
global  ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
Count = 1
}

VarSetCapacity(MVALUE,4,0)
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)

Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)

return, result 
}


Run time is 3 times faster than before - 92ms
still all-in-one, but will only winget 1 time and openprocess 1 time
the 60ms difference than yours, i assume it is the check if statement 1000 times
Back to top
Ice_Tea



Joined: 12 Jan 2008
Posts: 131

PostPosted: Fri Oct 24, 2008 5:38 pm    Post subject: Reply with quote

Nope a if statement shouldn't affect a lot at all... but the difference could be in our CPUs... a weaker CPU would give worse results...
Back to top
View user's profile Send private message
[VxE]



Joined: 07 Oct 2006
Posts: 3254
Location: Simi Valley, CA

PostPosted: Fri Oct 24, 2008 10:52 pm    Post subject: Reply with quote

Here's my cleanup of your ReadMemory() function:

Perks:
- Obtains the PID and handle to a process once for any number of calls to the same PROGRAM.
- Does not loop to obtain the 32bit int (increases speed marginally)
- Some error handling ("Fail" for failure to read or open process, and "Handle Closed: ?" when just closing the handle)
- My laptop clocked it at 26ms for 1000 calls using SetBatchLines, -1

This function should execute at a speed on par with simply looping ReadProcessMemory between OpenProcess and CloseHandle.
Code:
; Automatically closes handle when a new (or null) program is indicated
; Otherwise, keeps the process handle open between calls that specify the
; same program. When finished reading memory, call this function with no
; parameters to close the process handle i.e: "Closed := ReadMemory()"
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"
}

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!
Back to top
View user's profile Send private message
evan
Guest





PostPosted: Sat Oct 25, 2008 2:09 am    Post subject: Reply with quote

excellent
i like the idea that include some error checking

i am glad that i share my script and your comments/suggestions will benefit my future memory reading projects. thanks
Back to top
Deicer



Joined: 22 Dec 2006
Posts: 43

PostPosted: Thu Dec 25, 2008 9:34 pm    Post subject: Reply with quote

Quick question.

When I use ReadMemory on a adress value eg. 2635 it returns 2635 (ok)
When I use ReadMemory on a adress value eg. HELLO it returns 1919595761 (Wrong)

How to convert/fix this, so it returns HELLO ?

ReadMemory looks like this:

Code:
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"
}


My code:

Code:
value:=ReadMemory(0x02F3F4F4,"SomeApp.exe")
MsgBox %value%


Thanks
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group