Skip to content

Instantly share code, notes, and snippets.

@RednibCoding
Last active July 4, 2018 00:07
Show Gist options
  • Save RednibCoding/4d9e1a3dc309cfd5f5af3089a67abac0 to your computer and use it in GitHub Desktop.
Save RednibCoding/4d9e1a3dc309cfd5f5af3089a67abac0 to your computer and use it in GitHub Desktop.
Example of how to open/read/write process memory on Windows with Golang
package main
import (
"bytes"
"encoding/binary"
"fmt"
"syscall"
"unsafe"
)
type Process uintptr
var kernel32 = syscall.MustLoadDLL("kernel32.dll")
const PROCESS_TERMINATE = 0x0001
const PROCESS_CREATE_THREAD = 0x0002
const PROCESS_SET_SESSIONID = 0x0004
const PROCESS_VM_OPERATION = 0x0008
const PROCESS_VM_READ = 0x0010
const PROCESS_VM_WRITE = 0x0020
const PROCESS_DUP_HANDLE = 0x0040
const PROCESS_CREATE_PROCESS = 0x0080
const PROCESS_SET_QUOTA = 0x0100
const PROCESS_SET_INFORMATION = 0x0200
const PROCESS_QUERY_INFORMATION = 0x0400
const PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
func main() {
pid := 0 // process id
var address uintptr = 0x31CE6590 // address to read
var size uintptr = 4 // size to read
// get pid from user
fmt.Print("Input PID: ")
fmt.Scanf("%d", &pid)
// open process
handle := OpenProcessHandle(pid, PROCESS_ALL_ACCESS)
// print the handle
fmt.Printf("handle: %d\n", handle)
fmt.Scanln()
var bufferIn = []byte{0, 0, 0, 0} // buffer that holds read data
// read data from memory location
data1 := ReadProcessMemory(handle, address, bufferIn, size)
fmt.Println(data1)
fmt.Scanln()
// write data to memory location
var bufferOut = intToBytes(1000) // buffer that holds write data
bytesWritten, ret := WriteProcessMemory(handle, address, bufferOut, size)
fmt.Println(bytesWritten)
fmt.Println(ret)
// read data from memory location
data2 := ReadProcessMemory(handle, address, bufferIn, size)
fmt.Println(data2)
fmt.Scanln()
}
// Wrapper function for OpenProcess
func OpenProcessHandle(processId int, access int) Process {
proc := kernel32.MustFindProc("OpenProcess")
handle, _, _ := proc.Call(ptr(access), ptr(false), ptr(processId))
return Process(handle)
}
// Wrapper function for ReadProcessMemory
func ReadProcessMemory(handle Process, address uintptr, buffer []byte, nSize uintptr) int32 {
proc := kernel32.MustFindProc("ReadProcessMemory")
ret, _, e := proc.Call(
uintptr(handle),
address,
uintptr(unsafe.Pointer(&buffer[0])),
nSize)
if ret == 0 {
fmt.Println(" Error:", e)
} else {
return bytesToInt(buffer)
}
return 0
}
// Wrapper function for ReadProcessMemory
func WriteProcessMemory(handle Process, address uintptr, buffer []byte, nSize uintptr) (int, bool) {
proc := kernel32.MustFindProc("WriteProcessMemory")
var nBytesWritten int
ret, _, _ := proc.Call(
uintptr(handle),
address,
uintptr(unsafe.Pointer(&buffer[0])),
nSize,
uintptr(unsafe.Pointer(&nBytesWritten)),
)
return nBytesWritten, ret != 0
}
// Converts types
func ptr(val interface{}) uintptr {
switch val.(type) {
case string:
return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(val.(string))))
case int:
return uintptr(val.(int))
default:
return uintptr(0)
}
}
// Converts >= 4 byte array to int32
func bytesToInt(byteArray []byte) int32 {
return *(*int32)(unsafe.Pointer(&byteArray[0]))
//return int32(uint32(byteArray[0]) + uint32(byteArray[1])<<8 + uint32(byteArray[2])<<16 + uint32(byteArray[3])<<24)
}
// Converts an int to []byte
func intToBytes(myInt int32) []byte {
buf := new(bytes.Buffer)
//var num uint16 = 1234
err := binary.Write(buf, binary.LittleEndian, myInt)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
return buf.Bytes()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment