Jump to content

_MemoryWrite with multiple offset values


Recommended Posts

At first I'd like to mention that I did search for this and I couldn't find clear answers how to do this with multiple pointers so here I go.

The case is that that I need to change a float value and I have only succeed doing it with temporarily address.

This is how I got it working but could somebody explain how do I make this work with the base address and offset values I have commented in.

#include <NomadMemory.au3>

$id = WinGetProcess("[CLASS:Application]", "")
;~          $baseAddress = 0x053969E8
;~          $off1 = 0x3c4
;~          $off2 = 0x0c 

            $address = 0x053ABC34
            $newValue = 20
            
$memory = _MemoryOpen($id)

_MemoryWrite($address, $memory, $newValue, "float") ; Changes the value to 20

_MemoryClose($memory)

I have tried writing directly to the $baseAddress but it just crashes my application so I think I need to include the offsets somehow.

Any kind of help or tips appreciated.

Link to comment
Share on other sites

i don't know that much about memory reading with autoit, but i think this code can help you:

http://www.autoitscript.com/forum/index.php?showtopic=78834&st=0&p=568869&#entry568869

Edited by cageman
Link to comment
Share on other sites

i don't know that much about memory reading with autoit, but i think this code can help you:

$memory=_MemoryOpen($proces_ID)
  $offset2[0]='NULL'
  $offset2[1]=1184
  $offset2[2]=92
  $offset2[3]=4
  $offset2[4]=116
  $offset2[5]=1824
$result2=_MemoryPointerRead (0x0089afB8,$memory, $offset2,'dword') ;<<- 0x0089afB8 is my base adress
;MsgBox(0,@error,$result2)
_MemoryClose($memory)
_ArrayDisplay($result2,"Result:") ;<<- Script isnt reading the right adress :/

Thanks for tyring to help but I'm trying to figure how to write memory, not read. I already know how to read base address with offset values.
Link to comment
Share on other sites

I figured in some cases people added the offset but I didn't see anyone adding two. I came with up something like this:

$id = WinGetProcess("[CLASS:Application]", "")

            $baseAddress = 0x053969E8
            $off1 = 0x3c4
            $off2 = 0x0c 
            $newValue = 20
            
            $memory = _MemoryOpen($id)

$1 = _MemoryRead($baseAddress,$id)
$2 = Hex($1+$off1)
$3 = Hex($2+$off2)
_MemoryWrite($3, $memory, $newValue, "float") ; Changes the value to 20

_MemoryClose($memory)

I can run it without errors but it doesn't change the wanted address.

Any ideas if this is even close?

Link to comment
Share on other sites

on the link i gave you the guy uses:

$finalADDR = "0x" & Hex($baseADDR + $StaticOffset) maybe you need to do this twice? or just do base +off1 + off2 ? i am not sure though but i hope it helps.

it seems you forgot the "Ox".

Edited by cageman
Link to comment
Share on other sites

I tried the base address + offset thing like this:

_MemoryWrite($baseAddress + $off1 + $off2, $memory, $newValue, "float") ; Changes the value to 20

...with and without "0x &" before Hex. Doesn't give me errors but still does nothing. I also double checked that the base address and offsets are correct.

Anyone out there who has played with _MemoryWrite'ing?

Link to comment
Share on other sites

I think you neeed to show the code you have for reading the memory address you just wrote to.

I'm using Nomad's quite common NomadMemory.au3

_MemoryRead():

;==================================================================================
; Function:         _MemoryRead($iv_Address, $ah_Handle[, $sv_Type])
; Description:      Reads the value located in the memory address specified.
; Parameter(s):     $iv_Address - The memory address you want to read from. It must
;                                 be in hex format (0x00000000).
;                   $ah_Handle - An array containing the Dll handle and the handle
;                                of the open process as returned by _MemoryOpen().
;                   $sv_Type - (optional) The "Type" of value you intend to read.
;                               This is set to 'dword'(32bit(4byte) signed integer)
;                               by default.  See the help file for DllStructCreate
;                               for all types.  An example: If you want to read a
;                               word that is 15 characters in length, you would use
;                               'char[16]' since a 'char' is 8 bits (1 byte) in size.
; Return Value(s):  On Success - Returns the value located at the specified address.
;                   On Failure - Returns 0
;                   @Error - 0 = No error.
;                            1 = Invalid $ah_Handle.
;                            2 = $sv_Type was not a string.
;                            3 = $sv_Type is an unknown data type.
;                            4 = Failed to allocate the memory needed for the DllStructure.
;                            5 = Error allocating memory for $sv_Type.
;                            6 = Failed to read from the specified process.
; Author(s):        Nomad
; Note(s):          Values returned are in Decimal format, unless specified as a
;                   'char' type, then they are returned in ASCII format.  Also note
;                   that size ('char[size]') for all 'char' types should be 1
;                   greater than the actual size.
;==================================================================================
Func _MemoryRead($iv_Address, $ah_Handle, $sv_Type = 'dword')
    
    If Not IsArray($ah_Handle) Then
        SetError(1)
        Return 0
    EndIf
    
    Local $v_Buffer = DllStructCreate($sv_Type)
    
    If @Error Then
        SetError(@Error + 1)
        Return 0
    EndIf
    
    DllCall($ah_Handle[0], 'int', 'ReadProcessMemory', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer), 'int', '')
    
    If Not @Error Then
        Local $v_Value = DllStructGetData($v_Buffer, 1)
        Return $v_Value
    Else
        SetError(6)
        Return 0
    EndIf
    
