14
votes

Good evening,

I've been trying to build a golang application which scans values in memory but am struggling trying to understand how to address specific memory locations. I know that when accessing memory within the application you can use *variablename to deference and get the address location, but how would I provide an address location and print the value to the screen or grab the next allocated object of any size from RAM and print it's value?

Thanks in advance for any help you may be willing to share

1
Do you want to read your process memory, I hope, and not system memory, right? Because the operating system usually disallows processes to read outside their memory space.AkiRoss
Also, the quality of the answer may be OS-dependent. Is your question relative to any OS, and do you want to operate within go's limits, or are you available to consider OS-dependent solutions?AkiRoss
@AkiRoss — this is a macintosh application reading another processes memory. I am open to Mac and Windows focused solutions thoughkkirsche
Normally, a non-root process cannot read the memory of another process due to OS' memory protection mechanisms (edit: and even root processes can't do it very easily). So, you probably need some external agent allowing you to read the other process' memory, such as the /proc pseudo-filesystem in Linux (unix.stackexchange.com/questions/6301/…) - you may want to search for similar mechanisms under mac, but I am not aware of any.AkiRoss
BOUNTY EDIT: We are talking about Windows-OS!C4d

1 Answers

9
votes

I don't know how much useful this will be, but here is a sample code.

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var i int = 1
    fmt.Println("Address : ", &i, " Value : ", i)

    var address *int
    address = &i // getting the starting address

    loc := (uintptr)(unsafe.Pointer(address))
    p := unsafe.Pointer(loc)

    // verification - it should print 1
    var val int = *((* int)(p))
    fmt.Println("Location : ", loc, " Val :",val) // it does print !!

    // lets print 1000 bytes starting from address of variable i
    // first memory location contains 1 as expected
    printValueAtMemoryLocation(loc, 1000)

    // now lets test for some arbitrary memory location
    // not so random ! wanted to reduce the diff value also any arbitrary memory location you can't read !!
    memoryToReach := 842350500000
    loc = changeToInputLocation(loc, memoryToReach)
    fmt.Println("Loc is now at : ", loc)
    // lets print 1000 bytes starting from the memory location "memoryToReach"
    printValueAtMemoryLocation(loc, 1000)

}

func changeToInputLocation(location uintptr, locationToreach int) uintptr {
    var diff,i int
    diff = locationToreach - int(location)

    fmt.Println("We need to travel ", diff, " memory locations !")

    if diff < 0 {
        i= diff * -1
        for i > 0 {
            location--
            i--
        }
    } else {
        i= diff
        for i > 0 {
            location++
            i--
        }
    }
    return location
}

func printValueAtMemoryLocation(location uintptr, next int) {
    var v byte
    p := unsafe.Pointer(location)
    fmt.Println("\n")
    for i:=1; i<next; i++ {
        p = unsafe.Pointer(location)
        v = *((*byte)(p))
        fmt.Print(v," ")
        //fmt.Println("Loc : ", loc, " --- Val : ", v)
        location++
    }
    fmt.Println("\n")
}

Using "unsafe" package is not a good idea, also you can not read any arbitrary location I believe.

For me when I tried some other random locations where, most probably, I didn't have read access, it threw me error like this:

unexpected fault address 0xc41ff8f780
fatal error: fault
[signal SIGBUS: bus error code=0x2 addr=0xc41ff8f780 pc=0x1093ec0]

But hopefully, it can be of some value to you.