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:

            try:
                op = self._arch.archParseOpcode(bytez.decode('hex'), 0, va)
            except envi.InvalidInstruction:
                self.fail(
                    "Failed to parse opcode bytes: %s (case: %s, expected: %s)"
                    % (bytez, name, reprOp))
            # 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)
            # print("render:  %s" % repr(scanv.strval))
            self.assertEqual(scanv.strval, renderOp)
Exemple #2
0
    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(bytez.decode('hex'), 0, va)
            except envi.InvalidInstruction:
                self.fail(
                    "Failed to parse opcode bytes: %s (case: %s, expected: %s)"
                    % (bytez, name, reprOp))
            except Exception as e:
                self.fail(
                    "Failed to parse opcode bytes: %s (case: %s, expected: %s)"
                    % (bytez, name, reprOp))
            # 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)
            # print("render:  %s" % repr(scanv.strval))
            self.assertEqual(scanv.strval, renderOp)
Exemple #3
0
    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)
Exemple #4
0
def _get_function_data(vw: VivWorkspace):
    all_funcs_va = vw.getFunctions()
    all_funcs_va = sorted(all_funcs_va)

    str_canvas = memcanvas.StringMemoryCanvas(vw)

    for fva in all_funcs_va:
        f_meta = vw.getFunctionMetaDict(fva)
        meta_keys = sorted(f_meta.keys())
        f_name = vw.getName(fva)

        str_canvas.addText('Function: %s\n' % f_name)
        for m_key in meta_keys:
            str_canvas.addText("\t%s: %s\n" % (str(m_key), str(f_meta[m_key])))

        for cbva, cbsize, cbfva in vw.getFunctionBlocks(fva):

            finalva = cbva + cbsize
            while cbva < finalva:
                opcode = vw.parseOpcode(cbva, const.LOC_OP)
                opcode.render(str_canvas)
                str_canvas.addText("\n")
                cbva += opcode.size

        str_canvas.addText('\n')

    return str_canvas.strval
Exemple #5
0
    def vqLoad(self):
        self.lastregs = self.regvals.copy()
        if not self.trace.isAttached():
            self.setEnabled(False)
            return

        if self.trace.isRunning():
            self.setEnabled(False)
            return

        model = RegisterListModel(parent=self)
        self.setModel(model)

        for rname in self.regnames:
            rval = self.trace.getRegisterByName(rname)
            self.regvals[rname] = rval
            hexva = self.trace.pointerString(rval)

            try:
                # TODO: yuck...implement a "fast" string memorycanvas?
                smc = e_mcanv.StringMemoryCanvas(self.trace)
                self.descrend.render(smc, rval)
            except Exception as e:
                smc = repr(e)
            finally:
                model.append((rname, hexva, rval, str(smc)))
Exemple #6
0
    def render(self, mcanv, va):
        trace = mcanv.mem
        if va != trace.getStackCounter():
            return DerefRenderer.render(self, mcanv, va)

        pc = trace.getProgramCounter()
        sym, is_thunk = trace.getSymByAddrThunkAware(pc)
        if sym is None:
            return DerefRenderer.render(self, mcanv, va)

        # TODO: this code also exists in win32stealth and in hookbreakpoint
        # we should put this somewhere common
        platform = trace.getMeta('Platform')
        arch = trace.getMeta('Architecture')
        impapi = viv_impapi.getImportApi(platform, arch)
        cc_name = impapi.getImpApiCallConv(sym)
        emu = vtrace.getEmu(trace)
        cc = emu.getCallingConvention(cc_name)
        args_def = impapi.getImpApiArgs(sym)
        if args_def is None:
            # sym did not exist in impapi :(
            logger.warning('sym but no impapi match: {}'.format(sym))
            return DerefRenderer.render(self, mcanv, va)

        argc = len(args_def)

        curop = trace.parseOpcode(trace.getProgramCounter())

        # use the calling convention to retrieve the args
        args = None
        if curop.isCall() or is_thunk:
            args = cc.getPreCallArgs(trace, argc)
        else:
            args = cc.getCallArgs(trace, argc)

        # since we are 'normalizing' the calls by visualizing all calling
        # conventions in a stdcall fashion, some args (like the ones in
        # registers don't have a stack va.
        mcanv.addText('%s :\n' % sym)
        fmt = '  arg%%d (%%s) 0x%%0%dx %%s\n' % (trace.getPointerSize() * 2, )
        for index, arg in enumerate(args):
            argtype = args_def[index][0]
            argva = arg
            if trace.isValidPointer(arg):
                argva = trace.readMemoryFormat(arg, 'P')[0]
            smc = e_canvas.StringMemoryCanvas(trace)
            e_canvas_rend.AutoBytesRenderer(maxrend=64).render(smc, argva)
            desc = str(smc)
            mcanv.addText(fmt % (index, argtype, arg, desc))
        mcanv.addText('-' * 5)
        mcanv.addText('\n')

        return DerefRenderer.render(self, mcanv, va)
    def SKIPtest_envi_amd64_disasm_Specific_VEX_Instrs(self):
        vw = vivisect.VivWorkspace()
        scanv = e_memcanvas.StringMemoryCanvas(vw)

        for name, bytez, va, reprOp, renderOp in amd64VexOpcodes:

            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)
Exemple #8
0
    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(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)
