def report(vw): res = {} for fromva, tova, reftype, rflags in vw.getXrefs(): if vw.getLocation(tova, range=True) is None: rname = v_const.ref_type_names.get(reftype, "Unknown") sname = "Unknown" seg = vw.getSegment(tova) if seg is not None: sname = seg[v_const.SEG_NAME] try: b = e_common.hexify(vw.readMemory(tova, 8)) except Exception as e: b = str(e) res[tova] = (b, "%s ref from 0x%x (%s)" % (rname, fromva, sname)) for va, name in vw.getNames(): if vw.getLocation(va) is None: try: b = e_common.hexify(vw.readMemory(tova, 8)) except Exception as e: b = str(e) res[va] = (b, name) return res
def render(self, mcanv, va): vastr = self.pformat % va # NOTE: we assume the memobj is a trace trace = mcanv.mem sym = trace.getSymByAddr(va) if sym is not None: mcanv.addText('\n') mcanv.addVaText(str(sym), va=va) mcanv.addText(':\n') op = trace.parseOpcode(va, arch=self.arch) obytes = trace.readMemory(va, op.size)[:8] prefix = self._getOpcodePrefix(trace, va, op) mcanv.addText(prefix) mcanv.addVaText(vastr, va=va) mcanv.addText(": %s " % e_common.hexify(obytes).ljust(17)) op.render(mcanv) try: suffix = self._getOpcodeSuffix(trace, va, op) if suffix: mcanv.addText(' ;' + suffix) except Exception as e: mcanv.addText('; suffix error: %s' % e) mcanv.addText("\n") return len(op)
def armthumbdis(db, line, disasmobj): ''' Core of disassmbly, for code-reuse. Only difference is the object actually doing the disassembly. ''' t = db.getTrace() argv = e_cli.splitargs(line) size = 20 argc = len(argv) if argc == 0: addr = t.getProgramCounter() else: addr = t.parseExpression(argv[0]) if argc > 1: size = t.parseExpression(argv[1]) bytez = t.readMemory(addr, size) offset = 0 db.vprint("Dissassembly:") while offset < size: va = addr + offset op = disasmobj.disasm(bytez, offset, va) obytez = bytez[offset:offset + len(op)] db.canvas.addVaText('0x%.8x' % va, va=va) db.canvas.addText(": %s " % e_common.hexify(obytez).ljust(17)) op.render(db.canvas) db.canvas.addText("\n") offset += len(op)
def do_vampsig(self, line): """ Generate a vamp signature string for the given function's first block. """ if not line: return self.do_help("vampsig") va = self.parseExpression(line) fva = self.getFunction(va) if fva is None: self.vprint("Invalid Function Address: 0x%.8x (%s)" % (va, line)) sig, mask = viv_vamp.genSigAndMask(self, fva) self.vprint("SIGNATURE: %s" % e_common.hexify(sig)) self.vprint("MASK: %s" % e_common.hexify(mask))
def buttonClicked(self): curexpr, cur_esize = self.nav.getValues() encoding = str(self.mode_combo.currentText()) rbytes = str(self.data_edit.text()) erbytes = self.encodeData(rbytes, encoding) hexbytes = e_common.hexify(erbytes) self.writeToMemory.emit(curexpr, hexbytes)
def getNameTag(self, name, typename='name'): ''' Return a "tag" for this memory canvas. In the case of the qt tags, they are a tuple of html text (<opentag>, <closetag>) ''' clsname = 'envi-%s' % typename namehex = e_common.hexify(name.lower()) subclsname = 'envi-%s-%s' % (typename, namehex) return ('<span class="%s %s" envitag="%s" envival="%s" onclick="nameclick(this)">' % (clsname,subclsname,typename,namehex), '</span>')
def addRandomSeed(self): ''' Add a random seed to the name hashing subsystem. This will produce values which may *only* be compared to other values generated by this solver. It also lets you calculate deltas by solving for deltas between two symbols in different seed inputs to see if they are likely arithmetically related. ''' self._sym_rseed = e_common.hexify(os.urandom(10))
def release(): parser = optparse.OptionParser() parser.add_option('--cacert', dest='cacert', default=None) parser.add_option('--sslkey', dest='sslkey', default=None) parser.add_option('--sslcert', dest='sslcert', default=None) opts, argv = parser.parse_args() pyzfile, appuri = argv with open(__file__, 'rb') as f: mainsrc = f.read() mainlines = mainsrc.split('\n')[:-2] castr = 'None' keystr = 'None' certstr = 'None' if opts.cacert: with open(opts.cacert, 'rb') as f: castr = '"%s"' % e_common.hexify(f.read()) if opts.sslkey: with open(opts.sslkey, 'rb') as f: keystr = '"%s"' % e_common.hexify(f.read()) if opts.sslcert: with open(opts.sslcert, 'rb') as f: certstr = '"%s"' % e_common.hexify(f.read()) mainlines.append(' appuri="%s"' % appuri) mainlines.append(' cacrt=%s' % castr) mainlines.append(' sslkey=%s' % keystr) mainlines.append(' sslcert=%s' % certstr) mainlines.append( ' main(appuri, cacrt=cacrt, sslcert=sslcert, sslkey=sslkey)') mainsrc = '\n'.join(mainlines) pyz = zipfile.PyZipFile(pyzfile, 'w') pyz.writepy('cobra') pyz.writestr('__main__.py', mainsrc) pyz.close()
def _monitorCommand(self, cmd): resp = '' cmd = 'qRcmd,%s' % e_common.hexify(cmd) pkt = self._cmdTransact(cmd) while not pkt.startswith('OK'): self._raiseIfError(pkt) if not pkt.startswith('O'): return binascii.unhexlify(pkt) resp += binascii.unhexlify(pkt[1:]) pkt = self._recvPkt() return resp
def platformSetRegCtx(self, tid, ctx): ''' Set the target stub's register context from the envi register context ''' # FIXME tid! regbytes = binascii.unhexlify(self._cmdTransact('g')) regremain = regbytes[self._gdb_regsize:] rvals = struct.unpack(self._gdb_regfmt, regbytes[:self._gdb_regsize]) rvals = list(rvals) # So we can assign to them... for myidx, enviidx in self._gdb_reg_xlat: rvals[myidx] = ctx.getRegister(enviidx) newbytes = struct.pack(self._gdb_regfmt, rvals) + regremain return self._cmdTransact('G' + e_common.hexify(newbytes))
def do_memcmp(self, line): ''' Compare memory at the given locations. Outputs a set of differences showing bytes at their given offsets.... Usage: memcmp <addr_expr1> <addr_expr2> <size_expr> ''' if len(line) == 0: return self.do_help('memcmp') argv = splitargs(line) if len(argv) != 3: return self.do_help('memcmp') addr1 = self.parseExpression(argv[0]) addr2 = self.parseExpression(argv[1]) size = self.parseExpression(argv[2]) bytes1 = self.memobj.readMemory(addr1, size) bytes2 = self.memobj.readMemory(addr2, size) res = e_mem.memdiff(bytes1, bytes2) if len(res) == 0: self.vprint('No Differences!') return for offset, offsize in res: diff1 = addr1+offset diff2 = addr2+offset self.canvas.addText('==== %d byte difference at offset %d\n' % (offsize,offset)) self.canvas.addVaText("0x%.8x" % diff1, diff1) self.canvas.addText(":") self.canvas.addText(e_common.hexify(bytes1[offset:offset+offsize])) self.canvas.addText('\n') self.canvas.addVaText("0x%.8x" % diff2, diff2) self.canvas.addText(":") self.canvas.addText(e_common.hexify(bytes2[offset:offset+offsize])) self.canvas.addText('\n')
def createEventChannel(self, wsname): wsinfo = self._req_wsinfo(wsname) chan = e_common.hexify(os.urandom(16)) lock, fpath, pevents, users = wsinfo with lock: events = [] events.extend(viv_basicfile.vivEventsFromFile(fpath)) events.extend(pevents) # These must reference the same actual list object... queue = e_threads.ChunkQueue(items=events) users[chan] = queue self.chandict[chan] = [wsinfo, queue] return chan
def _menuCopyBytesToClipBoard(self, va, currend, all_window_bytes): t = self.db.getTrace() if all_window_bytes: va = self._canv_beginva size = self._canv_endva - va else: if 'asm' in currend: op = t.parseOpcode(va) size = len(op) else: size = t.getPointerSize() bytez = t.readMemory(va, size) clipboard = QApplication.clipboard() clipboard.setText(e_common.hexify(bytez))
def disasm(self, bytez, offset, va): """ Parse a sequence of bytes out into an envi.Opcode instance. """ opval, = struct.unpack_from('>H', bytez, offset) prim = opval >> 8 opdata = h8_parsers.main_table[prim] if opdata is None: raise envi.InvalidInstruction(bytez=bytez[offset:offset + 16], va=va) subtable, mnem, decoder, tsize, iflags = opdata if subtable: raise Exception("NEED subtable at 0x%x: %s" % (va, e_common.hexify(bytez[offset:offset + 16]))) elif decoder is not None: opcode, nmnem, olist, flags, isize = decoder( va, opval, bytez, offset, tsize) # print opcode, nmnem, olist, flags, isize, decoder if nmnem is not None: mnem = nmnem iflags |= flags else: opcode = opval isize = 2 olist = tuple() if olist is None: raise envi.InvalidInstruction( mesg='Operand list cannot be None for instruction "%s"' % mnem, bytez=bytez[offset:offset + 16], va=va) op = h8_operands.H8Opcode(va, opcode, mnem, None, isize, olist, iflags) if op.opers is not None: # following the nasty little hack from other modules. "everybody's doing it!" for oper in op.opers: oper._dis_regctx = self._dis_regctx return op
def dismain(d): ''' Easy utility for implementing stand-alone disassembler utils... ''' # TODO: this belongs as a standalone utility, not in an __init__ file if os.path.isfile(sys.argv[1]): with open(sys.argv[1], 'rb') as f: b = f.read() else: b = binascii.unhexlify(sys.argv[1]) offset = 0 va = 0x41414141 while offset < len(b): op = d.disasm(b, offset, va + offset) print('0x%.8x %s %s' % (va + offset, e_common.hexify( b[offset:offset + len(op)]).ljust(16), repr(op))) offset += len(op)
def render(self, mcanv, va): trace = mcanv.mem max_readable = trace.getMaxReadSize(va) if max_readable <= 0: return '' rsize = min(self.readsize, max_readable) bytez = trace.readMemory(va, rsize) prettyperm = '' mmap = trace.getMemoryMap(va) if mmap is not None: addr, size, perm, fname = mmap prettyperm = e_memory.reprPerms(perm) ascii_text = getAsciiFormatted(bytez) uni_text = getBasicUnicodeFormatted(bytez) sym = getSymByAddrFormatted(trace, va) fname = getFilenameFromFdFormatted(trace, va) desc = '' pdesc = (ascii_text, uni_text, sym, fname) items = [ppdesc for ppdesc in pdesc if ppdesc is not None] if len(items) == 1: desc = items[0] elif len(items) == 0: # if none match, just return the bytes. desc = e_common.hexify(bytez) elif len(items) > 1: # we only really expect one or none of these to match. desc = 'Error, multiple matches for this address!' else: raise Exception('should never get here') best_desc = '%s %s' % (prettyperm, desc) chopped_best_desc = best_desc[:self.maxrend] if len(best_desc) > len(chopped_best_desc): mcanv.addText(' %s...' % chopped_best_desc) else: mcanv.addText(' %s' % chopped_best_desc) return len(chopped_best_desc)
def test_parsers_rudimentary(self, buf=b'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 = binascii.unhexlify(instr[0]) op = h8m.archParseOpcode(inst, 0, 0x50) if len(op) != len(inst): raise Exception( " LENGTH FAILURE: %s '%s' expected: %d real: %d '%s'" % (instr[0], op, len(inst), len(op), e_common.hexify(inst)))
def thumb(db, line): ''' Disassemble thumb instructions from the given address. Usage: thumb <addr_exp> ''' t = db.getTrace() d = e_thumb.ArmThumbDisasm() argv = e_cli.splitargs(line) size = 20 argc = len(argv) if argc == 0: addr = t.getProgramCounter() else: addr = t.parseExpression(argv[0]) if argc > 1: size = t.parseExpression(argv[1]) bytes = t.readMemory(addr, size) offset = 0 db.vprint("Dissassembly:") while offset < size: va = addr + offset op = d.disasm(bytes, offset, va) obytes = bytes[offset:offset + len(op)] db.canvas.addVaText('0x%.8x' % va, va=va) db.canvas.addText(": %s " % e_common.hexify(obytes).ljust(17)) op.render(db.canvas) db.canvas.addText("\n") offset += len(op)
def _loadMacho(vw, filebytes, filename=None, baseaddr=None): # We fake them to *much* higher than norm so pointer tests do better... if baseaddr is None: baseaddr = vw.config.viv.parsers.macho.baseaddr if filename is None: filename = 'macho_%.8x' % baseaddr # FIXME more than one! # grab md5 and sha256 hashes before we modify the bytes fhash = viv_parsers.md5Bytes(filebytes) sha256 = viv_parsers.sha256Bytes(filebytes) # Check for the FAT binary magic... if e_common.hexify(filebytes[:4]) in ('cafebabe', 'bebafeca'): archhdr = None fatarch = vw.config.viv.parsers.macho.fatarch archlist = [] offset = 0 fat = vsm_fat.fat_header() offset = fat.vsParse(filebytes, offset=offset) if fat.magic in vsm_const.FAT_64: archcon = vsm_fat.fat_arch_64 else: archcon = vsm_fat.fat_arch for i in range(fat.nfat_arch): ar = archcon() offset = ar.vsParse(filebytes, offset=offset) archname = vs_macho.mach_cpu_names.get(ar.cputype) if archname == fatarch: archhdr = ar break archlist.append((archname, ar)) if not archhdr: # If we don't have a specified arch, exception! vw.vprint('Mach-O Fat Binary Architectures:') for archname, ar in archlist: vw.vprint('0x%.8x 0x%.8x %s' % (ar.offset, ar.size, archname)) raise Exception( 'Mach-O Fat Binary: Please specify arch with -O viv.parsers.macho.fatarch="<archname>"' ) filebytes = filebytes[archhdr.offset:archhdr.offset + archhdr.size] # Instantiate the parser wrapper and parse bytes macho = vs_macho.mach_o() macho.vsParse(filebytes) arch = vs_macho.mach_cpu_names.get(macho.mach_header.cputype) if arch is None: raise Exception('Unknown MACH-O arch: %.8x' % macho.mach_header.cputype) # Setup arch/plat/fmt vw.setMeta('Architecture', arch) vw.setMeta("Platform", "Darwin") vw.setMeta("Format", "macho") vw.setMeta('DefaultCall', archcalls.get(arch, 'unknown')) # Add the file entry fname = vw.addFile(filename, baseaddr, fhash) vw.setFileMeta(fname, 'sha256', sha256) # Add the memory maps and segments from the macho definition for segname, rva, perms, segbytes in macho.getSegments(): segbase = baseaddr + rva vw.addMemoryMap(segbase, perms, fname, segbytes) vw.addSegment(segbase, len(segbytes), segname, fname) # Add the library dependancies for libname in macho.getLibDeps(): # FIXME hack.... libname = libname.split('/')[-1] libname = libname.split('.')[0].lower() vw.addLibraryDependancy(libname) return fname
def platformWriteMemory(self, addr, mbytes): cmd = 'M%x,%x:%s' % (addr, len(mbytes), e_common.hexify(mbytes)) pkt = self._cmdTransact(cmd)
def do_search(self, line): ''' search memory for patterns. search [options] <pattern> -e <codec> encode the pattern with a codec (hex, utf-16le, etc) -X pattern is in hex (ie. 41414242 is AABB) -E pattern is an envi memory expression (numeric search) -r pattern is a regular expression -R <baseexpr:sizeexpr> search a range of memory (base + size) -c show context (32 bytes) after each hit ''' parser = VOptionParser() parser.add_option('-e', action='store', dest='encode_as') parser.add_option('-X', action='store_true', dest='is_hex') parser.add_option('-E', action='store_true', dest='is_expr') parser.add_option('-r', action='store_true', dest='is_regex') parser.add_option('-R', action='store', dest='range_search') parser.add_option('-c', action='store_const', dest='num_context_bytes', const=32) argv = shlex.split(line) try: options, args = parser.parse_args(argv) except Exception as e: self.vprint(repr(e)) return self.do_help('search') pattern = (' '.join(args)).encode('utf-8') if len(pattern) == 0: self.vprint('you must specify a pattern') return self.do_help('search') if options.is_expr: sval = self.parseExpression(pattern) endian = self.memobj.getEndian() size = self.memobj.getPointerSize() pattern = e_bits.buildbytes(sval, size, bigend=endian) if options.is_hex: pattern = binascii.unhexlify(pattern) if options.encode_as is not None: if options.encode_as == 'hex': pattern = e_common.hexify(pattern) else: import codecs patternutf8 = pattern.decode('utf-8') pattern = codecs.encode(patternutf8, encoding=options.encode_as) if options.range_search: try: addrexpr, sizeexpr = options.range_search.split(":") except Exception as e: self.vprint(repr(e)) return self.do_help('search') addr = self.parseExpression(addrexpr) size = self.parseExpression(sizeexpr) self.canvas.addText('searching from ') self.canvas.addVaText('0x%.8x' % addr, addr) self.canvas.addText(' for %d bytes\n' % size) res = self.memobj.searchMemoryRange(pattern, addr, size, regex=options.is_regex) else: self.vprint('searching all memory...') res = self.memobj.searchMemory(pattern, regex=options.is_regex) if len(res) == 0: self.vprint('pattern not found: %s (%s)' % (e_common.hexify(pattern), repr(pattern))) return brend = e_render.ByteRend() self.vprint('matches for: %s (%s)' % (e_common.hexify(pattern), repr(pattern))) for va in res: mbase,msize,mperm,mfile = self.memobj.getMemoryMap(va) pname = e_mem.reprPerms(mperm) sname = self.reprPointer(va) self.canvas.addVaText('0x%.8x' % va, va) self.canvas.addText(': ') self.canvas.addText('%s ' % pname) self.canvas.addText(sname) if options.num_context_bytes is not None: self.canvas.addText('\n') self.canvas.renderMemory(va, options.num_context_bytes, rend=brend) self.canvas.addText('\n') self.vprint('done (%d results).' % len(res))
def hooks(vdb, line): ''' Check the executable regions of the target process for any hooks by comparing against the PE on disk. This will account for relocations and import entries. ''' t = vdb.getTrace() bases = t.getMeta("LibraryBases") paths = t.getMeta("LibraryPaths") found = False for bname in bases.keys(): base = bases.get(bname) fpath = paths.get(base) with open(fpath, 'rb') as fd: pobj = PE.PE(fpath) filebase = pobj.IMAGE_NT_HEADERS.OptionalHeader.ImageBase skips = {} # Get relocations for skipping r = list(range(t.getPointerSize())) for relrva, reltype in pobj.getRelocations(): for i in r: skips[base + relrva + i] = True # Add the import entries to skip for iva, libname, name in pobj.getImports(): for i in r: skips[base + iva + i] = True for sec in pobj.getSections(): if sec.Characteristics & PE.IMAGE_SCN_MEM_EXECUTE: size = sec.VirtualSize va = base + sec.VirtualAddress fileva = filebase + sec.VirtualAddress filebytes = pobj.readAtRva(sec.VirtualAddress, sec.VirtualSize) procbytes = t.readMemory(va, size) for off, size in bindiff(filebytes, procbytes): difva = va + off fdifva = fileva + off # Check for a relocation covering this... if skips.get(difva): continue found = True dmem = e_common.hexify(procbytes[off:off + size])[:10] dfil = e_common.hexify(filebytes[off:off + size])[:10] vdb.canvas.addVaText('0x%.8x' % difva, difva) vdb.canvas.addText(' (0x%.8x) (%d)' % (fdifva, size)) vdb.canvas.addText(' mem: %s file: %s ' % (dmem, dfil)) sym = vdb.symobj.getSymByAddr(difva, exact=False) if sym is not None: vdb.canvas.addText(' ') vdb.canvas.addVaText( '%s + %d' % (repr(sym), difva - int(sym)), difva) vdb.canvas.addText('\n') if not found: vdb.canvas.addText('No Hooks Found!\n')
def menuCopyBytesToClipboard(self, va, size): bytez = self.mem.readMemory(va, size) clipboard = QApplication.clipboard() clipboard.setText(e_common.hexify(bytez))
def renderLocation(self, mcanv, loc, name, isfunc, cmnt, extra): """ Actually render a given VA to the given text buffer. If there is *any* function to optimize, this is it... it renders EVERYTHING... """ lva, lsize, ltype, tinfo = loc vatag = mcanv.getVaTag(lva) cmnttag = mcanv.getTag("comment") seg = self.vw.getSegment(lva) segname = "map" if seg is None else seg[SEG_NAME] vastr = self.vw.arch.pointerString(lva) linepre = "%s:%s " % (segname, vastr) xrefs = self.vw.getXrefsTo(lva) xrcount = len(xrefs) if seg is not None and self._show_segment: segva, segsize, segname, segfname = seg if segva == lva: mcanv.addText(linepre, tag=vatag) mcanv.addText("Segment: %s (%d bytes) FIXME PERMS\n" % (segname, segsize)) if isfunc: mcanv.addText(linepre, tag=vatag) mcanv.addText('\n') mcanv.addText(linepre, tag=vatag) mcanv.addText("FUNC: ") api = self.vw.getFunctionApi(lva) rtype, rname, convname, apiname, apiargs = api mcanv.addNameText(rtype) mcanv.addText(' ') mcanv.addNameText(convname) mcanv.addText(' ') mcanv.addText(name, tag=vatag) mcanv.addText("( ") for typename, argname in apiargs: mcanv.addNameText(typename) mcanv.addText(' ') mcanv.addNameText(argname) mcanv.addText(', ') mcanv.addText(")") # FIXME color code and get args parsing goin on mcanv.addText(" ") xrtag = mcanv.getTag("xrefs") mcanv.addText("[%d XREFS]\n" % xrcount, tag=xrtag) mcanv.addText(linepre, tag=vatag) mcanv.addText('\n') mcanv.addText(linepre, tag=vatag) mcanv.addText('Stack Variables:\n') funclocals = self.vw.getFunctionLocals(lva) funclocals.sort() funclocals.reverse() for _, spdelta, _, _ in funclocals: # Make the workspace do the resolving for us typename, varname = self.vw.getFunctionLocal(lva, spdelta) mcanv.addText(linepre, tag=vatag) mcanv.addText(' ') mcanv.addText('%4d: ' % spdelta) mcanv.addNameText(typename) mcanv.addText(' ') mcanv.addNameText(varname) mcanv.addText('\n') mcanv.addText(linepre, tag=vatag) mcanv.addText('\n') elif xrcount > 0 or name is not None: mcanv.addText(linepre, tag=vatag) if name is None: name = "loc_%.8x" % lva mcanv.addText(urllib.parse.quote_plus(name), tag=vatag) mcanv.addText(": ") xrtag = mcanv.getTag("xrefs") mcanv.addText('[%d XREFS]\n' % xrcount, tag=xrtag) if ltype == LOC_OP: mcanv.addText(linepre, tag=vatag) opbytes = mcanv.mem.readMemory(lva, lsize) mcanv.addText(e_common.hexify(opbytes[:8]).ljust(17)) # extra is the opcode object try: extra.render(mcanv) except Exception as e: mcanv.addText("Opcode Render Failed: %s (%s)\n" % (repr(extra), str(e))) if cmnt is not None: mcanv.addText(" ;%s" % cmnt, tag=cmnttag) mcanv.addText("\n") elif ltype == LOC_STRUCT: for soff, sind, sname, sobj in extra.vsGetPrintInfo(): sva = lva + soff if soff != 0: vastr = self.vw.arch.pointerString(sva) linepre = '%s:%s ' % (segname, vastr) vatag = mcanv.getVaTag(sva) mcanv.addText(linepre, tag=vatag) totag = None if isinstance(sobj, vs_prims.v_ptr): stova = int(sobj) stoname = self.vw.getName(stova) if stoname is None: stoname = repr(sobj) if self.vw.isValidPointer(stova): totag = mcanv.getVaTag(stova) # Insert the field name (and indent) mcanv.addText(" " * sind) mcanv.addNameText(sname) mcanv.addText(": ") # Insert the sobj info (if it's a primitive) if isinstance(sobj, vs_prims.v_prim): if totag is not None: mcanv.addText(stoname, tag=totag) else: mcanv.addText(repr(sobj)) if soff != 0: xrefs = self.vw.getXrefsTo(sva) if len(xrefs): xrtag = mcanv.getTag("xrefs") mcanv.addText("[%d XREFS]" % len(xrefs), tag=xrtag) # Handle the comment if present cmnt = self.vw.getComment(sva) if cmnt is not None: mcanv.addText(" ;%s" % cmnt, tag=cmnttag) mcanv.addText("\n") elif ltype == LOC_POINTER: fromva, tova, rtype, rflags = self.vw.getXrefsFrom(lva)[ 0] # FIXME hardcoded one mcanv.addText(linepre, tag=vatag) mcanv.addNameText("ptr: ") totag = mcanv.getVaTag(tova) pstr = self.vw.arch.pointerString(tova) mcanv.addText(pstr, tag=totag) name = self.vw.getName(tova) if name is None: name = "loc_%.8x" % tova # FIXME 64bit mcanv.addText(" (") mcanv.addText(name, tag=totag) mcanv.addText(")") if cmnt is not None: mcanv.addText(" ;%s" % cmnt, tag=cmnttag) mcanv.addText("\n") elif ltype == LOC_UNDEF: mcanv.addText(linepre, vatag) offset, bytez = self.vw.getByteDef(lva) b = bytez[offset:offset + 1] mcanv.addNameText(b.hex(), typename="undefined") try: b = b.decode('utf-8') if b in string.printable: mcanv.addText(' %s' % repr(b), tag=cmnttag) except: # if we don't decode correctly, don't print it. pass if cmnt is not None: mcanv.addText(' ;%s' % cmnt, tag=cmnttag) mcanv.addText("\n") elif ltype == LOC_IMPORT: mcanv.addText(linepre, vatag) tva = self.vw.vaByName(tinfo) mcanv.addText('IMPORT: ') if tva is not None: mcanv.addVaText(tinfo, tva) else: mcanv.addText(tinfo) if cmnt is not None: mcanv.addText(" ;%s" % cmnt, tag=cmnttag) mcanv.addText("\n") else: tagname = loc_type_names.get(ltype, None) if tagname is None: tagname = "location" ltag = mcanv.getTag(tagname) cdone = False for line in self.vw.reprLocation(loc).split("\n"): mcanv.addText(linepre, tag=vatag) mcanv.addText(line, ltag) if not cdone: cdone = True if cmnt is not None: mcanv.addText(" ;%s" % cmnt, tag=cmnttag) mcanv.addText("\n")