EndFunc

_MemoryWrite():

;==================================================================================
; Function:         _MemoryWrite($iv_Address, $ah_Handle, $v_Data[, $sv_Type])
; Description:      Writes data to the specified memory address.
; Parameter(s):     $iv_Address - The memory address which you want to write to.
;                                 It must be in hex format (0x00000000).
;                   $ah_Handle - An array containing the Dll handle and the handle
;                                of the open process as returned by _MemoryOpen().
;                   $v_Data - The data to be written.
;                   $sv_Type - (optional) The "Type" of value you intend to write.
;                               This is set to 'dword'(32bit(4byte) signed integer)
;                               by default.  See the help file for DllStructCreate
;                               for all types.  An example: If you want to write a
;                               word that is 15 characters in length, you would use
;                               'char[16]' since a 'char' is 8 bits (1 byte) in size.
; Return Value(s):  On Success - Returns 1
;                   On Failure - Returns 0
;                   @Error - 0 = No error.
;                            1 = Invalid $ah_Handle.
;                            2 = $sv_Type was not a string.
;                            3 = $sv_Type is an unknown data type.
;                            4 = Failed to allocate the memory needed for the DllStructure.
;                            5 = Error allocating memory for $sv_Type.
;                            6 = $v_Data is not in the proper format to be used with the
;                                "Type" selected for $sv_Type, or it is out of range.
;                            7 = Failed to write to the specified process.
; Author(s):        Nomad
; Note(s):          Values sent must be in Decimal format, unless specified as a
;                   'char' type, then they must be in ASCII format.  Also note
;                   that size ('char[size]') for all 'char' types should be 1
;                   greater than the actual size.
;==================================================================================
Func _MemoryWrite($iv_Address, $ah_Handle, $v_Data, $sv_Type = 'dword')
    
    If Not IsArray($ah_Handle) Then
        SetError(1)
        Return 0
    EndIf
    
    Local $v_Buffer = DllStructCreate($sv_Type)
    
    If @Error Then
        SetError(@Error + 1)
        Return 0
    Else
        DllStructSetData($v_Buffer, 1, $v_Data)
        If @Error Then
            SetError(6)
            Return 0
        EndIf
    EndIf
    
    DllCall($ah_Handle[0], 'int', 'WriteProcessMemory', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer), 'int', '')
    
    If Not @Error Then
        Return 1
    Else
        SetError(7)
        Return 0
    EndIf
    
EndFunc
Link to comment
Share on other sites

Very clever, clap clap.

I dont suppose you are adding any parameters to those functions are you?

If you scroll up for my code examples you can see I do have parameters.

For example _MemoryWrite($3, $memory, $newValue, "float") has at first $3 which is supposed to be the address I'm trying to write one. Then comes $memory which has the value of opening my application's id. $newValue contains number 20 which is going to be written as float, like it says in the end.

Edited by Ryoni
Link to comment
Share on other sites

$baseMem2 = "0x" & Hex($baseMem1 + Dec($offsetStatic))

saw this.. try that with your offsets and try to experiment..

also found this:

Func UpdateValues()
    
    If WinActive($GUI) = 0 Then
        $Value = _MemoryPointerRead($finalADDR, $openmem, $Offset1)
        $TimeAddress = $Value[0]
        GUICtrlSetData($TimeLabel, "Time (milliseconds): " & $Value[1])
        GUICtrlSetData($Time, $Value[1])
        $Value = _MemoryPointerRead($finalADDR, $openmem, $Offset2)
        $BlocksAddress = $Value[0]
        GUICtrlSetData($BlocksLabel, "Blocks: " & $Value[1])
        GUICtrlSetData($Blocks, $Value[1])
    EndIf
    
    If BitAnd(GUICtrlRead($TimeFreeze),$GUI_CHECKED) = $GUI_CHECKED Then
        _MemoryWrite($TimeAddress, $openmem, $FreezeTime_Time)
    EndIf

