Beispiel #1
0
)

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
	},
})
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}