Example #1
0
func NewUsercornRaw(l models.Loader, config *models.Config) (*Usercorn, error) {
	config = config.Init()
	a, OS, err := arch.GetArch(l.Arch(), l.OS())
	if err != nil {
		return nil, err
	}
	unicorn, err := NewUnicorn(a, OS, l.ByteOrder())
	if err != nil {
		return nil, err
	}
	u := &Usercorn{
		Unicorn:       unicorn,
		traceMatching: true,
		config:        config,
		loader:        l,
		exit:          0xffffffffffffffff,
	}
	if config.Output == os.Stderr && readline.IsTerminal(int(os.Stderr.Fd())) {
		config.Color = true
	}
	u.memio = memio.NewMemIO(
		// ReadAt() callback
		func(p []byte, addr uint64) (int, error) {
			if err := u.MemReadInto(p, addr); err != nil {
				return 0, err
			}
			if u.config.TraceMemBatch {
				u.memlog.UpdateBytes(addr, p, false)
			}
			return len(p), nil
		},
		// WriteAt() callback
		func(p []byte, addr uint64) (int, error) {
			if err := u.MemWrite(addr, p); err != nil {
				return 0, err
			}
			if u.config.TraceMemBatch {
				u.memlog.UpdateBytes(addr, p, true)
			}
			return len(p), nil
		},
	)
	// load kernels
	// the array cast is a trick to work around circular imports
	if OS.Kernels != nil {
		kernelI := OS.Kernels(u)
		kernels := make([]co.Kernel, len(kernelI))
		for i, k := range kernelI {
			kernels[i] = k.(co.Kernel)
		}
		u.kernels = kernels
	}
	u.status = models.StatusDiff{U: u}
	if u.config.LoopCollapse > 0 {
		u.blockloop = models.NewLoopDetect(u.config.LoopCollapse)
	}
	// TODO: if we error, should close Usercorn/Unicorn instance?
	// GC might take its time
	if err := u.mapStack(); err != nil {
		return nil, err
	}
	if err := u.addHooks(); err != nil {
		return nil, err
	}
	return u, nil
}
Example #2
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
}