A => README.md +3 -0
@@ 0,0 1,3 @@
+memdump - a tool for dumping the memory of a process into a file
+================================================================
+Runs with linux only. Because of the limitations of Go this program will not work on 64-bit machines.
A => cmd/dump/main.go +53 -0
@@ 0,0 1,53 @@
+package main
+
+import (
+ "bitbucket.org/telesto/memdump"
+ "flag"
+ "fmt"
+ "os"
+)
+
+func usage() {
+ fmt.Fprintln(os.Stderr, "usage: dump -p pid")
+}
+
+func main() {
+ pid := flag.Int("pid", 0, "pid of the process to dump")
+ split := flag.Bool("s", false, "write one file for each memory region")
+ file := flag.String("o", "", "write regions into file")
+
+ flag.Parse()
+ if *pid <= 0 {
+ usage()
+ os.Exit(0)
+ }
+
+ maps, err := memdump.ParseMappings(*pid)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ conn, err := memdump.Open(*pid)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ for i := range maps {
+ if *split {
+ err = memdump.Dump(conn, maps[i].Start, maps[i].End)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ conn.Close()
+ os.Exit(1)
+ }
+ }
+ if len(*file) != 0 {
+ // todo:
+ }
+ }
+ if err := conn.Close(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+}
A => linux.go +34 -0
@@ 0,0 1,34 @@
+package memdump
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+const proc = "/proc"
+
+func openMemory(pid int) (*os.File, error) {
+ return os.Open(fmt.Sprintf("%s/%d/mem", proc, pid))
+}
+
+func ParseMappings(pid int) ([]MemoryRegion, error) {
+ c, err := ioutil.ReadFile(fmt.Sprintf("%s/%d/maps", proc, pid))
+ if err != nil {
+ return nil, err
+ }
+ maps := []MemoryRegion{}
+ for _, line := range bytes.Split(bytes.TrimSpace(c), []byte{'\n'}) {
+ var r MemoryRegion
+ n, err := fmt.Sscanf(string(line), "%x-%x", &r.Start, &r.End)
+ if err != nil {
+ return nil, err
+ }
+ if n != 2 {
+ return nil, fmt.Errorf("needed %d values for scanning, found %d", 2, n)
+ }
+ maps = append(maps, r)
+ }
+ return maps, nil
+}
A => memdump.go +61 -0
@@ 0,0 1,61 @@
+package memdump
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "syscall"
+)
+
+type MemoryRegion struct {
+ Start, End int64
+}
+
+type Connection interface {
+ io.ReaderAt
+ io.Closer
+}
+
+type connection struct {
+ pid int
+ *os.File
+}
+
+func (c *connection) Close() error {
+ err := c.File.Close()
+ err1 := syscall.PtraceDetach(c.pid)
+ if err1 != nil {
+ err = err1
+ }
+ return err
+}
+
+func Open(pid int) (Connection, error) {
+ var err error
+ if err = syscall.PtraceAttach(pid); err != nil {
+ return nil, err
+ }
+ if pid, err = syscall.Wait4(pid, nil, 0, nil); err != nil {
+ return nil, err
+ }
+ conn, err := openMemory(pid)
+ if err != nil {
+ syscall.PtraceDetach(pid)
+ return nil, err
+ }
+ return &connection{pid, conn}, nil
+}
+
+func Dump(conn Connection, start, end int64) error {
+ dump, err := os.Create(fmt.Sprintf("%x-%x.bin", start, end))
+ defer dump.Close()
+ if err != nil {
+ return err
+ }
+ written, err := io.Copy(dump, io.NewSectionReader(conn, start, end))
+ if written != end-start {
+ return fmt.Errorf("written %d bytes, expected %d bytes to copy",
+ written, end-start)
+ }
+ return err
+}