Jump to content

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

Cant Read Memory adress



  • Please log in to reply
2 replies to this topic
Wyvern010
  • Members
  • 24 posts
  • Last active: Jul 11 2016 11:17 PM
  • Joined: 30 Mar 2015

So, i was able to read some adress from Battlefield 4

 

But for some reason it fails after the 4th iteration.

i Checked everything as in, offsets,typo's.

Im not realy a wizzard in Memory Reading, just using the functions i found on the net!

I can say the offsets work cus in Cheat Engine it works and got the desired effect in game.

I think the Problem is in the ReadMemory() but as i said earlier, thats a bit out of my league.

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance Force


PROGRAM = Battlefield 4
CLIENTGAMECONTEXT = 0x1424a0c00 ;0 +  Base
OFFSET_ANGLES = 0x1421e3400 
;---------gamecontext----------
ClientPlayerManager = 0x60 ;GameContext 1
IdToPlayerMapOffset = 0x548 ;ClientPlayerManager
;------------------ReadLocalPlayer --------------------
ClientPlayer = 0x540 ;ClientPlayerManager 2
ClientSoldier = 0x14d0 ;ClientPlayer 3
ClientReplication = 0x490 ;ClientSoldier
soldierWeaponsComponent = 0x570 ;ClientSoldier 4
breathControlHandler = 0x588 ;clientSoldier
pHealthComponent = 0x140 ;ClientSoldier
ActiveSlot = 0x0a98 ;SoldierWeaponCompenent 5
CurrentAnimatedWeaponHandler = 0x0890 ;soldierWeaponComponent
ClientSoldierWeapon = * 0x8 ;currentAnimantedWeaponHandler + ActiveSlot
CorrectedFiring = 0x49c0 ;Angles
WeaponSway = 0x78 ;CorrectedFiring
WeaponSwayData = 0x08 ;WeaponSway
;---------------------PlayerData-------------------
Offset_InVehicle = 0x14c0 ;clientPlayer
Offset_TeamID = 0x13cc ;Clientplayer
Offset_Health = 0x20 ;pHealthComponent
Offset_projectilesLoaded = 0x01a0 ;CorrectedFiring
Offset_ProjectilesInMagagzines = 0x01a4 ;CorrectedFiring
Offset_PositionX = 0x30 ;clientReplication
Offset_PositionY = 0x34 ;ClientReplication
Offset_PositionZ = 0x38 ;clientReplication
Offset_flYaw = 0x4D8 ;clientSoldier
;--------ReadPlayer(id)------------

;----noRecoil----------------
;Write nothing in FLOAT to WeaponSwayData +:
;0x444
;Write nothing in FLOAT to WeaponSwayData +:
;0x440
OffsetAmmo1 = 0x138
OffsetAmmo2 = 0x128
OffsetAmmo3 = 0x2C0
OffsetAmmo4 = 0x1B0
OffsetAmmo5 = 0x100
Pointers = [0x138,0x128,0x2C0,0x1B0,0x100]


{
BaseAdrr := Convert((getProcessBaseAddress(PROGRAM,3)),"H")
PointerAmmo1 := Convert(ReadMemory(BaseAdrr+0x0246F118,PROGRAM),"H")
PointerAmmo2 := Convert(ReadMemory(PointerAmmo1+OffsetAmmo1,PROGRAM),"H")
PointerAmmo3 := Convert(ReadMemory(PointerAmmo2+OffsetAmmo2,PROGRAM),"H")
PointerAmmo4 := Convert(ReadMemory(PointerAmmo3+OffsetAmmo3,PROGRAM),"H")
PointerAmmo5 := Convert(ReadMemory(PointerAmmo4+OffsetAmmo4,PROGRAM),"H")
PointerAmmo6 := Convert(ReadMemory(PointerAmmo5+OffsetAmmo5,PROGRAM),"H")
AmmoInMag := Convert(PointerAmmo6,"D")

Tooltip % BaseAdrr "  " PointerAmmo1 "  " PointerAmmo2 "  " PointerAmmo3 " " PointerAmmo4 "  " PointerAmmo5 "  " PointerAmmo6 "  " AmmoInMag " "
}



	Loop
	{
	Addr_BaseAddr := getProcessBaseAddress(PROGRAM)
	Addr_gameContext := Addr_BaseAddr + 0x24a0c00
	Addr_ClientPlayerManager := ReadMemory(Addr_gameContext+ClientPlayerManager,PROGRAM)
	Addr_ClientPlayer := ReadMemory(Addr_ClientPlayerManager+ClientPlayer,PROGRAM) ;FAILED!
	Addr_ClientSoldier := ReadMemory(Addr_ClientPlayer+ClientSoldier,PROGRAM)
	Addr_SoldierWeaponComponent := ReadMemory(Addr_ClientSoldier+SoldierWeaponComponent,PROGRAM)
	Addr_ActiveSlot := ReadMemory(Addr_SoldierWeaponComponent+ActiveSlot,PROGRAM)
	Tooltip % " 1 " Addr_BaseAddr " 2 "  Addr_gameContext " 3 " Addr_ClientPlayerManager " 4" Addr_ClientPlayer "  5 " Addr_ClientSoldier " 6 " Addr_SoldierWeaponComponent "  7 "  Addr_ActiveSlot
}
	

