Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[Solved] ReadProcessMemory & offsets from Cheat Engine


  • Please log in to reply
4 replies to this topic
ameyrick
  • Members
  • 69 posts
  • Last active: Feb 16 2015 11:28 AM
  • Joined: 19 Sep 2011
Hi, I have been playing with Cheat Engine the last few days & have found the Static pointer from the base address. Which returns the current logged in character name in Final Fantasy XIV.

I have been through the help file on DllCall But I'm finding it a little cloudy on how to translate my offsets from CE.

Any help or hints to retrieve the character name using my CE offsets would be much appreciated, thanks.

ameyrick
  • Members
  • 69 posts
  • Last active: Feb 16 2015 11:28 AM
  • Joined: 19 Sep 2011
Ok I can now read memory from the static offsets I got from CE

I'm having a problem retrieving strings, The results return as an Int Intead of a text string. I'm sure this is due to an error in my DllCall.

I need it to return a text string with a max length of 25 characters.

My code so far:
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,"StrP",MADDRESS,"Str",MVALUE,"UInt",4,"str P",0) 

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

	return, result  
}

;//Read from current Dynamic address
addr := 0x07B7EE7A       
DynAddr := ReadMemory(addr, "ahk_class RAPTURE")

;//Read from Static Pointer
addr0 := 0x00E8D368
offset0 := 0x144
offset1 := 0xE0
offset2 := 0xE2

value0 := ReadMemory(addr0, "ahk_class RAPTURE")
addr1 := value0 + offset0

value1 := ReadMemory(addr1, "ahk_class RAPTURE")
addr2 := value1 + offset1

value2 := ReadMemory(addr2, "ahk_class RAPTURE")
addr3 := value2 + offset2

StaticAddr := ReadMemory(addr3, "ahk_class RAPTURE")

MsgBox, Dynamic Address,`n Player = %DynAddr%  `n`nStatic Pointer,`n Player = %StaticAddr% `n





  • Guests
  • Last active:
  • Joined: --
if you solve it problem with getting string, please post it here. I also need that script.
Hey AHK Gurus please help!

ameyrick
  • Members
  • 69 posts
  • Last active: Feb 16 2015 11:28 AM
  • Joined: 19 Sep 2011
Ok, it seems I lied in post 2 about reading memory from offsets. However I can now read strings from a specified memory address.

But can't seem to do it with a lvl-3 pointer, In CE this pointer always returns the Character name. I have asked on the CE forum & read the guides on multilevel pointers. I just cannot replicate it in ahk.

Posted Image


Any help with reading multi pointers in ahk would be much appreciated, thanks!

;//function ReadMemory
ReadMemory(MADDRESS, pOffset = 0, PROGRAM = "ffxivgame.exe") 
{ 
			Process, wait, %PROGRAM%, 0.5
			pid = %ErrorLevel%
			if pid = 0
			{
				MsgBox The specified process could not be found.
				return
			}
			VarSetCapacity(MVALUE,4) 
			ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
			DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS+pOffset, "Str", MVALUE, "Uint",4, "Uint *",0)
			DllCall("CloseHandle", "int", ProcessHandle)
			Loop 4 
				result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)
				
			return result
}


;//function ReadMemory_Str 
ReadMemory_Str(MADDRESS, pOffset = 0, PROGRAM = "ffxivgame.exe") 
{ 
			Process, wait, %PROGRAM%, 0.5
			pid = %ErrorLevel%
			if pid = 0
			{
				MsgBox The specified process could not be found.
				return
			}
			ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "Uint")
			teststr =
			Loop
			{
			   Output := "x"  ; Put exactly one character in as a placeholder. used to break loop on null
			   tempVar := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS+pOffset, "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  
}



;//Current Dynamic address
DynAddr := 0x07A9EE7A       
DynResult := ReadMemory_Str(DynAddr) ;//Returns: Character name in FFXIV

;//Three lvl Pointer in CE which always Points to the Character name
Pointer := 0x00E8D368 
offset0 := 0x144
offset1 := 0xE0
offset2 := 0xE2

PointerResult1 := ReadMemory(Pointer, offset0)
PointerResult2 := ReadMemory(PointerResult1, offset1)

PointerResult3 := ReadMemory_Str(PointerResult2, offset2) ;//??? Does not Return: Character name in FFXIV ???

ListVars

`::
Reload



ameyrick
  • Members
  • 69 posts
  • Last active: Feb 16 2015 11:28 AM
  • Joined: 19 Sep 2011
Solved! Thanks to Lexikos ~ <!-- m -->http://www.autohotke...pic.php?t=77188<!-- m -->


