Чтение памяти другого процесса (linux) в golang
Я пытаюсь сделать консольную версию "чит-движка", это программа, в которой пользователь может найти и изменить любые байты / байты памяти в каком-то другом процессе. Для обучения моим навыкам го я выбрал этот язык. Однако я столкнулся с некоторыми трудностями. Во-первых, я хотел бы задать несколько вопросов не о golang, а о чтении памяти процесса в linux:
- Могу ли я прочитать память, используя только ptrace без чтения / proc / $ pid / mem?
- Как узнать начальный и конечный адреса процесса без чтения / proc / $ pid / maps?
- Если я могу найти начальный и конечный адреса из / proc / $ pid / maps, какой раздел мне выбрать?
Возвращаясь к Голангу, я нашел 2 библиотеки, которые предоставляют оболочку системных вызовов и ptrace: https://godoc.org/github.com/hjr265/ptrace.go/ptrace https://gowalker.org/github.com/tfogal/ptrace
Обе эти библиотеки используют uintptr как тип адреса, где вы можете читать данные из памяти. Но когда я ввожу адрес, он имеет тип int64. Как я могу привести его из int64 в uintptr? Если я скомпилирую программу с жестко закодированным значением адреса, она будет работать нормально. Но, если я использую переменную для этого, я получил ошибку.
Мой черновой вариант программы:
package main
import (
"fmt"
"os"
"strconv"
"log"
"github.com/tfogal/ptrace"
)
func findValueInProcessMemory(pid int) {
_, err := os.FindProcess(pid)
if err != nil {
fmt.Printf("Error opening process: %v\n", err)
panic("FindProcess")
}
t, err := ptrace.Attach(pid)
if err != nil {
fmt.Printf("Error attaching to process: %v\n", err)
panic("AttachProcess")
}
fmt.Printf("Process [%d] attached.\n", pid)
var startAddr uintptr = 0x00400000;
wd, err := t.ReadWord(startAddr) // THIS WORKS FINE
if err != nil {
log.Fatalf("Could not read first word of program image: %v\n", err)
}
fmt.Printf("We've found value: %d at 0x00400000.\n", wd)
/*
for addr := start; addr < end; addr += searchValLen {
res, err := t.ReadWord(addr) // HERE IS AN ISSUE WITH READING MEMORY
resInt := int64(res)
if err != nil {
log.Fatalf("Read error: %s\n", err.Error())
}
if resInt == searchVal {
fmt.Printf("Value found at [0x%x].\n", addr)
}
}
*/
err = t.Detach()
if err != nil {
log.Fatalf("Detach error: %s\n", err.Error())
}
fmt.Printf("Process [%d] detached.\n", pid)
}
func main() {
pid, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Printf("Error getting process id: %v\n", err)
}
start, err := strconv.ParseInt(os.Args[2], 0, 32)
if err != nil {
fmt.Printf("Error getting start address: %v\n", err)
}
end, err := strconv.ParseInt(os.Args[3], 0, 32)
if err != nil {
fmt.Printf("Error getting end address: %v\n", err)
}
searchVal, err := strconv.ParseInt(os.Args[4], 0, 32)
if err != nil {
fmt.Printf("Error getting search value: %v\n", err)
}
searchValLen, err := strconv.ParseInt(os.Args[5], 0, 32)
if err != nil {
fmt.Printf("Error getting length of search value: %v\n", err)
}
fmt.Printf("Process id: %v\n", pid)
fmt.Printf("Start addr: %v\n", start)
fmt.Printf("End addr: %v\n", end)
fmt.Printf("Search value: %v\n", searchVal)
fmt.Printf("Length of search value: %v\n", searchValLen)
findValueInProcessMemory(pid)
}
Команда для запуска: ./test 26484 0x400000 0x401000 125 1