Exemple #10
0
    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 list(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 list(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 )
Exemple #11
0
    def do_saveout(self, line):
        '''
        saves output to file for any command.  still outputs to whatever
        canvas the command normally outputs to.

        saveout <output file> <cli command>

        Example:
        saveout out.txt search -c MZ
        '''
        argv = shlex.split(line)
        if len(argv) < 2:
            return self.do_help('saveout')

        fname = argv[0]
        command = ' '.join(argv[1:])

        strcanvas = e_canvas.StringMemoryCanvas(self.canvas.mem)
        with e_canvas.TeeCanvas(self, (self.canvas, strcanvas)) as tc:
            self.onecmd(command)

            with open(fname, 'wb') as f:
                f.write(str(strcanvas))
Exemple #12
0
    def regEdited(self, index, value):
        node = index.internalPointer()
        if not node or not value:
            return False

        expr = str(value.toString())
        try:
            value = self.trace.parseExpression(expr)
        except Exception as e:
            return False

        reg = node.rowdata[0]
        self.trace.setRegisterByName(reg, value)
        regval = self.trace.getRegisterByName(reg)
        # TODO: yuck...implement a "fast" string memorycanvas?
        smc = e_mcanv.StringMemoryCanvas(self.trace)
        self.descrend.render(smc, regval)

        node.rowdata[1] = self.trace.pointerString(regval)
        node.rowdata[2] = regval
        node.rowdata[3] = str(smc)

        return True
Exemple #13
0
    def test_do_cmds(self):
        mem = e_mem.MemoryObject()
        mem.addMemoryMap(0x41410000, 7, 'testmem', b'@ABCDEF' * 256)

        ecli = e_cli.EnviCli(mem)

        ecli.canvas = e_mcanvas.StringMemoryCanvas(mem)
        ecli.canvas.addRenderer("bytes", e_render.ByteRend())
        ecli.canvas.addRenderer("u_int_16", e_render.ShortRend())
        ecli.canvas.addRenderer("u_int_32", e_render.LongRend())
        ecli.canvas.addRenderer("u_int_64", e_render.QuadRend())

        # do_alias
        ecli.do_alias('')
        output = ecli.canvas.strval
        self.assertIn('Runtime Aliases (not saved):', output)
        self.assertIn('Configured Aliases:', output)
        ecli.canvas.clearCanvas()

        # do_binstr
        ecli.do_binstr('47145')
        output = ecli.canvas.strval
        self.assertIn('0x0000b829 (47145) 1011100000101001', output)
        ecli.canvas.clearCanvas()

        # do_clear
        ecli.vprint("foobar")
        ecli.do_clear('')
        output = ecli.canvas.strval
        self.assertEqual('', output)
        ecli.canvas.clearCanvas()

        # do_config
        ecli.do_config('')
        output = ecli.canvas.strval
        self.assertIn('cli.verbose = False\n', output)
        ecli.canvas.clearCanvas()

        # do_EOF
        ecli.do_EOF('')
        output = ecli.canvas.strval
        self.assertIn('Use quit\n', output)
        ecli.canvas.clearCanvas()

        # do_eval
        ecli.do_eval('0x40 + 0x47145')
        output = ecli.canvas.strval
        self.assertIn('0x40 + 0x47145 = 0x00047185 (291205)\n', output)
        ecli.canvas.clearCanvas()

        # do_maps
        ecli.do_maps('')
        output = ecli.canvas.strval
        self.assertIn('0x41410000', output)
        ecli.canvas.clearCanvas()

        ecli.do_maps('0x41410001')
        output = ecli.canvas.strval
        self.assertIn(' 0x41410001\n0x41410000', output)
        ecli.canvas.clearCanvas()

        # do_mem
        ecli.do_mem('0x41410001 20')
        output = ecli.canvas.strval
        self.assertIn(
            '0x41410001  41 42 43 44 45 46 40 41 42 43 44 45 46 40 41 42   ABCDEF@ABCDEF@AB\n0x41410011  43 44 45 46 40 41 42 43 44 45 46 40 41 42 43 44   CDEF@ABCDEF@ABCD\n',
            output)
        ecli.canvas.clearCanvas()

        ecli.do_mem('-F u_int_16 0x41410001 20')
        output = ecli.canvas.strval
        self.assertIn(
            '0x41410001  4241 4443 4645 4140 4342 4544 4046 4241   ABCDEF@ABCDEF@AB\n0x41410011  4443 4645 4140 4342 4544 4046 4241 4443   CDEF@ABCDEF@ABCD\n',
            output)
        ecli.canvas.clearCanvas()

        ecli.do_mem('-F u_int_32 0x41410001 20')
        output = ecli.canvas.strval
        self.assertIn(
            '0x41410001  44434241 41404645 45444342 42414046   ABCDEF@ABCDEF@AB\n0x41410011  46454443 43424140 40464544 44434241   CDEF@ABCDEF@ABCD\n',
            output)
        ecli.canvas.clearCanvas()

        ecli.do_mem('-F u_int_64 0x41410001 20')
        output = ecli.canvas.strval
        self.assertIn(
            '0x0000000041410001  4140464544434241 4241404645444342   ABCDEF@ABCDEF@AB\n0x0000000041410011  4342414046454443 4443424140464544   CDEF@ABCDEF@ABCD\n',
            output)
        ecli.canvas.clearCanvas()

        # do_memcmp
        ecli.do_memcmp('0x41410001 0x41410005 20')
        output = ecli.canvas.strval
        self.assertIn(
            '==== 20 byte difference at offset 0\n0x41410001:4142434445464041424344454640414243444546\n0x41410005:4546404142434445464041424344454640414243\n',
            output)
        ecli.canvas.clearCanvas()

        # do_memdump
        ecli.do_memdump('0x41410001 /tmp/foo40 20')
        output = ecli.canvas.strval
        self.assertIn('wrote 20 bytes.\n', output)
        ecli.canvas.clearCanvas()
        with open('/tmp/foo40', 'rb') as testfile:
            self.assertEqual(testfile.read(), b'ABCDEF@ABCDEF@ABCDEF')
        ecli.canvas.clearCanvas()

        # do_python
        ecli.do_python(
            'with open("/tmp/foo41", "wb") as testfile:\n\ttestfile.write(b"Test Worked")'
        )
        output = ecli.canvas.strval
        with open('/tmp/foo41', 'rb') as testfile:
            self.assertEqual(testfile.read(), b'Test Worked')
        ecli.canvas.clearCanvas()

        # do_saveout
        ecli.do_saveout('/tmp/foo42 search ABCDEF')
        output = ecli.canvas.strval
        self.assertIn('\ndone (256 results).\n', output)
        ecli.canvas.clearCanvas()

        # do_search
        ecli.do_search('ABCDEF')
        output = ecli.canvas.strval
        self.assertIn('\ndone (256 results).\n', output)
        ecli.canvas.clearCanvas()
Exemple #14
0
                return

            for nva, node in graph.getNodes():
                va = nva
                endva = va + node.get('cbsize')
                while va < endva:
                    lva, lsz, ltype, ltinfo = self.getLocation(va)
                    valist.append(va)
                    va += lsz

        else:
            # the whole workspace is our oyster
            valist = [va for va, lvsz, ltype, ltinfo in self.getLocations(LOC_OP)]

        res = []
        canv = e_canvas.StringMemoryCanvas(self)

        defaultSearchAll = True
        for va in valist:
            try:
                addthis = False
                op = self.parseOpcode(va)

                # search comment
                if options.searchComments:
                    defaultSearchAll = False
                    cmt = self.getComment(va)
                    if cmt != None:

                        if options.is_regex:
                            if len(re.findall(pattern, cmt)):
Exemple #15
0
    def runStep(self,
                maxstep=1000000,
                follow=True,
                showafter=True,
                runTil=None,
                pause=True,
                silent=False,
                finish=0,
                silentExcept=()):
        global op, mcanv, call_handlers
        emu = self.emu

        mcanv = e_memcanvas.StringMemoryCanvas(emu, syms=emu.vw)

        nonstop = 0
        tova = None
        quit = False
        moveon = False
        emuBranch = False

        i = 0
        while maxstep > i:
            skip = skipop = False
            i += 1

            pc = emu.getProgramCounter()
            if pc in (runTil, finish):
                break

            op = emu.parseOpcode(pc)

            # cancel emuBranch as we've come to one
            if op.isReturn() or op.isCall():
                emuBranch = False

            if silent and not pc in silentExcept:
                showafter = False
            else:
                # do all the interface stuff here:
                showPriRegisters(emu, snapshot=SNAP_SWAP)
                #showFlags(emu) # ARM fails this right now.
                try:
                    printMemStatus(emu, op)
                except Exception as e:
                    print "MEM ERROR: %s:    0x%x %s" % (e, op.va, op)

                print "Step: %s" % i
                mcanv.clearCanvas()
                try:
                    op.render(mcanv)
                except Exception as e:
                    print "ERROR rendering opcode: %r" % e

                extra = getNameRefs(op, emu)

                opbytes = emu.readMemory(pc, len(op))
                print("%.4x\t%20s\t%s\t%s" %
                      (pc, sp.hexText(opbytes), mcanv.strval, extra))

                print "---------"
                prompt = "q<enter> - exit, eval code to execute, 'skip' an instruction, 'b'ranch, 'go [+]#' to va or +# instrs or enter to continue: "

                # nonstop controls whether we stop.  tova indicates we're hunting for a va, otherwise
                # treat nonstop as a negative-counter
                if tova is not None:
                    if pc == tova:
                        nonstop = 0

                elif nonstop:
                    nonstop -= 1

                if not (emuBranch or nonstop) and pause:
                    tova = None
                    moveon = False

                    uinp = raw_input(prompt)
                    while len(uinp) and not (moveon or quit or emuBranch):
                        if uinp == "q":
                            quit = True
                            break
                        elif uinp.startswith('go '):
                            args = uinp.split(' ')
                            if args[-1].startswith('+'):
                                nonstop = int(args[-1], 0)
                            else:
                                tova = int(args[-1], 0)
                                nonstop = 1
                            break

                        elif uinp in ('b', 'branch'):
                            emuBranch = True
                            break

                        elif uinp == 'stack':
                            stackDump(emu)
                            break

                        elif uinp == 'refresh':
                            # basically does a NOP, doesn't change anything, just let the data be reprinted.
                            moveon = True
                            break

                        elif uinp.startswith('pc=') or uinp.startswith('pc ='):
                            print "handling setProgramCounter()"
                            args = uinp.split('=')
                            newpc = int(args[-1], 0)
                            print "new PC: 0x%x" % newpc
                            emu.setProgramCounter(newpc)
                            moveon = True
                            break

                        elif '=' in uinp:
                            print "handling generic register/memory writes"
                            args = uinp.split('=')
                            details = args[-1].split(',')
                            if '[' in args[0]:
                                if len(details) > 1:
                                    size = int(details[-1])
                                else:
                                    size = 4

                                #memaddr = int(args[0].replace('[','').replace(']',''), 0)
                                memaddr = emu.vw.parseExpression(
                                    args[0].replace('[', '').replace(']', ''))
                                emu.writeMemValue(
                                    memaddr,
                                    emu.vw.parseExpression(details[0], 0),
                                    size)
                                #emu.writeMemValue(memaddr, int(details[0], 0), size)

                            else:
                                # must be registers
                                emu.setRegisterByName(args[0],
                                                      int(details[0], 0))

                        elif uinp.strip().startswith('[') and ']' in uinp:
                            try:
                                idx = uinp.find('[') + 1
                                eidx = uinp.find(']', idx)
                                expr = uinp[idx:eidx]
                                print "handling memory read at [%s]" % expr
                                size = emu.getPointerSize()
                                if ':' in expr:
                                    nexpr, size = expr.rsplit(':', 1)
                                    try:
                                        size = emu.vw.parseExpression(size)
                                        expr = nexpr
                                    except:
                                        # if number fails, just continue with a default size and the original expr
                                        pass

                                va = emu.vw.parseExpression(expr)
                                data = emu.readMemory(va, size)
                                print "[%s:%s] == %r" % (expr, size,
                                                         data.encode('hex'))
                            except Exception as e:
                                print "ERROR: %r" % e

                        elif uinp == 'skip':
                            newpc = emu.getProgramCounter() + len(op)
                            print "new PC: 0x%x" % newpc
                            skipop = True
                            break
                        elif uinp == 'memset':
                            print memset(emu)
                            skipop = True
                        elif uinp == 'memcpy':
                            print memcpy(emu)
                            skipop = True
                        elif uinp == 'strcpy':
                            print strcpy(emu)
                            skipop = True
                        elif uinp == 'strncpy':
                            print strncpy(emu)
                            skipop = True
                        elif uinp == 'strcat':
                            print strcat(emu)
                            skipop = True
                        elif uinp == 'strlen':
                            print strlen(emu)
                            skipop = True
                        else:
                            try:
                                print eval(uinp, globals(), locals())
                            except:
                                sys.excepthook(*sys.exc_info())

                        uinp = raw_input(prompt)

            if quit:
                return

            if moveon:
                continue

            if len(op.opers) and op.iflags & (envi.IF_CALL) and not skipop:
                self.dbgprint("Call...")
                tva = op.getOperValue(0, emu)
                handler = self.call_handlers.get(tva)
                self.dbgprint(" handler for call to (0x%x): %r" %
                              (tva, handler))
                if handler is not None:
                    handler(emu, op)
                    skipop = True

                elif follow and not skip and not skipop:
                    # use the emulator to execute the call
                    starteip = emu.getProgramCounter()
                    emu.executeOpcode(op)
                    endeip = emu.getProgramCounter()
                    i += 1

                    self.dbgprint("starteip: 0x%x, endeip: 0x%x  -> %s" %
                                  (starteip, endeip, emu.vw.getName(endeip)))
                    vg_path.getNodeProp(emu.curpath, 'valist').append(starteip)
                    skip = True

            if not skip and not skipop:
                # if not already emulated a call, execute the instruction here...
                emu.stepi()

                # print the updated latest stuff....
                if showafter:
                    try:
                        extra = getNameRefs(op, emu)
                        if len(extra):
                            print("after:\t%s\t%s" % (mcanv.strval, extra))

                        printMemStatus(emu, op, use_cached=True)
                    except Exception as e:
                        print "MEM ERROR: %s:    0x%x %s" % (e, op.va, op)

            elif skipop:
                newpc = emu.getProgramCounter() + len(op)
                emu.setProgramCounter(newpc)
Exemple #16
0
    def do_searchopcodes(self, line):
        '''
        search opcodes/function for a pattern

        searchopcodes [-f <funcva>] [options] <pattern>
        -f [fva]   - focus on one function
        -c         - search comments
        -o         - search operands
        -t         - search text
        -M <color> - mark opcodes (default = orange)
        -R         - pattern is REGEX (otherwise just text)

        '''
        parser = e_cli.VOptionParser()
        parser.add_option('-f', action='store', dest='funcva', type='int')
        parser.add_option('-c', action='store_true', dest='searchComments')
        parser.add_option('-o', action='store_true', dest='searchOperands')
        parser.add_option('-t', action='store_true', dest='searchText')
        parser.add_option('-M',
                          action='store',
                          dest='markColor',
                          default='orange')
        parser.add_option('-R', action='store_true', dest='is_regex')

        argv = shlex.split(line)
        try:
            options, args = parser.parse_args(argv)
        except Exception as e:
            self.vprint(repr(e))
            return self.do_help('searchopcodes')

        pattern = ' '.join(args)
        if len(pattern) == 0:
            self.vprint('you must specify a pattern')
            return self.do_help('searchopcodes')

        # generate our interesting va list
        valist = []
        if options.funcva:
            # setup valist from function data
            try:
                fva = options.funcva
                graph = viv_graph.buildFunctionGraph(self, fva)
            except Exception as e:
                self.vprint(repr(e))
                return

            for nva, node in graph.getNodes():
                va = nva
                endva = va + node.get('cbsize')
                while va < endva:
                    lva, lsz, ltype, ltinfo = self.getLocation(va)
                    valist.append(va)
                    va += lsz

        else:
            # the whole workspace is our oyster
            valist = [
                va for va, lvsz, ltype, ltinfo in self.getLocations(LOC_OP)
            ]

        res = []
        canv = e_canvas.StringMemoryCanvas(self)

        defaultSearchAll = True
        for va in valist:
            try:
                addthis = False
                op = self.parseOpcode(va)

                # search comment
                if options.searchComments:
                    defaultSearchAll = False
                    cmt = self.getComment(va)
                    if cmt is not None:

                        if options.is_regex:
                            if len(re.findall(pattern, cmt)):
                                addthis = True

                        else:
                            if pattern in cmt:
                                addthis = True

                # search operands
                if options.searchOperands:
                    defaultSearchAll = False
                    for opidx, oper in enumerate(op.opers):
                        # we're writing to a temp canvas, so clear it before each test
                        canv.clearCanvas()
                        oper = op.opers[opidx]
                        oper.render(canv, op, opidx)
                        operepr = canv.strval

                        if options.is_regex:
                            if len(re.findall(pattern, operepr)):
                                addthis = True

                        else:
                            if pattern in operepr:
                                addthis = True

                            # if we're doing non-regex, let's test against real numbers
                            # (instead of converting to hex and back)
                            numpattrn = pattern
                            try:
                                numpattrn = int(numpattrn, 0)
                            except:
                                pass

                            if numpattrn in vars(oper).values():
                                addthis = True

                # search full text
                if options.searchText or defaultSearchAll:
                    # search through the rendering of the opcode, as well as the comment
                    canv.clearCanvas()
                    op.render(canv)
                    oprepr = canv.strval
                    cmt = self.getComment(va)
                    if cmt is not None:
                        oprepr += "  ; " + cmt

                    if options.is_regex:
                        if len(re.findall(pattern, oprepr)):
                            addthis = True

                    else:
                        if pattern in oprepr:
                            addthis = True
                # only want one listing of each va, no matter how many times it matches
                if addthis:
                    res.append(va)
            except:
                self.vprint(''.join(
                    traceback.format_exception(*sys.exc_info())))

        if len(res) == 0:
            self.vprint('pattern not found: %s (%s)' %
                        (pattern.encode('utf-8').hex(), repr(pattern)))
            return

        # set the color for each finding
        color = options.markColor
        colormap = {va: color for va in res}
        if self._viv_gui is not None:
            from vqt.main import vqtevent
            vqtevent('viv:colormap', colormap)

        self.vprint('matches for: %s (%s)' %
                    (pattern.encode('utf-8').hex(), repr(pattern)))
        for va in res:
            mbase, msize, mperm, mfile = self.memobj.getMemoryMap(va)
            pname = e_memory.reprPerms(mperm)
            sname = self.reprPointer(va)

            op = self.parseOpcode(va)
            self.canvas.renderMemory(va, len(op))
            cmt = self.getComment(va)
            if cmt is not None:
                self.canvas.addText('\t\t; %s (Perms: %s, Smartname: %s)' %
                                    (cmt, pname, sname))

            self.canvas.addText('\n')

        self.vprint('done (%d results).' % len(res))
Exemple #17
0
    def __init__(self, expr='', esize='', emu=None, parent=None):
        QWidget.__init__(self, parent=parent)

        self.modes = [
            'ascii', 'hex', 'regex', 'utf-8', 'utf-16-le', 'utf-16-be'
        ]

        rend_orig = e_render.ByteRend()
        self.canvas_orig = e_canvas.StringMemoryCanvas(None)
        self.canvas_orig.addRenderer('bytes', rend_orig)

        rend_new = e_render.ByteRend()
        self.canvas_new = e_canvas.StringMemoryCanvas(None)
        self.canvas_new.addRenderer('bytes', rend_new)

        hbox1 = QHBoxLayout()
        self.nav = MemNavWidget()
        self.nav.userChanged.connect(self.renderMemory)
        self.renderRequest.connect(self.nav.setValues)
        hbox1.addWidget(self.nav)

        hbox2 = QHBoxLayout()
        self.hex_edit = QPlainTextEdit()
        self.hex_edit.setWordWrapMode(QtGui.QTextOption.NoWrap)
        self.hex_edit.setReadOnly(True)
        font = QtGui.QFont('Courier')  # should use actual memcanvas
        self.hex_edit.setFont(font)
        hbox2.addWidget(self.hex_edit)

        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)
        gbox1 = QGroupBox('Original Bytes')
        gbox1.setLayout(vbox1)

        hbox3 = QHBoxLayout()
        mode_label = QLabel('Input:')
        self.mode_combo = QComboBox()
        self.mode_combo.addItems(self.modes)
        self.mode_combo.currentIndexChanged.connect(self.encodingChanged)
        hbox3.addWidget(mode_label)
        hbox3.addWidget(self.mode_combo, alignment=QtCore.Qt.AlignLeft)
        hbox3.addStretch(1)

        hbox4 = QHBoxLayout()
        data_label = QLabel('Bytes:')
        self.data_edit = VQLineEdit()
        self.data_edit.keyReleased.connect(self.keyReleasedSlot)
        hbox4.addWidget(data_label)
        hbox4.addWidget(self.data_edit)

        vbox2 = QVBoxLayout()
        vbox2.addLayout(hbox3)
        vbox2.addLayout(hbox4)
        gbox2 = QGroupBox('New Bytes')
        gbox2.setLayout(vbox2)

        hbox5 = QHBoxLayout()
        self.hex_preview = QPlainTextEdit()
        self.hex_preview.setWordWrapMode(QtGui.QTextOption.NoWrap)
        self.hex_preview.setReadOnly(True)
        self.hex_preview.setFont(font)
        hbox5.addWidget(self.hex_preview)

        vbox3 = QVBoxLayout()
        vbox3.addLayout(hbox5)
        gbox3 = QGroupBox('Result Preview')
        gbox3.setLayout(vbox3)

        hbox6 = QHBoxLayout()
        button = QPushButton('Write Memory')
        button.clicked.connect(self.buttonClicked)
        hbox6.addWidget(button)

        vbox = QVBoxLayout()
        vbox.addWidget(gbox1)
        vbox.addWidget(gbox2)
        vbox.addWidget(gbox3)
        vbox.addLayout(hbox6)
        self.setLayout(vbox)

        self.setWindowTitle('Memory Write')
        self.resize(650, 500)
        self.data_edit.setFocus()
        self.emu = emu
        self.renderMemory(expr, esize)
