簡體   English   中英

Golang 根據進程句柄和偏移量計算另一個進程內存的地址

[英]Golang Calculate address of another process memory based on process handle and offset

我需要從具有給定進程名稱/id、指針和偏移量的另一個進程的內存中讀取值並將其實時輸出給用戶,我已經找到了另一個問題並成功實現了從進程內存的給定地址讀取和轉換浮點值的邏輯,但由於每次重新加入游戲時地址都會改變,我需要計算它。 我使用作弊引擎找到了指針和進程偏移:

在此處輸入圖像描述

根據我對閱讀理論的理解,最終地址需要使用以下算法計算:

  1. 使用常量偏移量 (+02518790) 計算基地址 (1DC45993300)
  2. 取這個地址並向它添加指針值
  3. 對從底部 (5E0) 到頂部 (2E4) 的每個指針值重復 2 步
  4. 這是您可以用來檢索數據的最終地址

我對步驟 2、3 和 4 沒有任何問題:我可以對十六進制數求和並在地址處 讀取進程內存,但我不知道如何使用偏移量來計算第一個地址,如何在 Go 中做到這一點? 我正在嘗試在 Windows 10 上執行此操作

更新:我嘗試了這個問題的代碼,但它返回了不正確的基地址。 我得到 7ff611530000 而作弊引擎中的實際基地址是 1A009A6AB70

更新 2:可能很難理解我想要做什么,所以我添加了另一張圖片。 我需要找到如何進行這個“加號”操作以及如何在紅色方塊中找到地址(綠色可以計算,紫色是常數)

在此處輸入圖像描述

為了找到另一個進程的地址和讀取值,您必須根據進程的偏移量和基地址來計算它。 作弊引擎將讀取地址值操作顯示為 [hex + hex] -> 在指針編輯器中的地址。 因此,每次您看到 [address + offset] -> next address 時,都表示將地址和偏移量求和為十六進制 (16),並在進程內存中讀取此地址的值。 檢索到的值是下一個地址,您應該使用它來獲取下一個地址。 重復此操作,直到到達最后一個偏移量,然后將地址和偏移量相加而不讀取值。 結果地址是存儲值的位置。

如何找到基地址? 雖然它在 Cheat Engine 中可能看起來是恆定的(如果你輸入 0 而不是 02518790,那么每次重啟進程都會得到相同的地址),但它只是一個虛擬地址,不要使用它。 相反,使用 winapi 使用 EnumProcessModules 遍歷指定進程的所有模塊。 您可以通過按窗口標題在正在運行的應用程序中搜索來找到 PID。 將模塊的文件名與 GetModuleFilenameExW 進行比較。 當您找到具有常量文件名的模塊(在您的情況下為“UE4Game-Win64-Shipping.exe”)時,使用 GetModuleInformation 檢索 LpBaseOfDll。 不是入口點,它不是基地址。

現在您已經有了 LpBaseOfDll,向它添加常量偏移量 (02518790) 並在結果地址處讀取值。 這是您應該用來運行循環和添加偏移量的起始地址。 所以圖像上標記的“加號操作”是 LpBaseOfDll 和偏移量的總和。 事實上,作弊引擎只接受不帶偏移量的可執行文件名,嘗試將“kernel32.dll”放入地址字段:)

要與虛擬內存交互,必須使用 windows 原生 api (kernel32.dll)。 與任何其他語言一樣,Go 有一個 winapi 包裝器。 您可以在經典硬編碼“golang.org/x/sys/windows”、現代和實驗性“github.com/Andoryuuta/kiwi”之間進行選擇,但我建議您使用“github.com/0xrawsec/golang-win32/win32” /內核32”。

下面的代碼演示了如何獲取基地址。 我發布了帶有完整代碼的GitHub gist ,可以按名稱查找進程 ID 並讀取 float32 值。

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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM