From 1bb4d6685c83372a267b78925f74024081bf4e41 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Tue, 13 Oct 2015 19:38:36 -0700 Subject: [PATCH] add Go README and sample.go --- bindings/go/README.md | 29 ++++++++++++ bindings/go/sample.go | 105 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 bindings/go/README.md create mode 100644 bindings/go/sample.go diff --git a/bindings/go/README.md b/bindings/go/README.md new file mode 100644 index 00000000..3433dad9 --- /dev/null +++ b/bindings/go/README.md @@ -0,0 +1,29 @@ +To download/update the Unicorn Go bindings, run: + + go get -u github.com/unicorn-engine/unicorn/bindings/go + +A very basic usage example follows + +_(Does not handle most errors for brevity. Please see sample.go for a more hygenic example):_ + + package main + + import ( + "fmt" + uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" + ) + + func main() { + mu, _ := uc.NewUnicorn(uc.ARCH_X86, uc.MODE_32) + // mov eax, 1234 + code := []byte{184, 210, 4, 0, 0} + mu.MemMap(0x1000, 0x1000) + mu.MemWrite(0x1000, code) + if err := mu.Start(0x1000, 0x1000+uint64(len(code))); err != nil { + panic(err) + } + eax, _ := mu.RegRead(uc.X86_REG_EAX) + fmt.Printf("EAX is now: %d\n", eax) + } + +An example program exercising far more Unicorn functionality and error handling can be found in sample.go. diff --git a/bindings/go/sample.go b/bindings/go/sample.go new file mode 100644 index 00000000..eeeb6195 --- /dev/null +++ b/bindings/go/sample.go @@ -0,0 +1,105 @@ +package main + +import ( + "encoding/hex" + "fmt" + uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" + "strings" +) + +var asm = strings.Join([]string{ + "48c7c003000000", // mov rax, 3 + "0f05", // syscall + "48c7c700400000", // mov rdi, 0x4000 + "488907", // mov [rdi], rdx + "488b07", // mov rdx, [rdi] + "4883c201", // add rdx, 1 +}, "") + +func addHooks(mu uc.Unicorn) { + mu.HookAdd(uc.HOOK_BLOCK, func(mu uc.Unicorn, addr uint64, size uint32) { + fmt.Printf("Block: 0x%x, 0x%x\n", addr, size) + }) + mu.HookAdd(uc.HOOK_CODE, func(mu uc.Unicorn, addr uint64, size uint32) { + fmt.Printf("Code: 0x%x, 0x%x\n", addr, size) + }) + mu.HookAdd(uc.HOOK_MEM_READ|uc.HOOK_MEM_WRITE, func(mu uc.Unicorn, access int, addr uint64, size int, value int64) { + if access == uc.MEM_WRITE { + fmt.Printf("Mem write") + } else { + fmt.Printf("Mem read") + } + fmt.Printf(": @0x%x, 0x%x = 0x%x\n", addr, size, value) + }) + invalid := uc.HOOK_MEM_READ_INVALID | uc.HOOK_MEM_WRITE_INVALID | uc.HOOK_MEM_FETCH_INVALID + mu.HookAdd(invalid, func(mu uc.Unicorn, access int, addr uint64, size int, value int64) bool { + switch access { + case uc.MEM_WRITE_INVALID: + fmt.Printf("invalid write") + case uc.MEM_READ_INVALID: + fmt.Printf("invalid read") + case uc.MEM_FETCH_INVALID: + fmt.Printf("invalid fetch") + default: + fmt.Printf("unknown memory error") + } + fmt.Printf(": @0x%x, 0x%x = 0x%x\n", addr, size, value) + return false + }) + mu.HookAdd(uc.HOOK_INSN, func(mu uc.Unicorn) { + rax, _ := mu.RegRead(uc.X86_REG_RAX) + fmt.Printf("Syscall: %d\n", rax) + }, uc.X86_INS_SYSCALL) +} + +func run() error { + code, err := hex.DecodeString(asm) + if err != nil { + return err + } + // set up unicorn instance and add hooks + mu, err := uc.NewUnicorn(uc.ARCH_X86, uc.MODE_64) + if err != nil { + return err + } + addHooks(mu) + // map and write code to memory + if err := mu.MemMap(0x1000, 0x1000); err != nil { + return err + } + if err := mu.MemWrite(0x1000, code); err != nil { + return err + } + // map scratch space + if err := mu.MemMap(0x4000, 0x1000); err != nil { + return err + } + // set example register + if err := mu.RegWrite(uc.X86_REG_RDX, 1); err != nil { + return err + } + rdx, err := mu.RegRead(uc.X86_REG_RDX) + if err != nil { + return err + } + fmt.Printf("RDX is: %d\n", rdx) + + // start emulation + if err := mu.Start(0x1000, 0x1000+uint64(len(code))); err != nil { + return err + } + + // read back example register + rdx, err = mu.RegRead(uc.X86_REG_RDX) + if err != nil { + return err + } + fmt.Printf("RDX is now: %d\n", rdx) + return nil +} + +func main() { + if err := run(); err != nil { + fmt.Println(err) + } +}