Exemple #18
0
    def runStep(self,
                maxstep=1000000,
                follow=True,
                showafter=True,
                runTil=None,
                pause=True,
                silent=False,
                finish=0,
                tracedict=None):
        '''
        runStep is the core "debugging" functionality for this emulation-helper.  it's goal is to 
        provide a single-step interface somewhat like what you might get from a GDB experience.  

        pertinent registers are printed with their values, the current instruction, and any helpers
        that the operands may point to in memory (as appropriate).

        special features:
        * tracedict allows code to be evaluated and printed at specific addresses: 
                tracedict={va:'python code here', 'locals':{'something':4}}

        * prints out the operands *after* exection as well  (arg:showafter=True) 

        * cli interface allows viewing and modifying memory/python objects:
                rax
                [rax]
                [rax:23]
                [rax+8:4]
                [0xf00b4:8]
                rax=42
                [0xf00b4]=0x47145
        * cli allows skipping printing  (arg:silent=True)
                silent=True
        * cli allows running until a VA without pauses: 
                go 0x12345
        * cli allows executing until next branch:
                b
        * cli allows dumping the stack:
                stack
        * cli allows viewing/setting the Program Counter:
                pc
                pc=0x43243
        * cli allows skipping instructions:
                skip
        * cli allows numerous libc-style functions:
                memset
                memcpy
                strcpy
                strncpy
                strcat
                strlen
        
        * call_handlers dict (global in the library) allows swapping in our python code in place of 
            calls to other binary code, like memcpy, or other code which may fail in an emulator

        '''
        emu = self.emu

        mcanv = e_memcanvas.StringMemoryCanvas(emu, syms=emu.vw)
        self.mcanv = mcanv  # store it for later inspection

        # set up tracedict
        if tracedict is None:
            tracedict = {}
        else:
            print("tracedict entries for %r" % (','.join(
                [hex(key) for key in tracedict.keys() if type(key) == int])))

        nonstop = 0
        tova = None
        quit = False
        moveon = False
        emuBranch = False
        silentUntil = None

        # set silentExcept to include all tracedict items
        silentExcept = [va for va, expr in tracedict.items() if expr is None]

        i = 0
        self.startRun = time.time()
        while maxstep > i:
            try:
                skip = skipop = False
                i += 1

                pc = emu.getProgramCounter()
                if pc in (runTil, finish):
                    print("PC reached 0x%x." % pc)
                    break

                op = emu.parseOpcode(pc)
                self.op = op  # store it for later in case of post-mortem

                # cancel emuBranch as we've come to one
                if op.isReturn() or op.isCall():
                    emuBranch = False

                #### TRACING
                tdata = tracedict.get(pc)
                if tdata is not None:
                    try:
                        lcls = locals()
                        outlcls = tracedict.get('locals')
                        if outlcls is not None:
                            lcls.update(outlcls)

                        print(repr(eval(tdata, globals(), lcls)))
                    except Exception as e:
                        print("TraceMonitor ERROR at 0x%x: %r" % (pc, e))

                ####

                if silentUntil == pc:
                    silent = False
                    silentUntil = None
                    self.printStats(i)

                if silent and not pc in silentExcept:
                    showafter = False
                else:
                    # do all the interface stuff here:
                    self.showPriRegisters(snapshot=SNAP_SWAP)
                    self.showFlags()  # ARM fails this right now.
                    try:
                        self.printMemStatus(op)
                    except Exception as e:
                        print("MEM ERROR: %s:    0x%x %s" % (e, op.va, op))
                        import traceback
                        traceback.print_exc()

                    print("Step: %s" % i)
                    mcanv.clearCanvas()
                    try:
                        op.render(mcanv)
                    except Exception as e:
                        print("ERROR rendering opcode: %r" % e)

                    extra = self.getNameRefs(op)

                    opbytes = emu.readMemory(pc, len(op))
                    print("%.4x\t%20s\t%s\t%s" %
                          (pc, hexlify(opbytes), mcanv.strval, extra))

                    print("---------")
                    prompt = "q<enter> - exit, eval code to execute, 'skip' an instruction, 'b'ranch, 'go [+]#' to va or +# instrs or enter to continue: "

                    # nonstop controls whether we stop.  tova indicates we're hunting for a va, otherwise
                    # treat nonstop as a negative-counter
                    if tova is not None:
                        if pc == tova:
                            nonstop = 0

                    elif nonstop:
                        nonstop -= 1

                    if not (emuBranch or nonstop) and pause:
                        tova = None
                        moveon = False

                        uinp = input(prompt)
                        while len(uinp) and not (moveon or quit or emuBranch):
                            try:
                                if uinp == "q":
                                    quit = True
                                    break

                                elif uinp.startswith('silent'):
                                    parts = uinp.split(' ')
                                    silentUntil = parseExpression(
                                        emu, parts[-1])
                                    silent = True

                                elif uinp.startswith('go '):
                                    args = uinp.split(' ')

                                    if args[-1].startswith('+'):
                                        nonstop = parseExpression(
                                            emu, args[-1])
                                    else:
                                        tova = parseExpression(emu, args[-1])
                                        nonstop = 1
                                    break

                                elif uinp in ('b', 'branch'):
                                    emuBranch = True
                                    break

                                elif uinp == 'stack':
                                    self.stackDump()
                                    moveon = True
                                    break

                                elif uinp == 'refresh':
                                    # basically does a NOP, doesn't change anything, just let the data be reprinted.
                                    moveon = True
                                    break

                                elif uinp.startswith('pc=') or uinp.startswith(
                                        'pc ='):
                                    print("handling setProgramCounter()")
                                    args = uinp.split('=')
                                    newpc = parseExpression(emu, args[-1])
                                    print("new PC: 0x%x" % newpc)
                                    emu.setProgramCounter(newpc)
                                    moveon = True
                                    break

                                elif '=' in uinp:
                                    print(
                                        "handling generic register/memory writes"
                                    )
                                    args = uinp.split('=')
                                    data = args[-1].strip(
                                    )  #   .split(',')  ??? why did i ever do this?

                                    if '[' in args[0]:
                                        # memory derefs
                                        tgt = args[0].replace('[', '').replace(
                                            ']', '').split(':')
                                        if len(tgt) > 1:
                                            size = parseExpression(
                                                emu, tgt[-1])
                                        else:
                                            size = 4

                                        addrstr = tgt[0]
                                        memaddr = parseExpression(emu, addrstr)

                                        if data.startswith(
                                                '"') and data.endswith('"'):
                                            # write string data
                                            emu.writeMemory(
                                                memaddr, data[1:-1])
                                        else:
                                            # write number
                                            emu.writeMemValue(
                                                memaddr,
                                                parseExpression(emu, data),
                                                size)

                                    else:
                                        # must be registers
                                        emu.setRegisterByName(
                                            args[0],
                                            parseExpression(emu, data))

                                elif uinp.strip().startswith(
                                        '[') and ']' in uinp:
                                    try:
                                        idx = uinp.find('[') + 1
                                        eidx = uinp.find(']', idx)
                                        expr = uinp[idx:eidx]
                                        print("handling memory read at [%s]" %
                                              expr)
                                        size = emu.getPointerSize()
                                        if ':' in expr:
                                            nexpr, size = expr.rsplit(':', 1)
                                            try:
                                                size = parseExpression(
                                                    emu, size)
                                                expr = nexpr
                                            except Exception as e:
                                                # if number fails, just continue with a default size and the original expr
                                                print(
                                                    "unknown size: %r.  using default size."
                                                    % size)

                                        va = parseExpression(emu, expr)
                                        data = emu.readMemory(va, size)
                                        print("[%s:%s] == %r" %
                                              (expr, size, data.hex()))
                                    except Exception as e:
                                        print("ERROR: %r" % e)

                                elif uinp == 'skip':
                                    newpc = emu.getProgramCounter() + len(op)
                                    print("new PC: 0x%x" % newpc)
                                    skipop = True
                                    break

                                elif uinp == 'memset':
                                    print(memset(emu))
                                    skipop = True
                                elif uinp == 'memcpy':
                                    print(memcpy(emu))
                                    skipop = True
                                elif uinp == 'strcpy':
                                    print(strcpy(emu))
                                    skipop = True
                                elif uinp == 'strncpy':
                                    print(strncpy(emu))
                                    skipop = True
                                elif uinp == 'strcat':
                                    print(strcat(emu))
                                    skipop = True
                                elif uinp == 'strlen':
                                    print(strlen(emu))
                                    skipop = True
                                else:
                                    try:
                                        lcls = locals()
                                        lcls.update(emu.getRegisters())
                                        out = eval(uinp, globals(), lcls)
                                        if type(out) == int:
                                            print(hex(out))
                                        else:
                                            print(out)
                                    except:
                                        import sys
                                        sys.excepthook(*sys.exc_info())

                            except:
                                traceback.print_exc()

                            #self.printStats(i)
                            uinp = input(prompt)

                if quit:
                    print("Quitting!")
                    self.printStats(i)
                    return

                if moveon:
                    continue

                # handle Calls separately
                if len(op.opers) and op.iflags & (envi.IF_CALL) and not skipop:
                    self.dbgprint("Call...")
                    tva = op.getOperValue(0, emu)
                    handler = self.call_handlers.get(tva)
                    self.dbgprint(" handler for call to (0x%x): %r" %
                                  (tva, handler))
                    if handler is not None:
                        handler(emu, op)
                        skipop = True

                    elif follow and not skip and not skipop:
                        # use the emulator to execute the call
                        starteip = emu.getProgramCounter()
                        if hasattr(emu, 'emumon') and emu.emumon is not None:
                            emu.emumon.prehook(emu, op, starteip)

                        emu.executeOpcode(op)
                        endeip = emu.getProgramCounter()
                        i += 1
                        if hasattr(emu, 'emumon') and emu.emumon is not None:
                            emu.emumon.posthook(emu, op, endeip)

                        self.dbgprint(
                            "starteip: 0x%x, endeip: 0x%x  -> %s" %
                            (starteip, endeip, emu.vw.getName(endeip)))
                        if hasattr(emu, 'curpath'):
                            vg_path.getNodeProp(emu.curpath,
                                                'valist').append(starteip)
                        skip = True

                # if not already emulated a call, execute the instruction here...
                if not skip and not skipop:
                    emu.stepi()

                    # print the updated latest stuff....
                    if showafter:
                        try:
                            extra = self.getNameRefs(op)
                            if len(extra):
                                print("after:\t%s\t%s" % (mcanv.strval, extra))

                            self.printMemStatus(op, use_cached=True)
                        except Exception as e:
                            print("MEM ERROR: %s:    0x%x %s" % (e, op.va, op))
                            import sys
                            sys.excepthook(*sys.exc_info())

                # unless we've asked to skip the instruction...
                elif skipop:
                    newpc = emu.getProgramCounter() + len(op)
                    emu.setProgramCounter(newpc)

            except KeyboardInterrupt:
                self.printStats(i)
                break

            except envi.SegmentationViolation:
                import sys
                sys.excepthook(*sys.exc_info())
                break

            except:
                import sys
                sys.excepthook(*sys.exc_info())

        self.printStats(i)
