 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
evan Guest
|
Posted: Thu Oct 23, 2008 2:01 am Post subject: ReadMemory function |
|
|
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
|
Posted: Thu Oct 23, 2008 2:31 am Post subject: WriteMemory function |
|
|
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
|
Posted: Thu Oct 23, 2008 3:17 am Post subject: |
|
|
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 |
|
 |
evan Guest
|
Posted: Thu Oct 23, 2008 4:05 am Post subject: |
|
|
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
|
Posted: Thu Oct 23, 2008 5:14 am Post subject: |
|
|
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
(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 |
|
 |
evan Guest
|
Posted: Thu Oct 23, 2008 5:54 am Post subject: |
|
|
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
|
Posted: Thu Oct 23, 2008 4:20 pm Post subject: |
|
|
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 |
|
 |
evan Guest
|
Posted: Fri Oct 24, 2008 2:18 am Post subject: |
|
|
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
|
Posted: Fri Oct 24, 2008 2:21 am Post subject: |
|
|
you need to set ProcessHandle as a global var in each func it is used. _________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
Ice_Tea
Joined: 12 Jan 2008 Posts: 131
|
Posted: Fri Oct 24, 2008 3:51 am Post subject: |
|
|
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 |
|
 |
evan Guest
|
Posted: Fri Oct 24, 2008 5:28 am Post subject: |
|
|
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
|
Posted: Fri Oct 24, 2008 5:38 pm Post subject: |
|
|
| 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 |
|
 |
[VxE]
Joined: 07 Oct 2006 Posts: 3254 Location: Simi Valley, CA
|
Posted: Fri Oct 24, 2008 10:52 pm Post subject: |
|
|
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 |
|
 |
evan Guest
|
Posted: Sat Oct 25, 2008 2:09 am Post subject: |
|
|
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
|
Posted: Thu Dec 25, 2008 9:34 pm Post subject: |
|
|
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 |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|