def parseFile(vw, filename, baseaddr=None): arch = vw.config.viv.parsers.ihex.arch if not arch: raise Exception('IHex loader *requires* arch option (-O viv.parsers.ihex.arch=\\"<archname>\\")') envi.getArchModule(arch) vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'Unknown') vw.setMeta('Format', 'ihex') vw.setMeta('DefaultCall', archcalls.get(arch, 'unknown')) # might we make use of baseaddr, even though it's an IHEX? for now, no. fname = vw.addFile(filename, 0, v_parsers.md5File(filename)) vw.setFileMeta(filename, 'sha256', v_parsers.sha256File(filename)) ihex = v_ihex.IHexFile() with open(filename, 'rb') as f: ihex.vsParse(f.read()) for addr, perms, notused, bytes in ihex.getMemoryMaps(): vw.addMemoryMap(addr, perms, fname, bytes) vw.addSegment(addr, len(bytes), '%.8x' % addr, fname)
def parseFile(vw, filename, baseaddr=None): arch = vw.config.viv.parsers.blob.arch bigend = vw.config.viv.parsers.blob.bigend if baseaddr is None: baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception: raise v_exc.BlobArchException() vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'unknown') vw.setMeta('Format', 'blob') vw.setMeta('bigend', bigend) vw.setMeta('DefaultCall', archcalls.get(arch, 'unknown')) with open(filename, 'rb') as f: bytez = f.read() fname = vw.addFile(filename, baseaddr, v_parsers.md5File(filename)) vw.setFileMeta(fname, 'sha256', v_parsers.sha256Bytes(bytez)) vw.addMemoryMap(baseaddr, 7, filename, bytez) vw.addSegment(baseaddr, len(bytez), '%.8x' % baseaddr, 'blob')
def parseFd(vw, fd, filename=None): fd.seek(0) arch = vw.config.viv.parsers.blob.arch baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception, e: raise Exception('Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")')
def parseFd(vw, fd, filename=None): fd.seek(0) arch = vw.config.viv.parsers.blob.arch bigend = vw.config.viv.parsers.blob.bigend baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception, e: raise Exception('Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")')
def parseFile(vw, filename): arch = vw.config.viv.parsers.blob.arch bigend = vw.config.viv.parsers.blob.bigend baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception, e: raise Exception('Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")')
def parseFile(vw, filename): arch = vw.config.viv.parsers.blob.arch baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception, e: raise Exception( 'Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")' )
def parseFile(vw, filename, baseaddr=None): arch = vw.config.viv.parsers.srec.arch if not arch: raise Exception( 'SRec loader *requires* arch option (-O viv.parsers.srec.arch=\\"<archname>\\")' ) envi.getArchModule(arch) vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'Unknown') vw.setMeta('Format', 'srec') vw.setMeta('DefaultCall', archcalls.get(arch, 'unknown')) offset = vw.config.viv.parsers.srec.offset if not offset: offset = 0 vw.config.viv.parsers.srec.offset = 0 srec = v_srec.SRecFile() with open(filename, 'rb') as f: shdr = f.read(offset) sbytes = f.read() if offset: logger.debug('skipping %d bytes: %r', offset, repr(shdr)[:300]) fname = vw.addFile(filename, 0, v_parsers.md5Bytes(shdr + sbytes)) vw.setFileMeta(fname, 'sha256', v_parsers.sha256Bytes(shdr + sbytes)) srec.vsParse(sbytes) # calculate SREC-specific hash - only the fields copied into memory srdata = srec.vsEmit() vw.setFileMeta(fname, 'sha256_srec', v_parsers.sha256Bytes(srdata.encode('utf-8'))) for eva in srec.getEntryPoints(): if eva is not None: vw.addExport(eva, EXP_FUNCTION, '__entry', fname, makeuniq=True) logger.info( 'adding function from SREC metadata: 0x%x (_entry)', eva) vw.addEntryPoint(eva) for addr, perms, notused, bytes in srec.getMemoryMaps(): vw.addMemoryMap(addr, perms, fname, bytes) vw.addSegment(addr, len(bytes), '%.8x' % addr, fname)
def __init__(self, trace): self.trace = trace self.archname = trace.getMeta('Architecture') self.arch = envi.getArchModule(self.archname) self.emu = self.arch.getEmulator() self.memcache = e_mem.MemoryCache(self.trace) plat = trace.getMeta('Platform') # gotta setup fs at least... if plat == 'windows' and self.archname in ('i386', 'amd64'): # so 32 and 64 bit are flipped. In x86-land FS:[0] points to the TIB. On x64, it's GS:[0] that points to the # TEB tid = trace.getCurrentThread() tinfo = trace.getThreads().get(tid) if self.archname == 'i386': self.emu.setSegmentInfo(e_i386.SEG_FS, tinfo, 0xffffffff) elif self.archname == 'amd64': self.emu.setSegmentInfo(e_i386.SEG_GS, tinfo, 0xffffffff) # Monkey patch the emulator's read methods self.emu.readMemory = self.memcache.readMemory self.emu.writeMemory = self.memcache.writeMemory self.emu.getMemoryMap = self.memcache.getMemoryMap self.emu.getMemoryMaps = self.memcache.getMemoryMaps self.emu.parseOpcode = parseOpcode.__get__(self.emu) regctx = trace.getRegisterContext() self.emu.setRegisterSnap(regctx.getRegisterSnap())
def __init__(self, trace): self.trace = trace self.archname = trace.getMeta('Architecture') self.arch = envi.getArchModule(self.archname) self.emu = self.arch.getEmulator() self.memcache = e_mem.MemoryCache(self.trace) plat = trace.getMeta('Platform') # gotta setup fs at least... if plat == 'windows' and self.archname in ('i386','amd64'): tid = trace.getCurrentThread() tinfo = trace.getThreads().get(tid) self.emu.setSegmentInfo(e_i386.SEG_FS, tinfo, 0xffffffff) # Monkey patch the emulator's read methods self.emu.readMemory = self.memcache.readMemory self.emu.writeMemory = self.memcache.writeMemory self.emu.getMemoryMap = self.memcache.getMemoryMap self.emu.getMemoryMaps = self.memcache.getMemoryMaps regctx = trace.getRegisterContext() self.emu.setRegisterSnap( regctx.getRegisterSnap() )
def emuFromTrace(trace): ''' Produce an envi emulator for this tracer object. ''' arch = trace.getMeta('Architecture') amod = envi.getArchModule(arch) emu = amod.getEmulator() # could use {get,set}MemorySnap if trace inherited from MemoryObject for va, size, perms, fname in trace.getMemoryMaps(): try: bytez = trace.readMemory(va, size) emu.addMemoryMap(va, perms, fname, bytez) except vtrace.PlatformException: print('failed to map: 0x{:x} into emu'.format(va, size)) continue rsnap = trace.getRegisterContext().getRegisterSnap() emu.setRegisterSnap(rsnap) if trace.getMeta('Platform') == 'windows': emu.setSegmentInfo(e_i386.SEG_FS, trace.getThreads()[trace.getMeta('ThreadId')], 0xffffffff) return emu
def __init__(self, trace=None): v_notif.Notifier.__init__(self) v_util.TraceManager.__init__(self) if trace == None: trace = vtrace.getTrace() arch = trace.getMeta("Architecture") self.arch = envi.getArchModule(arch) self.difftracks = {} self.setMode("NonBlocking", True) self.manageTrace(trace) self.registerNotifier(vtrace.NOTIFY_ALL, self) # FIXME if config verbose #self.registerNotifier(vtrace.NOTIFY_ALL, vtrace.VerboseNotifier()) self.vdbhome = e_config.gethomedir(".vdb") self.loadConfig() self.setupSignalLookups() # Ok... from here down we're handing everybody the crazy # on-demand-resolved trace object. trace = vdb.VdbTrace(self) e_cli.EnviMutableCli.__init__(self, trace, self.config, symobj=trace) self.prompt = "vdb > " self.banner = "Welcome To VDB!\n" self.loadDefaultRenderers(trace) self.loadExtensions(trace)
def _mcb_Architecture(self, name, value): # This is for legacy stuff... self.arch = envi.getArchModule(value) self.psize = self.arch.getPointerSize() archid = envi.getArchByName(value) self.setMemArchitecture(archid)
def emuFromTrace(trace): ''' Produce an envi emulator for this tracer object. ''' arch = trace.getMeta('Architecture') plat = trace.getMeta('Platform') amod = envi.getArchModule(arch) emu = amod.getEmulator() # could use {get,set}MemorySnap if trace inherited from MemoryObject for va, size, perms, fname in trace.getMemoryMaps(): try: # So linux maps in a PROT_NONE page for efficient library sharing, so we have to take that into account if (not perms & e_memory.MM_READ): continue if plat == 'linux' and fname in ['[vvar]']: continue bytez = trace.readMemory(va, size) emu.addMemoryMap(va, perms, fname, bytez) except vtrace.PlatformException: print('failed to map: 0x{:x} into emu'.format(va, size)) continue rsnap = trace.getRegisterContext().getRegisterSnap() emu.setRegisterSnap(rsnap) if plat == 'windows': emu.setSegmentInfo(e_i386.SEG_FS, trace.getThreads()[trace.getMeta('ThreadId')], 0xffffffff) return emu
def __init__(self, trace): self.trace = trace self.archname = trace.getMeta('Architecture') self.arch = envi.getArchModule(self.archname) self.emu = self.arch.getEmulator() self.memcache = e_mem.MemoryCache(self.trace) plat = trace.getMeta('Platform') # gotta setup fs at least... if plat == 'windows' and self.archname in ('i386', 'amd64'): tid = trace.getCurrentThread() tinfo = trace.getThreads().get(tid) self.emu.setSegmentInfo(e_i386.SEG_FS, tinfo, 0xffffffff) # Monkey patch the emulator's read methods self.emu.readMemory = self.memcache.readMemory self.emu.writeMemory = self.memcache.writeMemory self.emu.getMemoryMap = self.memcache.getMemoryMap self.emu.getMemoryMaps = self.memcache.getMemoryMaps regctx = trace.getRegisterContext() self.emu.setRegisterSnap(regctx.getRegisterSnap())
def test_x86_OperAddrs(self): arch32 = envi.getArchModule('i386') emu32 = arch32.getEmulator() emu32.setStackCounter(0x7fd0) op = arch32.archParseOpcode(bytes.fromhex('8d8c246894f6c5'), 0, 0) self.assertEqual(op.opers[1].getOperAddr(op, emu32), 0xc5f71438) import envi.archs.i386.disasm as eaid oper = eaid.i386SibOper(tsize=4, reg=eaid.REG_ESP, index=5, scale=2, disp=-0x98765432) oper._dis_regctx = eaid.i386RegisterContext() addr32 = oper.getOperAddr(op, emu32) self.assertEqual(addr32, 0x678a2b9e) oper = eaid.i386SibOper(tsize=4, imm=256, index=5, scale=2, disp=-0x98765432) oper._dis_regctx = eaid.i386RegisterContext() addr32 = oper.getOperAddr(op, emu32) self.assertEqual(addr32, 0x6789acce) oper = eaid.i386RegMemOper(reg=eaid.REG_ESP, tsize=4, disp=-0x98765432) oper._dis_regctx = eaid.i386RegisterContext() addr32 = oper.getOperAddr(op, emu32) self.assertEqual(addr32, 0x678a2b9e)
def notify(self, event, trace): print "Got event: %d from pid %d, signal: %d" % (event, trace.getPid(), trace.getMeta("PendingSignal")) UnixDebugger.handlingFault.set() buff = "" addr = None # Stacktrace buff += "\nStacktrace:\n" buff += " [ PC ] [ Frame ] [ Location ]\n" for frame in trace.getStackTrace(): buff += " 0x%.8x 0x%.8x %s\n" % (frame[0],frame[1],self.bestName(trace,frame[0])) if addr == None: addr = frame[0] # Registers buff += "\nRegisters:\n" regs = trace.getRegisters() rnames = regs.keys() rnames.sort() for r in rnames: buff += " %s 0x%.8x\n" % (r, regs[r]) # Dissassembly arch = trace.getMeta("Architecture") arch = envi.getArchModule(arch) mem = trace.readMemory(addr-256, 512) addrStart = addr - 256 offset = 0 count = 0 buff += "\nDissassembly:\n" ops = [] while offset < 500 and count < 200: va = addrStart + offset op = arch.makeOpcode(mem[offset:]) if va == addr: for i in ops[-20:]: buff += i buff += ">>>0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va)) count = 190 elif va < addr: ops.append(" 0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va))) else: buff += " 0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va)) offset += len(op) count += 1 print buff UnixDebugger.lock.acquire() UnixDebugger.crashInfo = { 'DebuggerOutput.txt' : buff, 'Bucket' : "AV_at_%d" % addr } UnixDebugger.fault = True UnixDebugger.lock.release() UnixDebugger.handledFault.set()
def __init__(self, archname=None): # For the crazy thread-call-proxy-thing # (must come first for __getattribute__ self.requires_thread = {} self.proxymeth = None # FIXME hack for now... self._released = False # The universal place for all modes # that might be platform dependant... self.modes = {} self.modedocs = {} self.notifiers = {} # For all transient data (if notifiers want # to track stuff per-trace self.metadata = {} self.initMode("RunForever", False, "Run until RunForever = False") self.initMode("NonBlocking", False, "A call to wait() fires a thread to wait *for* you") self.initMode( "ThreadProxy", True, "Proxy necessary requests through a single thread (can deadlock...)" ) self.initMode( "SingleStep", False, "All calls to run() actually just step. This allows RunForever + SingleStep to step forever ;)" ) self.initMode("FastStep", False, "All stepi() will NOT generate a step event") self.regcache = None self.regcachedirty = False self.sus_threads = {} # A dictionary of suspended threads # Set if we're a server and this trace is proxied self.proxy = None # Set us up with an envi arch module # FIXME eventually we should just inherit one... if archname == None: archname = envi.getCurrentArch() arch = envi.getArchByName(archname) self.setMeta('Architecture', archname) self.arch = envi.getArchModule(name=archname) e_resolv.SymbolResolver.__init__(self, width=self.arch.getPointerSize()) e_mem.IMemory.__init__(self, arch=arch) e_reg.RegisterContext.__init__(self) # Add event numbers to here for auto-continue self.auto_continue = [ NOTIFY_LOAD_LIBRARY, NOTIFY_CREATE_THREAD, NOTIFY_UNLOAD_LIBRARY, NOTIFY_EXIT_THREAD, NOTIFY_DEBUG_PRINT ]
def parseFile(vw, filename): arch = vw.config.viv.parsers.ihex.arch if not arch: raise Exception('IHex loader *requires* arch option (-O viv.parsers.ihex.arch=\\"<archname>\\")') envi.getArchModule(arch) vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'Unknown') vw.setMeta('Format', 'ihex') fname = vw.addFile(filename, 0, v_parsers.md5File(filename)) ihex = v_ihex.IHexFile() ihex.vsParse(open(filename, 'rb').read()) for addr, perms, notused, bytes in ihex.getMemoryMaps(): vw.addMemoryMap(addr, perms, fname, bytes) vw.addSegment(addr, len(bytes), '%.8x' % addr, fname)
def parseFd(vw, fd, filename=None): fd.seek(0) arch = vw.config.viv.parsers.blob.arch bigend = vw.config.viv.parsers.blob.bigend baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception as e: raise Exception('Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")') vw.setMeta('Architecture', arch) vw.setMeta('Platform','unknown') vw.setMeta('Format','blob') vw.setMeta('bigend', bigend) bytez = fd.read() vw.addMemoryMap(baseaddr, 7, filename, bytez) vw.addSegment( baseaddr, len(bytez), '%.8x' % baseaddr, 'blob' )
def test_envi_amd64_assorted_instrs(self): global instrs archmod = envi.getArchModule("amd64") for bytez, va, reprOp in instrs: op = archmod.archParseOpcode(bytez.decode('hex'), 0, va) if repr(op).replace(' ','') != reprOp.replace(' ',''): raise Exception("FAILED to decode instr: %.8x %s - should be: %s - is: %s" % \ ( va, bytez, reprOp, repr(op) ) )
def __init__(self, archname=None): # For the crazy thread-call-proxy-thing # (must come first for __getattribute__ self.requires_thread = {} self.proxymeth = None # FIXME hack for now... self._released = False # The universal place for all modes # that might be platform dependant... self.modes = {} self.modedocs = {} self.notifiers = {} # For all transient data (if notifiers want # to track stuff per-trace self.metadata = {} self.initMode("RunForever", False, "Run until RunForever = False") self.initMode("NonBlocking", False, "A call to wait() fires a thread to wait *for* you") self.initMode("ThreadProxy", True, "Proxy necissary requests through a single thread (can deadlock...)") self.initMode("FastBreak", False, "Do *NOT* add/remove breakpoints per-run, but leave them there once active") self.initMode( "SingleStep", False, "All calls to run() actually just step. This allows RunForever + SingleStep to step forever ;)", ) self.initMode("FastStep", False, "All stepi() will NOT generate a step event") self.regcache = None self.regcachedirty = False self.fb_bp_done = False # A little hack for FastBreak mode self.sus_threads = {} # A dictionary of suspended threads # Set if we're a server and this trace is proxied self.proxy = None # Set us up with an envi arch module # FIXME eventually we should just inherit one... if archname == None: archname = envi.getCurrentArch() self.setMeta("Architecture", archname) self.arch = envi.getArchModule(name=archname) e_resolv.SymbolResolver.__init__(self, width=self.arch.getPointerSize()) e_mem.IMemory.__init__(self, archmod=self.arch) e_reg.RegisterContext.__init__(self) # Add event numbers to here for auto-continue self.auto_continue = [ NOTIFY_LOAD_LIBRARY, NOTIFY_CREATE_THREAD, NOTIFY_UNLOAD_LIBRARY, NOTIFY_EXIT_THREAD, NOTIFY_DEBUG_PRINT, ]
def parseFd(vw, fd, filename=None): fd.seek(0) arch = vw.config.viv.parsers.blob.arch bigend = vw.config.viv.parsers.blob.bigend baseaddr = vw.config.viv.parsers.blob.baseaddr try: envi.getArchModule(arch) except Exception as e: raise Exception( 'Blob loader *requires* arch option (-O viv.parsers.blob.arch="<archname>")' ) vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'unknown') vw.setMeta('Format', 'blob') vw.setMeta('bigend', bigend) bytez = fd.read() vw.addMemoryMap(baseaddr, 7, filename, bytez) vw.addSegment(baseaddr, len(bytez), '%.8x' % baseaddr, 'blob')
def parseFile(vw, filename): arch = vw.config.viv.parsers.ihex.arch if not arch: raise Exception( 'IHex loader *requires* arch option (-O viv.parsers.ihex.arch=\\"<archname>\\")' ) envi.getArchModule(arch) vw.setMeta('Architecture', arch) vw.setMeta('Platform', 'Unknown') vw.setMeta('Format', 'ihex') fname = vw.addFile(filename, 0, v_parsers.md5File(filename)) ihex = v_ihex.IHexFile() ihex.vsParse(open(filename, 'rb').read()) for addr, perms, notused, bytes in ihex.getMemoryMaps(): vw.addMemoryMap(addr, perms, fname, bytes) vw.addSegment(addr, len(bytes), '%.8x' % addr, fname)
def _mcb_Architecture(self, name, value): # This is for legacy stuff... self.arch = envi.getArchModule(value) self.psize = self.arch.getPointerSize() archid = envi.getArchByName(value) self.setMemArchitecture(archid) # Default calling convention for architecture # This will be superceded by Platform and Parser settings defcall = self.arch.getArchDefaultCall() if defcall: self.setMeta('DefaultCall', defcall)
def parseFile(vw, filename, baseaddr=None): arch = vw.config.viv.parsers.ihex.arch if not arch: raise Exception('IHex loader *requires* arch option (-O viv.parsers.ihex.arch=\\"<archname>\\")') envi.getArchModule(arch) vw.setMeta('Architecture', arch) vw.setMeta('Platform','Unknown') vw.setMeta('Format','ihex') vw.setMeta('DefaultCall', archcalls.get(arch,'unknown')) # might we make use of baseaddr, even though it's an IHEX? for now, no. fname = vw.addFile(filename, 0, v_parsers.md5File(filename)) ihex = v_ihex.IHexFile() ihex.vsParse( file(filename, 'rb').read() ) for addr, perms, notused, bytes in ihex.getMemoryMaps(): vw.addMemoryMap( addr, perms, fname, bytes ) vw.addSegment( addr, len(bytes), '%.8x' % addr, fname )
def getEmu(trace, arch=envi.ARCH_DEFAULT): ''' See comment for emulator from trace (in envitools); does not set any registers or mem. TODO: this really belongs in envitools, or somewhere else, but putting it in envitools causes a circular import problem due to the TraceEmulator. ''' if arch == envi.ARCH_DEFAULT: arch_name = trace.getMeta('Architecture') else: arch_name = envi.getArchById(trace.arch) arch_mod = envi.getArchModule(arch_name) emu = arch_mod.getEmulator() return emu
def emulatorFromTraceSnapshot(tsnap): """ Produce an envi emulator for this tracer object. Use the trace's arch info to get the emulator so this can be done on the client side of a remote vtrace session. """ arch = tsnap.getMeta("Architecture") amod = envi.getArchModule(arch) emu = amod.getEmulator() if tsnap.getMeta("Platform") == "Windows": emu.setSegmentInfo(e_intel.SEG_FS, tsnap.getThreads()[tsnap.getMeta("ThreadId")], 0xffffffff) emu.setMemoryObject(tsnap) setRegs(emu, tsnap) return emu
def emulatorFromTrace(trace): """ Produce an envi emulator for this tracer object. Use the trace's arch info to get the emulator so this can be done on the client side of a remote vtrace session. """ arch = trace.getMeta("Architecture") amod = envi.getArchModule(arch) emu = amod.getEmulator() if trace.getMeta("Platform") == "Windows": emu.setSegmentInfo(e_i386.SEG_FS, trace.getThreads()[trace.getMeta("ThreadId")], 0xffffffff) emu.setMemoryObject(trace) setRegs(emu, trace) return emu
def test_parsers_rudimentary(self, buf='ABCDEFGHIJKLMNOP', off=3, va=0x2544): val, = struct.unpack_from('>H', buf, off) for tsize in (1, 2, 4): p_i3_Rd(va, val, buf, off, tsize) p_i3_aERd(va, val, buf, off, tsize) p_i3_aAA8(va, val, buf, off, tsize) p_i8_CCR(va, val, buf, off, tsize) p_i8_Rd(va, val, buf, off, tsize) p_i16_Rd(va, val, buf, off, tsize) p_i32_ERd(va, val, buf, off, tsize) p_Rd(va, val, buf, off, tsize) p_Rs_Rd(va, val, buf, off, tsize) p_Rs_Rd_4b(va, val, buf, off, tsize) p_Rs_ERd(va, val, buf, off, tsize) p_Rs_ERd_4b(va, val, buf, off, tsize) p_ERd(va, val, buf, off, tsize) p_ERs_ERd(va, val, buf, off, tsize) p_Rn_Rd(va, val, buf, off, tsize) p_Rn_aERd(va, val, buf, off, tsize) p_Rn_aAA8(va, val, buf, off, tsize) p_aERn(va, val, buf, off, tsize) p_aAA24(va, val, buf, off, tsize) p_aaAA8(va, val, buf, off, tsize) p_disp8(va, val, buf, off, tsize) p_disp16(va, val, buf, off, tsize) p_nooperands(va, val, buf, off, tsize) h8m = envi.getArchModule('h8') for instr in raw_instrs: inst = instr[0].decode('hex') op = h8m.archParseOpcode(inst, 0, 0x50) #print( "%26s %s" % (instr[0].encode('hex'), op) ) if len(op) != len(inst): #raise Exception(" LENGTH FAILURE: expected: %d real: %d '%s'" % (len(inst), len(op), inst.encode('hex'))) #print(" LENGTH FAILURE: expected: %d real: %d '%s'" % (len(inst), len(op), inst.encode('hex'))) raise Exception( " LENGTH FAILURE: %s '%s' expected: %d real: %d '%s'" % (instr[0], op, len(inst), len(op), inst.encode('hex')))
def __init__(self, trace=None): v_notif.Notifier.__init__(self) v_util.TraceManager.__init__(self) if trace == None: trace = vtrace.getTrace() arch = trace.getMeta("Architecture") self.arch = envi.getArchModule(arch) self.difftracks = {} # We hangn on to an opcode renderer instance self.opcoderend = None # If a VdbGui instance is present it will set this. self.gui = None self.setMode("NonBlocking", True) self.manageTrace(trace) self.registerNotifier(vtrace.NOTIFY_ALL, self) # FIXME if config verbose #self.registerNotifier(vtrace.NOTIFY_ALL, vtrace.VerboseNotifier()) self.vdbhome = e_config.gethomedir(".vdb") self.loadConfig() self.setupSignalLookups() # Ok... from here down we're handing everybody the crazy # on-demand-resolved trace object. trace = vdb.VdbTrace(self) e_cli.EnviMutableCli.__init__(self, trace, self.config, symobj=trace) self.prompt = "vdb > " self.banner = "Welcome To VDB!\n" self.loadDefaultRenderers(trace) self.loadExtensions(trace)
def test_parsers_rudimentary(self, buf = 'ABCDEFGHIJKLMNOP', off=3, va=0x2544): val, = struct.unpack_from('>H', buf, off) for tsize in (1,2,4): p_i3_Rd(va, val, buf, off, tsize) p_i3_aERd(va, val, buf, off, tsize) p_i3_aAA8(va, val, buf, off, tsize) p_i8_CCR(va, val, buf, off, tsize) p_i8_Rd(va, val, buf, off, tsize) p_i16_Rd(va, val, buf, off, tsize) p_i32_ERd(va, val, buf, off, tsize) p_Rd(va, val, buf, off, tsize) p_Rs_Rd(va, val, buf, off, tsize) p_Rs_Rd_4b(va, val, buf, off, tsize) p_Rs_ERd(va, val, buf, off, tsize) p_Rs_ERd_4b(va, val, buf, off, tsize) p_ERd(va, val, buf, off, tsize) p_ERs_ERd(va, val, buf, off, tsize) p_Rn_Rd(va, val, buf, off, tsize) p_Rn_aERd(va, val, buf, off, tsize) p_Rn_aAA8(va, val, buf, off, tsize) p_aERn(va, val, buf, off, tsize) p_aAA24(va, val, buf, off, tsize) p_aaAA8(va, val, buf, off, tsize) p_disp8(va, val, buf, off, tsize) p_disp16(va, val, buf, off, tsize) p_nooperands(va, val, buf, off, tsize) h8m = envi.getArchModule('h8') for instr in raw_instrs: inst = instr[0].decode('hex') op = h8m.archParseOpcode(inst, 0, 0x50) #print( "%26s %s" % (instr[0].encode('hex'), op) ) if len(op) != len(inst): #raise Exception(" LENGTH FAILURE: expected: %d real: %d '%s'" % (len(inst), len(op), inst.encode('hex'))) #print(" LENGTH FAILURE: expected: %d real: %d '%s'" % (len(inst), len(op), inst.encode('hex'))) raise Exception(" LENGTH FAILURE: %s '%s' expected: %d real: %d '%s'" % (instr[0], op, len(inst), len(op), inst.encode('hex')))
def test_i386_reps(self): arch32 = envi.getArchModule('i386') emu32 = arch32.getEmulator() emu32.addMemoryMap(0x40000000, 7, 'test', b'foobarbazbane' + b'\0'*100) op_movsd = arch32.archParseOpcode(bytes.fromhex('f3a5'), 0, 0) # rep movsd op_movsb = arch32.archParseOpcode(bytes.fromhex('f3a4'), 0, 0) # rep movsb op_scasb = arch32.archParseOpcode(bytes.fromhex('f2ae'), 0, 0) # repnz scasb op_zscasb = arch32.archParseOpcode(bytes.fromhex('f3ae'), 0, 0) # repz scasb # rep Dword copy desiredoutput1 = b'foobarbazbane\0\0\0foobarbazbane\0\0\0' emu32.setRegisterByName('ecx', 5) emu32.setRegisterByName('esi', 0x40000000) emu32.setRegisterByName('edi', 0x40000010) emu32.executeOpcode(op_movsd) self.assertEqual(emu32.readMemory(0x40000000, 0x20), desiredoutput1) # rep Byte copy desiredoutput2 = b'foobarbazbane\0\0\0foobarbazbane\0\0\0foobarbazbane\0\0\0' emu32.setRegisterByName('ecx', 16) emu32.setRegisterByName('esi', 0x40000000) emu32.setRegisterByName('edi', 0x40000020) emu32.executeOpcode(op_movsb) self.assertEqual(emu32.readMemory(0x40000000, 0x30), desiredoutput2) # repnz Byte scan string emu32.setRegisterByName('eax', 0) emu32.setRegisterByName('ecx', -1) emu32.setRegisterByName('edi', 0x40000000) emu32.executeOpcode(op_scasb) self.assertEqual(emu32.getRegisterByName('ecx'), 0xfffffff1) # repz Byte scan string emu32.setRegisterByName('eax', 0) emu32.setRegisterByName('ecx', -1) emu32.setRegisterByName('edi', 0x4000000d) emu32.executeOpcode(op_zscasb) self.assertEqual(emu32.getRegisterByName('ecx'), 0xfffffffb)
def test_amd64_emulator(self): arch = envi.getArchModule('amd64') self.run_emulator_tests(arch, amd64Tests)
class i386InstructionSet(unittest.TestCase): _arch = envi.getArchModule("i386") def test_envi_i386_disasm_Specific_SingleByte_Instrs(self): ''' pick 10 arbitrary 1-byte-operands ''' vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) for name, bytez, va, reprOp, renderOp in i386SingleByteOpcodes: op = self._arch.archParseOpcode(bytez.decode('hex'), 0, va) # print("'%s', 0x%x, '%s' == '%s'" % (bytez, va, repr(op), reprOp)) self.assertEqual(repr(op), reprOp) scanv.clearCanvas() op.render(scanv) # print("render: %s" % repr(scanv.strval)) self.assertEqual(scanv.strval, renderOp) def test_envi_i386_disasm_Specific_MultiByte_Instrs(self): ''' pick 10 arbitrary 2- and 3-byte operands ''' vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) for name, bytez, va, reprOp, renderOp in i386MultiByteOpcodes: op = self._arch.archParseOpcode(bytez.decode('hex'), 0, va) # print("'%s', 0x%x, '%s' == '%s'" % (bytez, va, repr(op), reprOp)) self.assertEqual(repr(op), reprOp) scanv.clearCanvas() op.render(scanv) # print("render: %s" % repr(scanv.strval)) self.assertEqual(scanv.strval, renderOp) ''' def test_envi_i386_disasm_A(self): pass def test_envi_i386_disasm_C(self): pass def test_envi_i386_disasm_D(self): pass def test_envi_i386_disasm_E(self): pass def test_envi_i386_disasm_F(self): pass def test_envi_i386_disasm_G(self): pass def test_envi_i386_disasm_I(self): pass def test_envi_i386_disasm_J(self): pass def test_envi_i386_disasm_L(self): pass def test_envi_i386_disasm_M(self): pass def test_envi_i386_disasm_N(self): pass def test_envi_i386_disasm_O(self): pass def test_envi_i386_disasm_P(self): pass def test_envi_i386_disasm_Q(self): pass def test_envi_i386_disasm_R(self): pass def test_envi_i386_disasm_S(self): pass def test_envi_i386_disasm_U(self): pass def test_envi_i386_disasm_V(self): pass def test_envi_i386_disasm_W(self): pass def test_envi_i386_disasm_X(self): pass def test_envi_i386_disasm_Y(self): pass ''' def checkOpcode(self, hexbytez, va, oprepr, opcheck, opercheck, renderOp): op = self._arch.archParseOpcode(hexbytez.decode('hex'), 0, va) self.assertEqual( repr(op), oprepr ) opvars = vars(op) for opk,opv in opcheck.items(): # print("op: %s %s" % (opk,opv)) self.assertEqual( (opk, opvars.get(opk)), (opk, opv) ) for oidx in range(len(op.opers)): oper = op.opers[oidx] opervars = vars(oper) for opk,opv in opercheck[oidx].items(): # print("oper: %s %s" % (opk,opv)) self.assertEqual( (opk, opervars.get(opk)), (opk, opv) ) vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) op.render(scanv) #print "render: %s" % repr(scanv.strval) self.assertEqual( scanv.strval, renderOp ) def test_envi_i386_disasm_Reg_Operands(self): ''' test an opcode encoded with an Reg operand _0 add al 04 G add 02 C mov 0f20 D mov 0f21 P punpcklbw 0f60 S mov 8c U movmskps 0f50 V sqrtps 0f51 ''' opbytez = '0032' oprepr = 'add byte [edx],dh' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = [{'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 2}, {'tsize': 1, 'reg': 134742018}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0440' oprepr = 'add al,64' opcheck = {'iflags': 65536, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ( {'tsize': 1, 'reg': 524288}, {'tsize': 1, 'imm': 64} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0218' oprepr = 'add bl,byte [eax]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ( {'tsize': 1, 'reg': 524291}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2018' oprepr = 'mov dword [eax],ctrl3' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 3} opercheck = ( {'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'reg': 35} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_Imm_Operands(self): ''' test an opcode encoded with an Imm operand _0 rol d000 A callf 9a ''' opbytez = 'd000' oprepr = 'rol byte [eax],1' opcheck = {'iflags': 65536, 'va': 16384, 'prefixes': 0, 'mnem': 'rol', 'opcode': 8201, 'size': 2} opercheck = ( {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'imm': 1} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) # this is failing legitimately... we decode this opcode wrong opbytez = '9aaa11aabbcc33' oprepr = 'callf 0x33cc:0xbbaa11aa' opcheck = {'iflags': 65540, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'callf', 'opcode': 4099, 'size': 7} opercheck = [{'tsize': 6, 'imm': 56954414829994}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_PcRel_Operands(self): ''' test an opcode encoded with an PcRelative operand ''' pass def test_envi_i386_disasm_RegMem_Operands(self): ''' test an opcode encoded with an RegMem operand X outsb 6e Y insd 6d ''' opbytez = '6e' oprepr = 'outsb edx,byte [esi]' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'outsb', 'opcode': 57347, 'size': 1} opercheck = [{'tsize': 4, 'reg': 2}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 6}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '6d' oprepr = 'insd dword [esi],edx' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'insd', 'opcode': 57346, 'size': 1} opercheck = [{'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 6}, {'tsize': 4, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_ImmMem_Operands(self): ''' test an opcode encoded with an ImmMem operand O mov a1 ''' opbytez = 'a1a2345678' oprepr = 'mov eax,dword [0x785634a2]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 5} opercheck = [{'tsize': 4, 'reg': 0}, {'tsize': 4, '_is_deref': True, 'imm': 2018915490}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_SIB_Operands(self): ''' exercize the entire SIB operand space A jmp ea E lar 0f02 Q cvttps2pi 0f2c W cvttps2pi 0f2c ''' opbytez = 'eaa123456789ab' # this wants more bytes, why? oprepr = 'jmp 0xab89:0x674523a1' # this repr's wrong. it should be ab89:674523a1 opcheck = {'iflags': 65545, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'jmp', 'opcode': 4097, 'size': 7} opercheck = [{'tsize': 6, 'imm': 188606631453601}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '0f02aabbccddee' oprepr = 'lar ebp,word [edx - 287454021]' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'lar', 'opcode': 57344, 'size': 7} opercheck = [{'tsize': 4, 'reg': 5}, {'disp': -287454021, 'tsize': 2, '_is_deref': True, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2caabbccddeeff' oprepr = 'cvttps2pi mm5,qword [edx - 287454021]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cvttps2pi', 'opcode': 61440} opercheck = [{'tsize': 8, 'reg': 13}, {'disp': -287454021, 'tsize': 8, '_is_deref': True, 'reg': 2}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr)
def test_i386_emulator(self): arch = envi.getArchModule('i386') self.run_emulator_tests(arch, i386Tests)
def __init__(self, trace): a = trace.getMeta("Architecture") self.arch = envi.getArchModule(a) self.pwidth = self.arch.getPointerSize()
class Amd64InstructionSet(unittest.TestCase): _arch = envi.getArchModule("amd64") def test_envi_amd64_disasm_Specific_SingleByte_Instrs(self): ''' pick 10 arbitrary 1-byte-operands ''' vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) for name, bytez, va, reprOp, renderOp in amd64SingleByteOpcodes: op = self._arch.archParseOpcode(bytez.decode('hex'), 0, va) #print "'%s', 0x%x, '%s' == '%s'" % (bytez, va, repr(op), reprOp) self.assertEqual( repr(op), reprOp ) scanv.clearCanvas() op.render(scanv) #print "render: %s" % repr(scanv.strval) self.assertEqual( scanv.strval, renderOp ) def test_envi_amd64_disasm_Specific_MultiByte_Instrs(self): ''' pick 10 arbitrary 2- and 3-byte operands ''' vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) for name, bytez, va, reprOp, renderOp in amd64MultiByteOpcodes: op = self._arch.archParseOpcode(bytez.decode('hex'), 0, va) #print "'%s', 0x%x, '%s' == '%s'" % (bytez, va, repr(op), reprOp) self.assertEqual( repr(op), reprOp ) scanv.clearCanvas() op.render(scanv) #print "render: %s" % repr(scanv.strval) self.assertEqual( scanv.strval, renderOp ) def checkOpcode(self, hexbytez, va, oprepr, opcheck, opercheck, renderOp): op = self._arch.archParseOpcode(hexbytez.decode('hex'), 0, va) self.assertEqual( repr(op), oprepr ) opvars = vars(op) for opk,opv in opcheck.items(): #print "op: %s %s" % (opk,opv) self.assertEqual( (repr(op), opk, opvars.get(opk)), (oprepr, opk, opv) ) for oidx in range(len(op.opers)): oper = op.opers[oidx] opervars = vars(oper) for opk,opv in opercheck[oidx].items(): #print "oper: %s %s" % (opk,opv) self.assertEqual( (repr(op), opk, opervars.get(opk)), (oprepr, opk, opv) ) vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) op.render(scanv) #print "render: %s" % repr(scanv.strval) self.assertEqual( scanv.strval, renderOp ) ############################################### # only pick the operands special to 64-bit mode def test_envi_amd64_disasm_Reg_Operands(self): ''' test an opcode encoded with an Reg operand _0 add al 04 G add 02 C mov 0f20 D mov 0f21 P punpcklbw 0f60 S mov 8c U movmskps 0f50 V sqrtps 0f51 _0 mov REX 41b* ''' opbytez = '0032' oprepr = 'add byte [rdx],dh' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = [{'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 2}, {'tsize': 1, 'reg': 134742018}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '480032' oprepr = 'add byte [rdx],sil' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1572864, 'mnem': 'add', 'opcode': 8193, 'size': 3} opercheck = [{'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 2}, {'tsize': 1, 'reg': 524294}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '480132' oprepr = 'add qword [rdx],rsi' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1572864, 'mnem': 'add', 'opcode': 8193, 'size': 3} opercheck = [{'disp': 0, 'tsize': 8, '_is_deref': True, 'reg': 2}, {'tsize': 8, 'reg': 6}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0440' oprepr = 'add al,64' opcheck = {'iflags': 131072, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ( {'tsize': 4, 'reg': 524288}, {'tsize': 4, 'imm': 64} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0218' oprepr = 'add bl,byte [rax]' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ( {'tsize': 1, 'reg': 524291}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2018' oprepr = 'mov dword [rax],ctrl3' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 3} opercheck = ( {'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'reg': 59} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) for x in range(0xb0, 0xb8): bytez = '41%.2xAAAAAAAA' % x op = self._arch.archParseOpcode((bytez).decode('hex'),0,0x1000) self.assertEqual( (bytez, hex(op.opers[0].reg)), (bytez, hex( 0x80000 + (x-0xa8) )) ) for x in range(0xb8, 0xc0): bytez = '41%.2xAAAAAAAA' % x op = self._arch.archParseOpcode((bytez).decode('hex'),0,0x1000) self.assertEqual( (bytez, hex(op.opers[0].reg)), (bytez, hex( 0x200000 + (x-0xb0) )) ) def test_envi_amd64_disasm_Imm_Operands(self): ''' test an opcode encoded with an Imm operand _0 rol d000 A callf 9a ''' opbytez = 'd000' oprepr = 'rol byte [rax],1' opcheck = {'iflags': 131072, 'va': 16384, 'prefixes': 0, 'mnem': 'rol', 'opcode': 8201, 'size': 2} opercheck = ( {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'imm': 1} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) # this is failing legitimately... we decode this opcode wrong opbytez = '9aaa11aabbcc33' oprepr = 'callf 0x33cc:0xbbaa11aa' opcheck = {'iflags': 131076, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'callf', 'opcode': 4099, 'size': 7} opercheck = [{'tsize': 6, 'imm': 56954414829994}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [3]: generateTestInfo('413ac4') opbytez = '413ac4' oprepr = 'cmp al,r12l' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1114112, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 524300}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [4]: generateTestInfo('453ac4') opbytez = '453ac4' oprepr = 'cmp r8l,r12l' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1376256, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524296}, {'tsize': 1, 'reg': 524300}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [5]: generateTestInfo('473ac4') opbytez = '473ac4' oprepr = 'cmp r8l,r12l' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1507328, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524296}, {'tsize': 1, 'reg': 524300}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [3]: generateTestInfo('3ac4') opbytez = '3ac4' oprepr = 'cmp al,ah' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cmp', 'opcode': 20482, 'size': 2} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 134742016}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [4]: generateTestInfo('403ac4') opbytez = '403ac4' oprepr = 'cmp al,spl' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1048576, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 524292}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [5]: generateTestInfo('663ac4') opbytez = '663ac4' oprepr = 'cmp al,ah' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 64, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 134742016}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [6]: generateTestInfo('673ac4') opbytez = '673ac4' oprepr = 'cmp al,ah' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 128, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 134742016}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [7]: generateTestInfo('663ac4') opbytez = '663ac4' oprepr = 'cmp al,ah' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 64, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 1, 'reg': 524288}, {'tsize': 1, 'reg': 134742016}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [9]: generateTestInfo('663bc4') opbytez = '663bc4' oprepr = 'cmp ax,sp' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 64, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 2, 'reg': 1048576}, {'tsize': 2, 'reg': 1048580}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [10]: generateTestInfo('3bc4') opbytez = '3bc4' oprepr = 'cmp eax,esp' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cmp', 'opcode': 20482, 'size': 2} opercheck = [{'tsize': 4, 'reg': 2097152}, {'tsize': 4, 'reg': 2097156}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [11]: generateTestInfo('403bc4') opbytez = '403bc4' oprepr = 'cmp eax,esp' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1048576, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 4, 'reg': 2097152}, {'tsize': 4, 'reg': 2097156}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [12]: generateTestInfo('413bc4') opbytez = '413bc4' oprepr = 'cmp eax,r12d' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1114112, 'mnem': 'cmp', 'opcode': 20482, 'size': 3} opercheck = [{'tsize': 4, 'reg': 2097152}, {'tsize': 4, 'reg': 2097164}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) #In [13]: generateTestInfo('66413bc4') opbytez = '66413bc4' oprepr = 'cmp ax,r12w' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1114176, 'mnem': 'cmp', 'opcode': 20482, 'size': 4} opercheck = [{'tsize': 2, 'reg': 1048576}, {'tsize': 2, 'reg': 1048588}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_amd64_disasm_PcRel_Operands(self): ''' test an opcode encoded with an PcRelative operand ''' pass def test_envi_amd64_disasm_RegMem_Operands(self): ''' test an opcode encoded with an RegMem operand X outsb 6e Y insd 6d ''' opbytez = '6e' oprepr = 'outsb dx,byte [rsi]' opcheck = {'iflags': 131074, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'outsb', 'opcode': 57347, 'size': 1} opercheck = [{'tsize': 4, 'reg': 1048578}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 6}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '6d' oprepr = 'insd dword [rsi],dx' opcheck = {'iflags': 131074, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'insd', 'opcode': 57346, 'size': 1} opercheck = [{'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 6}, {'tsize': 4, 'reg': 1048578}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_amd64_disasm_ImmMem_Operands(self): ''' test an opcode encoded with an ImmMem operand O mov a1 ''' opbytez = 'a1a2345678aabbccdd' oprepr = 'mov eax,dword [0xddccbbaa785634a2]' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 9} opercheck = [{'tsize': 4, 'reg': 2097152}, {'tsize': 4, '_is_deref': True, 'imm': 15982355518468797602L}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_amd64_disasm_SIB_Operands(self): ''' exercize the entire SIB operand space A jmp fa E lar 0f02 Q cvttps2pi 0f2c W cvttps2pi 0f2c with REX: mov qword [rsp + r12 * 8 + 32],rdi 4a897ce420 ''' opbytez = 'eaa123456789ab' # this wants more bytes, why? oprepr = 'jmp 0xab89:0x674523a1' # this repr's wrong. it should be ab89:674523a1 opcheck = {'iflags': 131081, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'jmp', 'opcode': 4097, 'size': 7} opercheck = [{'tsize': 6, 'imm': 188606631453601}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f02aabbccddee' oprepr = 'lar ebp,word [rdx - 287454021]' opcheck = {'iflags': 131074, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'lar', 'opcode': 57344, 'size': 7} opercheck = [{'tsize': 4, 'reg': 2097157}, {'disp': -287454021, 'tsize': 2, '_is_deref': True, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2caabbccddeeff' oprepr = 'cvttps2pi mm5,oword [rdx - 287454021]' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cvttps2pi', 'opcode': 61440, 'size': 7} opercheck = [{'tsize': 8, 'reg': 21}, {'disp': -287454021, 'tsize': 16, '_is_deref': True, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '3b80ABCDEF12' oprepr = 'cmp eax,dword [rax + 317705643]' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cmp', 'opcode': 20482, 'size': 6} opercheck = [{'tsize': 4, 'reg': 2097152}, {'disp': 317705643, 'tsize': 4, '_is_deref': True, 'reg': 0}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '4a897ce420' oprepr = 'mov qword [rsp + r12 * 8 + 32],rdi' opcheck = {'iflags': 131072, 'va': 16384, 'repr': None, 'prefixes': 1703936, 'mnem': 'mov', 'opcode': 24577, 'size': 5} opercheck = [{'disp': 32, 'index': 12, 'tsize': 8, 'scale': 8, 'imm': None, '_is_deref': True, 'reg': 4}, {'tsize': 8, 'reg': 7}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr )
class i386InstructionSet(unittest.TestCase): _arch = envi.getArchModule("i386") def check_opreprs(self, opcodes): vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) for name, bytez, va, reprOp, renderOp in opcodes: try: op = self._arch.archParseOpcode(binascii.unhexlify(bytez), 0, va) except envi.InvalidInstruction: self.fail("Failed to parse opcode bytes: %s (case: %s, expected: %s)" % (bytez, name, reprOp)) except Exception: self.fail("Failed to parse opcode bytes: %s (case: %s, expected: %s)" % (bytez, name, reprOp)) msg = '%s failed length check. Got %d, expected %d' % (name, len(op), int(len(bytez)/2)) self.assertEqual(len(op), int(len(bytez)/2), msg=msg) # print("'%s', 0x%x, '%s' == '%s'" % (bytez, va, repr(op), reprOp)) try: self.assertEqual(repr(op), reprOp) except AssertionError: self.fail("Failing match for case %s (%s != %s)" % (name, repr(op), reprOp)) scanv.clearCanvas() op.render(scanv) self.assertEqual(scanv.strval, renderOp) def test_envi_i386_disasm_Specific_SingleByte_Instrs(self): self.check_opreprs(i386SingleByteOpcodes) def test_envi_i386_disasm_Specific_MultiByte_Instrs(self): self.check_opreprs(i386MultiByteOpcodes) def checkOpcode(self, hexbytez, va, oprepr, opcheck, opercheck, renderOp): op = self._arch.archParseOpcode(binascii.unhexlify(hexbytez), 0, va) self.assertEqual(repr(op), oprepr) opvars = vars(op) for opk, opv in opcheck.items(): self.assertEqual((opk, opvars.get(opk)), (opk, opv)) for oidx in range(len(op.opers)): oper = op.opers[oidx] opervars = vars(oper) for opk, opv in opercheck[oidx].items(): self.assertEqual((opk, opervars.get(opk)), (opk, opv)) vw = vivisect.VivWorkspace() scanv = e_memcanvas.StringMemoryCanvas(vw) op.render(scanv) self.assertEqual(scanv.strval, renderOp) def test_envi_i386_disasm_Reg_Operands(self): ''' test an opcode encoded with an Reg operand _0 add al 04 G add 02 C mov 0f20 D mov 0f21 P punpcklbw 0f60 S mov 8c U movmskps 0f50 V sqrtps 0f51 ''' opbytez = '0032' oprepr = 'add byte [edx],dh' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ({'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 2}, {'tsize': 1, 'reg': 134742018},) self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '0440' oprepr = 'add al,64' opcheck = {'iflags': 65536, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ({'tsize': 1, 'reg': 524288}, {'tsize': 1, 'imm': 64}) self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '0218' oprepr = 'add bl,byte [eax]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'add', 'opcode': 8193, 'size': 2} opercheck = ( {'tsize': 1, 'reg': 524291}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2018' oprepr = 'mov dword [eax],ctrl3' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 3} opercheck = ( {'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'reg': 27} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_Imm_Operands(self): ''' test an opcode encoded with an Imm operand _0 rol d000 A callf 9a ''' opbytez = 'd000' oprepr = 'rol byte [eax],1' opcheck = {'iflags': 65536, 'va': 16384, 'prefixes': 0, 'mnem': 'rol', 'opcode': 8201, 'size': 2} opercheck = ( {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 0}, {'tsize': 4, 'imm': 1} ) self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) # this is failing legitimately... we decode this opcode wrong opbytez = '9aaa11aabbcc33' oprepr = 'callf 0x33cc:0xbbaa11aa' opcheck = {'iflags': 65540, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'callf', 'opcode': 4099, 'size': 7} opercheck = [{'tsize': 6, 'imm': 56954414829994}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_PcRel_Operands(self): ''' test an opcode encoded with an PcRelative operand ''' pass def test_envi_i386_disasm_RegMem_Operands(self): ''' test an opcode encoded with an RegMem operand X outsb 6e Y insd 6d ''' opbytez = '6e' oprepr = 'outsb edx,byte [esi]' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'outsb', 'opcode': 57347, 'size': 1} opercheck = [{'tsize': 4, 'reg': 2}, {'disp': 0, 'tsize': 1, '_is_deref': True, 'reg': 6}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '6d' oprepr = 'insd dword [esi],edx' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'insd', 'opcode': 57346, 'size': 1} opercheck = [{'disp': 0, 'tsize': 4, '_is_deref': True, 'reg': 6}, {'tsize': 4, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_ImmMem_Operands(self): ''' test an opcode encoded with an ImmMem operand O mov a1 ''' opbytez = 'a1a2345678' oprepr = 'mov eax,dword [0x785634a2]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'mov', 'opcode': 24577, 'size': 5} opercheck = [{'tsize': 4, 'reg': 0}, {'tsize': 4, '_is_deref': True, 'imm': 2018915490}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) def test_envi_i386_disasm_SIB_Operands(self): ''' exercize the entire SIB operand space A jmp ea E lar 0f02 Q cvttps2pi 0f2c W cvttps2pi 0f2c ''' opbytez = 'eaa123456789ab' # this wants more bytes, why? oprepr = 'jmp 0xab89:0x674523a1' # this repr's wrong. it should be ab89:674523a1 opcheck = {'iflags': 65545, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'jmp', 'opcode': 4097, 'size': 7} opercheck = [{'tsize': 6, 'imm': 188606631453601}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr) opbytez = '0f02aabbccddee' oprepr = 'lar ebp,word [edx - 287454021]' opcheck = {'iflags': 65538, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'lar', 'opcode': 57344, 'size': 7} opercheck = [{'tsize': 4, 'reg': 5}, {'disp': -287454021, 'tsize': 2, '_is_deref': True, 'reg': 2}] self.checkOpcode( opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr ) opbytez = '0f2caabbccddeeff' oprepr = 'cvttps2pi mm5,qword [edx - 287454021]' opcheck = {'iflags': 65536, 'va': 16384, 'repr': None, 'prefixes': 0, 'mnem': 'cvttps2pi', 'opcode': 61440} opercheck = [{'tsize': 8, 'reg': 4194355}, {'disp': -287454021, 'tsize': 8, '_is_deref': True, 'reg': 2}] self.checkOpcode(opbytez, 0x4000, oprepr, opcheck, opercheck, oprepr)