Exemple #19
0
    def __init__(self):
        QDialog.__init__(self)

        self.modes = [
            'ascii', 'hex', 'regex', 'utf-8', 'utf-16-le', 'utf-16-be'
        ]
        self.pattern = None
        self.filename = None

        rend = e_render.ByteRend()
        self.canvas = e_canvas.StringMemoryCanvas(None)
        self.canvas.addRenderer('bytes', rend)

        hbox1 = QHBoxLayout()
        mode_label = QLabel('Input: ')
        self.mode_combo = QComboBox()
        self.mode_combo.addItems(self.modes)
        self.mode_combo.currentIndexChanged.connect(self.encodingChanged)
        hbox1.addWidget(mode_label)
        hbox1.addWidget(self.mode_combo, alignment=QtCore.Qt.AlignLeft)
        hbox1.addStretch(1)

        hbox2 = QHBoxLayout()
        data_label = QLabel('Bytes: ')
        self.data_edit = QLineEdit()
        hbox2.addWidget(data_label)
        hbox2.addWidget(self.data_edit)

        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)

        gbox1 = QGroupBox('Search Criteria')
        gbox1.setLayout(vbox1)

        hbox3 = QHBoxLayout()
        vbox_hex_label = QVBoxLayout()  # for align to top.
        hex_label = QLabel('Hex:   ')
        vbox_hex_label.addWidget(hex_label, alignment=QtCore.Qt.AlignTop)
        self.hex_edit = QPlainTextEdit()
        self.hex_edit.setReadOnly(True)
        font = QtGui.QFont('Courier')  # should use actual memcanvas.
        self.hex_edit.setFont(font)
        hbox3.addLayout(vbox_hex_label)
        hbox3.addWidget(self.hex_edit)

        vbox2 = QVBoxLayout()
        vbox2.addLayout(hbox3)

        gbox2 = QGroupBox('Bytes to Search For')
        gbox2.setLayout(vbox2)

        hbox4 = QHBoxLayout()
        save_check = QCheckBox('Save Search Results')
        save_check.stateChanged.connect(self.checkChanged)
        self.fname_label = QLabel('')
        buttons = QDialogButtonBox()
        buttons.setStandardButtons(QDialogButtonBox.Cancel
                                   | QDialogButtonBox.Ok)
        buttons.accepted.connect(self.okClicked)
        buttons.rejected.connect(self.cancelClicked)
        hbox4.addWidget(save_check)
        hbox4.addWidget(self.fname_label)
        hbox4.addWidget(buttons)

        vbox = QVBoxLayout()
        vbox.addWidget(gbox1)
        vbox.addWidget(gbox2)
        vbox.addLayout(hbox4)

        self.setLayout(vbox)

        self.setWindowTitle('Memory Search')
        self.resize(650, 300)
        self.data_edit.setFocus()