) var MapsCmd = cmd(&Command{ Name: "maps", Desc: "Display memory mappings.", // TODO: once we have command overloading, merge this with mem command Run: func(c *Context) error { for _, m := range c.U.Mappings() { c.Printf(" %v\n", m.String()) } return nil }, }) var MemCmd = cmd(&Command{ Name: "mem", Desc: "Read/write memory.", // TODO: need overloading so we can keep arg safety // at that point optional args might as well be an overloaded form Run: func(c *Context, addr, size uint64) error { mem, err := c.U.MemRead(addr, size) if err != nil { return err } for _, line := range models.HexDump(addr, mem, int(c.U.Bits())) { c.Printf(" %s\n", line) } return nil }, })
func handleCmd(c *cmd.UsercornCmd, line string) bool { u := c.Usercorn args := strings.Split(line, " ") switch args[0][1:] { case "help": fmt.Println(helpTxt) case "alloc": if len(args) != 2 { fmt.Println(helpTxt) } else { mem, err := u.Mmap(0, parseAddr(u, args[1])) if err != nil { fmt.Println(err) } else { fmt.Printf(" = 0x%x\n", mem.Addr) } } case "read": if len(args) < 2 { fmt.Println(helpTxt) } else { addr := parseAddr(u, args[1]) size := uint64(64) if len(args) > 2 { size = parseAddr(u, args[2]) } mem, err := u.MemRead(addr, size) if err != nil { fmt.Println(err) break } for _, line := range models.HexDump(addr, mem, int(u.Bits())) { fmt.Printf(" %s\n", line) } } case "write": if len(args) < 3 { fmt.Println(helpTxt) } else { addr := parseAddr(u, args[1]) rest := strings.Join(args[2:], " ") rest, err := strconv.Unquote("\"" + rest + "\"") if err != nil { fmt.Println(err) break } err = u.MemWrite(addr, []byte(rest)) if err != nil { fmt.Println(err) break } } case "regs": status := models.StatusDiff{U: u} fmt.Printf("%s", status.Changes(false).String("", c.Config.Color)) default: return false } return true }
func (u *Usercorn) Run(args []string, env []string) error { // PrefixArgs was added for shebang if len(u.config.PrefixArgs) > 0 { args = append(u.config.PrefixArgs, args...) } if u.os.Init != nil && !u.stackinit { u.stackinit = true if err := u.os.Init(u, args, env); err != nil { return err } } if u.config.Verbose { u.Printf("[entry @ 0x%x]\n", u.entry) dis, err := u.Disas(u.entry, 64) if err != nil { u.Println(err) } else { u.Println(dis) } sp, err := u.RegRead(u.arch.SP) if err != nil { return err } buf := make([]byte, u.StackBase+STACK_SIZE-sp) if err := u.MemReadInto(buf, sp); err != nil { return err } u.Printf("[stack @ 0x%x]\n", sp) for _, line := range models.HexDump(sp, buf[:], u.arch.Bits) { u.Println(line) } u.Printf("[memory map]\n") for _, m := range u.Mappings() { u.Printf(" %v\n", m.String()) } } if u.config.Verbose || u.config.TraceReg { u.Printf("%s", u.status.Changes(false).String("", u.config.Color)) } if u.config.Verbose { u.Println("=====================================") u.Println("==== Program output begins here. ====") u.Println("=====================================") } if u.config.TraceBlock || u.config.TraceReg || u.config.TraceExec { sp, _ := u.RegRead(u.arch.SP) u.stacktrace.Update(u.entry, sp) } if u.config.TraceMemBatch { u.memlog = *models.NewMemLog(u.ByteOrder()) } if u.config.SavePre != "" { u.RegWrite(u.arch.PC, u.entry) if err := u.save(u.config.SavePre); err != nil { u.Printf("failed to save pre-state: %s\n", err) os.Exit(1) } os.Exit(0) } // handle savestate even under panic if u.config.SavePost != "" { defer func() { if err := u.save(u.config.SavePost); err != nil { u.Printf("failed to save post-state: %s\n", err) } }() } // panic/exit handler verboseExit := func() { u.Printf("[memory map]\n") for _, m := range u.Mappings() { u.Printf(" %v\n", m.String()) } u.Println("[registers]") u.Printf("%s", u.status.Changes(false).String("", u.config.Color)) u.Println("[stacktrace]") pc, _ := u.RegRead(u.arch.PC) sp, _ := u.RegRead(u.arch.SP) for _, frame := range u.stacktrace.Freeze(pc, sp) { u.Printf(" %s\n", frame.Pretty(u)) } } defer func() { if e := recover(); e != nil { u.Printf("\n+++ panic dump +++\n") verboseExit() u.Printf("------------------\n\n") panic(e) } }() // loop to restart Unicorn if we need to call a trampoline function pc := u.entry var err error for err == nil { // well there's a huge pile of sync here to make sure everyone's ready to go... u.gate.Start() err = u.Start(pc, u.exit) u.gate.Stop() u.Printf("%s", u.memlog.Flush("", u.arch.Bits)) if err != nil || len(u.trampolines) == 0 { break } pc, _ = u.RegRead(u.arch.PC) sp, _ := u.RegRead(u.arch.SP) trampolines := u.trampolines u.trampolines = nil // TODO: trampolines should be annotated in trace // trampolines should show up during symbolication? u.trampolined = true for _, tramp := range trampolines { if err = tramp.fun(); err != nil { break } } u.trampolined = false u.RegWrite(u.arch.PC, pc) u.RegWrite(u.arch.SP, sp) } if err != nil || u.config.Verbose { verboseExit() } else if u.config.TraceReg { u.Printf("\n%s", u.status.Changes(false).String("", u.config.Color)) } if err == nil && u.exitStatus != nil { err = u.exitStatus } return err }
func (u *Usercorn) Run(args []string, env []string) error { if u.LoopCollapse > 0 { u.blockloop = models.NewLoopDetect(u.LoopCollapse) } if err := u.addHooks(); err != nil { return err } if err := u.setupStack(); err != nil { return err } if u.os.Init != nil { if err := u.os.Init(u, args, env); err != nil { return err } } if u.Verbose { fmt.Fprintf(os.Stderr, "[entry @ 0x%x]\n", u.entry) dis, err := u.Disas(u.entry, 64) if err != nil { fmt.Fprintln(os.Stderr, err) } else { fmt.Fprintln(os.Stderr, dis) } sp, err := u.RegRead(u.arch.SP) if err != nil { return err } buf := make([]byte, u.StackBase+STACK_SIZE-sp) if err := u.MemReadInto(buf, sp); err != nil { return err } fmt.Fprintf(os.Stderr, "[stack @ 0x%x]\n", sp) for _, line := range models.HexDump(sp, buf[:], u.arch.Bits) { fmt.Fprintf(os.Stderr, "%s\n", line) } } if u.Verbose || u.TraceReg { u.status.Changes().Print("", true, false) } if u.Verbose { fmt.Fprintln(os.Stderr, "=====================================") fmt.Fprintln(os.Stderr, "==== Program output begins here. ====") fmt.Fprintln(os.Stderr, "=====================================") } if u.TraceReg || u.TraceExec { sp, _ := u.RegRead(u.arch.SP) sym, _ := u.Symbolicate(u.entry) u.stacktrace.Update(u.entry, sp, sym) } if u.TraceMemBatch { u.memlog = *models.NewMemLog(u.ByteOrder()) } err := u.Unicorn.Start(u.entry, 0xffffffffffffffff) if u.TraceMemBatch && !u.memlog.Empty() { u.memlog.Print("", u.arch.Bits) u.memlog.Reset() } if err != nil { fmt.Fprintln(os.Stderr, "Registers:") u.status.Changes().Print("", true, false) fmt.Fprintln(os.Stderr, "Stacktrace:") u.stacktrace.Print(u) } if err == nil && u.exitStatus != nil { err = u.exitStatus } return err }