; wont correctly handle 8 bytes with extreme values



ReadMemory(MADDRESS=0,PROGRAM="",BYTES=4)
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE, BYTES,0)
   If (PROGRAM != OLDPROC || !ProcessHandle)
   {
      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",BYTES,"UInt *",0))
      return  !ProcessHandle ? "Handle Closed: " closed : "Fail"
   else if (BYTES = 1)
      Type := "UChar"
   else if (BYTES = 2)
      Type := "UShort"
   else if (BYTES = 4)
      Type := "UInt"
   else 
   {
      loop % BYTES 
          result += numget(MVALUE, A_index-1, "Uchar") << 8 *(A_Index-1)
      return result
   }

   return numget(MVALUE, 0, Type)
}
; 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_Str()"

; the lengths probably depend on the encoding style, but for my needs they are always 1

;//function ReadMemory_Str 
ReadMemory_Str(MADDRESS=0, PROGRAM = "", length = 0 , terminator = "")  ; "" = Null
{ 
    Static OLDPROC, ProcessHandle

    If (PROGRAM != OLDPROC || !ProcessHandle)
    {
        WinGet, pid, pid, % OLDPROC := PROGRAM
        ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
        ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
        ,"Int",16,"Int",0,"UInt",pid) : 0) ;PID is stored in value pid
    }
    ; length depends on the encoding too
    VarSetCapacity(Output, length ? length : 1, 0)
    If !length ; read until terminator found or something goes wrong/error
	{
        Loop
        { 
            success := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS++, "str", Output, "Uint", 1, "Uint *", 0) 
            if (ErrorLevel || !success || Output = terminator) 
                break
            teststr .= Output 
		} 
	}		
	Else ; will read X length
	{
        DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "str", Output, "Uint", length, "Uint *", 0) 
        ;  Loop % length
        ;     teststr .= chr(NumGet(Output, A_Index-1, "Char"))      
        teststr := StrGet(&Output, length, "UTF-8")
	}
	return teststr 	 
}

;This version of getProcessBaseAddress will work with both 32 and 64 bit versions of AHK.
; Return values:
;   Null        The process's window couldn't be found.
;   0           The GetWindowLong or GetWindowLongPtr call failed.
;   Non-Zero    The base address of the process (success).

getProcessBaseAddress(WindowTitle, windowMatchMode := "3")    ;WindowTitle can be anything ahk_exe ahk_class etc
{
    if (windowMatchMode && A_TitleMatchMode != windowMatchMode)
    {
        mode := A_TitleMatchMode ; This is a string and will not contain the 0x prefix
        StringReplace, windowMatchMode, windowMatchMode, 0x ; remove hex prefix as SetTitleMatchMode will throw a run time error. This will occur if integer mode is set to hex and matchmode param is passed as an number not a string.
        SetTitleMatchMode, %windowMatchMode%    ;mode 3 is an exact match
    }
    WinGet, hWnd, ID, %WindowTitle%
    if mode
        SetTitleMatchMode, %mode%    ; In case executed in autoexec
    if !hWnd
        return ; return blank failed to find window
    return DllCall(A_PtrSize = 4     ; If DLL call fails, returned value will = 0
        ? "GetWindowLong"
        : "GetWindowLongPtr"
        , "Ptr", hWnd, "Int", -6, A_Is64bitOS ? "Int64" : "UInt")  
        ; For the returned value when the OS is 64 bit use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit 
        ; however if the OS is 32 bit, must use UInt, otherwise the number will be huge (however it will still work as the lower 4 bytes are correct)      
        ; Note - it's the OS bitness which matters here, not the scripts/AHKs
} 

