3

I need to read value from memory of another process with given process name/id, pointer and offset and output it to the user in realtime, I already found another question and successfully implemented logic to read and convert float values from given address of process memory, but since address is changing every time I rejoin the game, I need to calculate it. I have found pointer and process offset using cheat engine:

enter image description here

From what I understood reading theory, final address needs to be calculated using this algorithm:

  1. Calculate base address (1DC45993300) using constant offset (+02518790)
  2. Take this address and add pointer value to it
  3. Repeat 2 step with every pointer value from bottom (5E0) to top (2E4)
  4. This is the final address that you can use to retreive data

I have no problem with steps 2, 3 and 4: I can sum hex numbers and read process memory at address, but I don't know how to use offset to calculate the first address, how to do this in Go? I'm trying to do this on Windows 10

Update: I tried code from this question but it returns incorrect base address. I get 7ff611530000 while actual base address in cheat engine is 1A009A6AB70

Update 2: It may be hard to understand what am I trying to do, so I added another picture. I need to find how to make this "plus" operation and how to find address in red square (green can be calculated, purple are constants)

enter image description here

VityaSchel
  • 579
  • 7
  • 18
  • 1
    In general, you cannot read or write some *other* process's memory. OSes do often provide a way for debuggers to do this, but it's via the address *in* that other process, with the OS determining whether you're allowed to do that in the first place, and then doing it (which may involve doing paging, if the memory for the other process is paged out at the moment). – torek Apr 02 '22 at 23:49
  • 1
    @torek, reading and writing to other processes' memory is possible, and Cheat Engine does it. – Sherif Elmetainy Jun 13 '22 at 14:32
  • @SherifElmetainy: doing this completely bypasses security, so OSes restrict who can do it and when. If the OS fails this restriction process, we get CVEs. All of this is far outside the scope of normal Go programming. – torek Jun 13 '22 at 17:46
  • @torek how does cheat programs works? hex editors? I wouldn't mind connecting any other language to Go just to read base address. In fact, I already did everything else: I can read other process memory in real time, I can find values and convert them, constants work, when I put base address from Cheat Engine. I just need to find a way to get base address of process, I doubt it's more restricted than reading value by exact address, correct me if I'm wrong :) – VityaSchel Jun 14 '22 at 10:20
  • That's highly OS-dependent. On a Linux system, for instance, you just use the `/proc` interface to read and write directly to some other process's memory. On old PDP-11 systems, you'd read out the swap maps and (knowing that another process is always swapped out while you're running) take its address plus its swap map to locate the swap-space area. What this particular program is doing on your particular OS and hardware combination, I don't know—you haven't mentioned the OS and hardware (though `.exe` might imply Windows and `Win64` almost certainly does). – torek Jun 14 '22 at 10:27
  • @torek Yes, sorry for confusion, I'm doing all this on Windows, should have mentioned it in the question body. I'll add this now. Is there a way to do that on Windows 10 64 with admin rights? – VityaSchel Jun 14 '22 at 11:26
  • *Is there a way to do that on Windows 10 64 with admin rights?* Almost certainly yes, but I don't use or program Windows. You'll need a Windows expert for the Windows parts of this; once those are solved, the Go parts are probably trivial (just use `uintptr` to do the arithmetic). – torek Jun 15 '22 at 00:44
  • 1
    Note that, as in the answer you linked, you may need the occasional trick to avoid having Go's GC some data. The syscall package in the Go runtime has these sprinkled about for the same reason. (The runtime is full of oddball tricks like this.) – torek Jun 15 '22 at 00:52

1 Answers1

1

In order to find address and read value of another process, you must calculate it, based on offsets and base address of process. Cheat engine shows reading address value operation as [hex + hex] -> address in pointer editor. So everytime you see [address + offset] -> next address, it means sum address and offset as hex (16) and read value at this address in process memory. Retrieved value is the next address, which you should use to get the following one. Repeat this until you get to the last offset, then just sum address and offset without reading value. The resulted address is where the value stored.

How to find base address? Although it may seem to be constant in Cheat Engine (if you put 0 instead of 02518790, you'll get the same address each time you restart process), it's just a virtual address, don't use it. Instead, use winapi to iterate through all modules of the specified process using EnumProcessModules. You can find PID by searching in running apps by window's title. Compare module's filename with GetModuleFilenameExW. When you found the module with constant filename ("UE4Game-Win64-Shipping.exe" in your case), use GetModuleInformation to retrieve LpBaseOfDll. Not EntryPoint, which is not base address.

Now that you have LpBaseOfDll, add constant offset to it (02518790) and read value at resulted address. This is your starting address that you should use to run the loop and add offsets. So the "plus operation" labelled on image is sum of LpBaseOfDll and offset. In fact, Cheat Engine accepts just executable name without offset, try putting "kernel32.dll" into address field :)

To interact with virtual memory, you must use windows native api (kernel32.dll). As in any other language, Go has a wrapper for winapi. You can choose between classic hardcoded "golang.org/x/sys/windows", modern and experimental "github.com/Andoryuuta/kiwi", but I would recommend you to use "github.com/0xrawsec/golang-win32/win32/kernel32".

The code below demonstrates how to get base address. I published GitHub gist with full code that can find process ID by name and read float32 values.

package main

import (
    "fmt"
    "path/filepath"

    "github.com/0xrawsec/golang-win32/win32"
    kernel32 "github.com/0xrawsec/golang-win32/win32/kernel32"
    windows "golang.org/x/sys/windows"
)

func memoryReadInit(pid uint32) (int64, bool) {
    win32handle, _ := kernel32.OpenProcess(0x0010 | windows.PROCESS_VM_READ | windows.PROCESS_QUERY_INFORMATION, win32.BOOL(0), win32.DWORD(pid))
    moduleHandles, _ := kernel32.EnumProcessModules(win32handle)
    for _, moduleHandle := range moduleHandles {
        s, _ := kernel32.GetModuleFilenameExW(win32handle, moduleHandle)
        targetModuleFilename := "UE4Game-Win64-Shipping.exe"
        if(filepath.Base(s) == targetModuleFilename) {
            info, _ := kernel32.GetModuleInformation(win32handle, moduleHandle)
            return int64(info.LpBaseOfDll), true
        }
    }
    return 0, false
}

func main() {
    var pid uint32 = 0x38E4 // put PID here, you can find it in Cheat Engine process list
    baseAddress, _ := memoryReadInit(pid)
    fmt.Println("Base address is", baseAddress)
}
Dmitriy
  • 76
  • 1