it seems that the first position the array after reading returns is the address you should read.. try that.

use an offset array..

Edited by cageman
Link to comment
Share on other sites

If you scroll up for my code examples you can see I do have parameters.

For example _MemoryWrite($3, $memory, $newValue, "float") has at first $3 which is supposed to be the address I'm trying to write one. Then comes $memory which has the value of opening my application's id. $newValue contains number 20 which is going to be written as float, like it says in the end.

Thats all well and good, but it still has nothing to do with your code for reading the memory.

At this point we only have your say so that you are actually reading the same address as you are writing to.

It would also be wise to check the return values of your memorywrites.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Thats all well and good, but it still has nothing to do with your code for reading the memory.

At this point we only have your say so that you are actually reading the same address as you are writing to.

It would also be wise to check the return values of your memorywrites.

Well as I said in the begining I know how to read from the base address with the offset values I mentioned and I do get value which is excatly the one I know is 100% correct. I just don't need to read it anymore in this macro.

Checking return value was actually a good idea, didn't think of it. It returns '1' so it's still not correct

I tried your method cageman like this:

$1 = _MemoryRead($baseAddress,$id)
$2 = _MemoryRead($1 + Dec($off1), $id)
$3 = _MemoryRead($2 + Dec($off2), $id)

_MemoryWrite($3, $memory, $newValue, "float") ; Changes the value to 20

Yet again it says no errors, does nothing and return that '1'.

Link to comment
Share on other sites

Ok, but it is your best intrests to post the code in order to better get help.

It seems to me that the read and the write are different

At the moment you say you are having trouble with the correct address to write to, but you are having no problems reading that very same address

It dosent make sense.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

#include <NomadMemory.au3>

$id = WinGetProcess("[CLASS:Application]", "")

$memory = _MemoryOpen($id)

$baseAddress = 0x053969E8
$Offset[0]=0x3c4
$Offset[1]=0x0c
$newValue=20;

$value=_MemoryPointerRead($baseAddress, $openmem, $Offset)

_MemoryWrite($value[0], $memory, $newValue, "float")

the right adress could also be

$finaladress="0x" & hex($baseAdress + Dec($offset[0]))

$finaladress="0x" & hex($finaladress + Dec($offset[1]))

_MemoryWrite($finaladress, $memory, $newValue, "float")

Edited by cageman
Link to comment
Share on other sites

#include <NomadMemory.au3>

$id = WinGetProcess("[CLASS:Application]", "")

$baseAddress = 0x053969E8
$off1 = 0x3c4
$off2 = 0x0c
            
$memory = _MemoryOpen($id)

$1 = _MemoryRead($baseAddress, $memory)
$2 = _MemoryRead($1 + $off1, $memory)
$3 = _MemoryRead($2 + $off2, $memory)
        
MsgBox("","",$3)

I'm not sure what it helps but that's how I read it.

I also tried your code cageman but nothing happens.

Edited by Ryoni
Link to comment
Share on other sites

I dont clain to no much about this kind of thing but the only time I ever tried using memory function was when trying to figure out what the hell cheat engine was which was when i discovered about these offsets, and the only reason I could figure for having 2 of them is that the inital base address has pointers, so your first offset would be a pointer to another address, so I had to read the value of the base + pointer to get the next address and so on and so forth, its doubtful that these offsets will be the same any two times.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I dont clain to no much about this kind of thing but the only time I ever tried using memory function was when trying to figure out what the hell cheat engine was which was when i discovered about these offsets, and the only reason I could figure for having 2 of them is that the inital base address has pointers, so your first offset would be a pointer to another address, so I had to read the value of the base + pointer to get the next address and so on and so forth, its doubtful that these offsets will be the same any two times.

I don't know so much about memory reading either so that's why I came here to ask because I don't really know how I'm supposed to play with the offsets when writing.

The base address and the offset values I have, are static, gotten with cheat engine. So I can read the value everytime even if I restart the application.

Link to comment
Share on other sites

Ah! Why didn't I notice that the returned '1' was actually an error message from the function.

"1 = Invalid $ah_Handle." So in my case it should be the $memory but there's no reason why it would be wrong. I use the same method getting the ID in my other macros too with the same application, even in the memory reading one I demonstrated and it works just fine. :mellow:?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...