;H for Hex D for Dec
Convert(Number=0, ConvertTo="") {
	TmpNum := Number
	Ok := False
	If TmpNum Is Integer
		Ok := True
	Else If TmpNum Is Xdigit
	{
		Ok := True
		TmpNum := "0x" TmpNum
	} Else If (InStr(TmpNum, "0x"))
		Ok := True
	Else
		Return -1
	If (Ok)
		If (ConvertTo = "D" ) {
			SetFormat Integer, D
			TmpNum += 0
			SetFormat Integer, H
			Return TmpNum
		} Else If (ConvertTo = "H") {
			SetFormat Integer, H
			TmpNum += 0
			SetFormat Integer, D
			Return TmpNum
		} Else
			Return -2
	Else
		Return -3
}


pointer(game, base, offsets*)
{ 
	For index, offset in offsets
	{
		if (index = offsets.maxIndex() && A_index = 1)
			pointer := offset + ReadMemory(base, game)
		Else 
		{
			IF (A_Index = 1) 
				pointer := ReadMemory(offset + ReadMemory(base, game), game)
			Else If (index = offsets.MaxIndex())
				pointer += offset
			Else pointer := ReadMemory(pointer + offset, game)
		}
	}	
	Return ReadMemory(pointer, game)
}


RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

So this is where it fails?

 Addr_ClientPlayer := ReadMemory(Addr_ClientPlayerManager+ClientPlayer,PROGRAM) ;FAILED!

What is the value of this address (Addr_ClientPlayerManager + ClientPlayer) in CE? 

Is it a 4-byte ptr?

What is A_lastError? ie

Addr_ClientPlayer := ReadMemory(Addr_ClientPlayerManager+ClientPlayer,PROGRAM) ;FAILED!
msgbox % A_LastError " | " Addr_ClientPlayer


Wyvern010
  • Members
  • 24 posts
  • Last active: Jul 11 2016 11:17 PM
  • Joined: 30 Mar 2015
✓  Best Answer

I Got it working, there was a Fault in the order of Offsets so to say

 

Original code: " WRONG" 

Addr_BaseAddr := getProcessBaseAddress(PROGRAM)
 
Addr_gameContext := Addr_BaseAddr + 0x24a0c00           ;Only Added the value, but didnt get the adress it points to.
Addr_ClientPlayerManager := ReadMemory(Addr_gameContext+ClientPlayerManager,PROGRAM)
Addr_ClientPlayer := ReadMemory(Addr_ClientPlayerManager+ClientPlayer,PROGRAM) ;FAILED!
 
Addr_ClientSoldier := ReadMemory(Addr_ClientPlayer+ClientSoldier,PROGRAM)
Addr_SoldierWeaponComponent := ReadMemory(Addr_ClientSoldier+SoldierWeaponComponent,PROGRAM)
Addr_ActiveSlot := ReadMemory(Addr_SoldierWeaponComponent+ActiveSlot,PROGRAM)
 
"Good":
Addr_BaseAddr := getProcessBaseAddress(PROGRAM)
Addr_gameContext := ReadMemory(Addr_BaseAddr + CLIENTGAMECONTEXT,PROGRAM) 
Addr_ClientPlayerManager := ReadMemory(Addr_gameContext+ClientPlayerManager,PROGRAM) ;
Addr_ClientPlayer := ReadMemory(Addr_ClientPlayerManager+ClientPlayer,PROGRAM) 
Addr_ClientSoldier := ReadMemory(Addr_ClientPlayer+ClientSoldier,PROGRAM)
Addr_SoldierWeaponComponent := ReadMemory(Addr_ClientSoldier+soldierWeaponsComponent,PROGRAM)
Addr_ActiveSlot := ReadMemory(Addr_SoldierWeaponComponent+ActiveSlot,PROGRAM)
 
i Guess coding with 3 hours sleep isn't a good idea,
Thanks for the reply though :)