AutoHotkey Community

It is currently May 26th, 2012, 10:14 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: ReadMemory function
PostPosted: October 23rd, 2008, 3:01 am 
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


Image

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


Report this post
Top
  
Reply with quote  
 Post subject: WriteMemory function
PostPosted: October 23rd, 2008, 3:31 am 
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)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 23rd, 2008, 4:17 am 
Offline

Joined: January 12th, 2008, 7:45 pm
Posts: 131
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.

Image
As you see, it's way more efficient.


Last edited by Ice_Tea on August 29th, 2010, 4:51 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 23rd, 2008, 5:05 am 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 23rd, 2008, 6:14 am 
Online
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3328
Location: Simi Valley, CA
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!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 23rd, 2008, 6:54 am 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 23rd, 2008, 5:20 pm 
Offline

Joined: January 12th, 2008, 7:45 pm
Posts: 131
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...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 3:18 am 
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
}


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 3:21 am 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
you need to set ProcessHandle as a global var in each func it is used.

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 4:51 am 
Offline

Joined: January 12th, 2008, 7:45 pm
Posts: 131
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 August 29th, 2010, 4:51 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 6:28 am 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 6:38 pm 
Offline

Joined: January 12th, 2008, 7:45 pm
Posts: 131
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...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 24th, 2008, 11:52 pm 
Online
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3328
Location: Simi Valley, CA
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!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 25th, 2008, 3:09 am 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 25th, 2008, 10:34 pm 
Offline

Joined: December 22nd, 2006, 1:41 pm
Posts: 43
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


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: xXDarknessXx and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group