;//function ReadMemory
ReadMemory(MADDRESS, pOffset = 0, PID = "") 
{ 
			if (PID == ""){
				Process, wait, ffxivgame.exe 0.5
				PID = %ErrorLevel%
				if PID = 0
				{
					MsgBox The specified process could not be found.
					return
				}
			}
			
			VarSetCapacity(MVALUE,4) 
			ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
			
			
			;int pAddress = 0x002D1120; 
			; ReadProcessMemory(pHandle,(LPVOID)pAddress,&pAddress,4,NULL); 
			;  pAddress += 0x14;
			  
			DllCall("ReadProcessMemory", "UInt", ProcessHandle, "Ptr", MADDRESS+pOffset, "Ptr", &MVALUE, "Uint",4, "Uint",0)
			DllCall("CloseHandle", "int", ProcessHandle)
			Loop 4 
				result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)
				
			return result
}


;//function ReadMemory_Str 
ReadMemory_Str(MADDRESS, pOffset = 0, PID = "") 
{ 
			if (PID == ""){
				Process, wait, ffxivgame.exe 0.5
				PID = %ErrorLevel%
				if PID = 0
				{
					MsgBox The specified process could not be found.
					return
				}
			}
			
			ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "Uint")
			teststr =
			Loop
			{
			   Output := "x"  ; Put exactly one character in as a placeholder. used to break loop on null
			   tempVar := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS+pOffset, "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  
}

;//function GetImagebase Thanks to Lexikos ~ http://www.autohotkey.com/forum/viewtopic.php?t=77188
GetImageBase(filename)
{
    static IMAGE_DOS_SIGNATURE := 0x5A4D
    static IMAGE_NT_SIGNATURE := 0x4550
    static IMAGE_SIZEOF_FILE_HEADER := 20
    static MAGIC_PE32 := 0x10B
    static MAGIC_PE32PLUS := 0x20B

    file := FileOpen(filename, "r")
    if !file
        return
    
    if (file.ReadUShort() != IMAGE_DOS_SIGNATURE)
    || !file.Seek(60) ; Seek to e_lfanew.
    || !file.Seek(file.ReadInt()) ; Seek to NT header.
    || (file.ReadUInt() != IMAGE_NT_SIGNATURE)
        return
    
    file.Seek(IMAGE_SIZEOF_FILE_HEADER, 1) ; Seek to optional header.
    
    magic := file.ReadUShort()
    if (magic = MAGIC_PE32)
    {
        file.Seek(26, 1)
        return file.ReadUInt()
    }
    else if (magic = MAGIC_PE32PLUS) ; x64
    {
        file.Seek(22, 1)
        return file.ReadInt64()
    }
}



win_count=0
WinGet, id, list, ahk_class RAPTURE
Loop, %id%
{
	win_count += 1
	this_id := id%A_Index%
	WinGet, this_pid, PID, ahk_id %this_id%
	pid%A_Index% := this_pid
}



;///////////////////////////////////////////////////////////////////////////
;//Function called to resolve path to ffxivgame.exe
;///////////////////////////////////////////////////////////////////////////
RegKeyType(RootKey, SubKey, ValueName)  
{
	Loop, %RootKey%, %SubKey%
	{
		IfInString, A_LoopRegName, %ValueName%
		{
		   ;StringReplace, OutputVar, InputVar, SearchText , ReplaceText
			StringReplace, Path, A_LoopRegName, %ValueName%, ffxivgame.exe
			return Path
		}
	}
	return
}
;///////////////////////////////////////////////////////////////////////////
;// Default Path
Path := "C:\Program Files (x86)\SquareEnix\FINAL FANTASY XIV\ffxivgame.exe"
;///////////////////////////////////////////////////////////////////////////
IfNotExist, %Path%
{
	PROGRAM := "ffxivboot.exe"
	RootKey := "HKEY_LOCAL_MACHINE"
	SubKey := "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs"
	Path := RegKeyType(RootKey, SubKey, PROGRAM)
}
;///////////////////////////////////////////////////////////////////////////


SetFormat IntegerFast, H
Base:=  GetImageBase(Path) ; Replace A_AhkPath with path of executable.
SetFormat IntegerFast, D

BaseOffset := 0x00E966B8
offset0 := 0x56C
offset1 := 0x5C0
offset2 := 0x12


loop, %win_count%
{
		pid := pid%A_Index%
		Pointer := ReadMemory(Base, BaseOffset, pid)
		PointerResult1 := ReadMemory(Pointer, offset0, pid)
		PointerResult2 := ReadMemory(PointerResult1, offset1, pid)
		Name := ReadMemory_Str(PointerResult2, offset2, pid)
		msgtext .= "Character Name" A_Index ": " Name "`n"
}

msgbox, %msgtext%