예제 #1
0
func NewUsercorn(exe string, prefix string) (*Usercorn, error) {
	l, err := loader.LoadFile(exe)
	if err != nil {
		return nil, err
	}
	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
	}
	exe, _ = filepath.Abs(exe)
	u := &Usercorn{
		Unicorn:       unicorn,
		exe:           exe,
		loader:        l,
		LoadPrefix:    prefix,
		traceMatching: true,
	}
	// load kernels
	// the array cast is a trick to work around circular imports
	if os.Kernels != nil {
		kernelI := os.Kernels(u)
		kernels := make([]common.Kernel, len(kernelI))
		for i, k := range kernelI {
			kernels[i] = k.(common.Kernel)
		}
		u.kernels = kernels
	}
	// map binary (and interp) into memory
	u.status = models.StatusDiff{U: u, Color: true}
	u.interpBase, u.entry, u.base, u.binEntry, err = u.mapBinary(u.loader, false)
	if err != nil {
		return nil, err
	}
	// find data segment for brk
	segments, err := l.Segments()
	if err != nil {
		return nil, err
	}
	for _, seg := range segments {
		if seg.Prot&uc.PROT_WRITE != 0 {
			addr := u.base + seg.Addr + seg.Size
			if addr > u.brk {
				u.brk = addr
			}
		}
	}
	// TODO: have a "host page size", maybe arch.Align()
	mask := uint64(4096 - 1)
	u.Brk((u.brk + mask) & ^mask)
	return u, nil
}
예제 #2
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
}