예제 #1
0
 def handle_mov(self, state):
     """Updates the state of the stack string finding based on a mov instruction"""
     op1 = tracing.get_opnd_replacement(state.ea, POS_FIRST)
     if "[" in op1:
         offset = tracing.get_operand_value_replacement(state.ea, POS_FIRST, state)
         self.set_stack(offset, state.ea, POS_SECOND, state)
     else:
         reg = tracing.get_reg_fam(op1)
         type_ = idc.get_operand_type(state.ea, POS_SECOND)
         if reg:
             if type_ != idc.o_phrase and type_ != idc.o_displ:
                 if type_ == idc.o_reg:
                     reg2 = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_SECOND))
                     if reg2 and reg2[0] in state.regs:
                         val = state.regs[reg2[0]][0]
                     else:
                         val = None
                 else:
                     val = idc.get_operand_value(state.ea, POS_SECOND)
                 if val is not None:
                     state.regs[reg[0]] = (val, state.ea)
             else:
                 offset = tracing.get_operand_value_replacement(state.ea, POS_SECOND, state)
                 value = state.stack.get(offset, None)
                 if value is not None:
                     state.regs[reg[0]] = value
                 else:
                     self.clear_reg_if_needed(reg, state.regs)
예제 #2
0
 def handle_lea(self, state):
     """Updates the state of the stack string finding based on an lea instruction"""
     if idc.get_operand_type(state.ea, POS_SECOND) == idc.o_reg:
         source_reg = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_SECOND))
         if source_reg and source_reg[0] in state.regs:
             value = state.regs[source_reg[0]]
         else:
             value = None
     else:
         value = tracing.get_operand_value_replacement(state.ea, POS_SECOND, state)
     if value is not None and value in state.stack:
         self.report_strings(state.strs, state.stack)
     self.clear_reg_if_needed(tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_FIRST)), state.regs)
예제 #3
0
 def set_stack(self, offset, ea, pos, state):
     """
     Sets the stack dictionary, at the given offset, to contain the value at the given position at the given ea,
     performing a lookup in the register dictionary if needed.
     """
     fill = False
     if idc.get_operand_type(ea, pos) == idc.o_imm:
         val = idc.get_operand_value(ea, pos)
         state.stack[offset] = (val, ea)
         fill = True
     else:
         reg = tracing.get_reg_fam(tracing.get_opnd_replacement(ea, pos))
         if reg and reg[0] in state.regs:
             val = state.regs[reg[0]][0]
             state.stack[offset] = (state.regs[reg[0]][0], ea)
             fill = True
     if fill:
         for i in range(0, tracing.get_byte_size_of_operand(ea, pos)):
             state.stack[offset + i] = (val & 0xFF, ea)
             val //= 256
예제 #4
0
    def get_stack_strings(self, functions):
        """
        Finds all the stack strings it can in the given functions.

        Parameters set globally:
            STRING_GAP_TOLERANCE - the gap allowed between string characters.
            MAX_CHARACTER_WIDTH  - the maximum character size, in bytes
            ASCII                - Whether character values must be 0-127
        """
        stack_strings = []
        for func in functions:
            state = tracing.BranchingTraceState(func.start_ea)
            state.strs = set()
            states = [state]
            func_eas = []
            ea = state.ea
            while ea < func.end_ea:
                func_eas.append(ea)
                ea += idc.get_item_size(ea)
            while states:
                state = states.pop()
                while state.ea < func.end_ea:
                    try:
                        func_eas.remove(state.ea)
                    except:
                        pass
                    state.visited_eas.append(state.ea)
                    mnemonic = idc.print_insn_mnem(state.ea)
                    if mnemonic in IGNORED_MNEMONICS:
                        pass
                    elif "pop" in mnemonic:
                        reg = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_FIRST))
                        if reg:
                            value = state.stack.get(idc.get_spd(state.ea), None)
                            if value is not None:
                                state.regs[reg[0]] = value
                            else:
                                self.clear_reg_if_needed(reg, state.regs)
                    elif "push" in mnemonic:
                        # bug where idc.get_spd was not correctly tracking the pointer,
                        # this case also hasn't really been seen often as part of a stack string
                        # self.set_stack(idc.get_spd(ea), ea, POS_FIRST, regs, stack)
                        pass
                    elif "mov" in mnemonic:
                        self.handle_mov(state)
                    elif (
                        (
                            "xor" in mnemonic
                            and tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_FIRST))
                            == tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_SECOND))
                        )
                        or ("lea" in mnemonic and idc.print_operand(state.ea, POS_SECOND) == "[0]")
                        or (
                            "sub" in mnemonic
                            and tracing.get_opnd_replacement(state.ea, POS_FIRST)
                            == tracing.get_opnd_replacement(state.ea, POS_SECOND)
                        )
                    ):
                        reg = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_FIRST))
                        if reg:
                            state.regs[reg[0]] = (0, state.ea)
                    elif "loop" in mnemonic or "movsb" in mnemonic:
                        state.regs["rcx"] = (0, state.ea)
                    elif mnemonic in JUMPS:
                        try:
                            target = next(idautils.CodeRefsFrom(state.ea, 0))
                        except StopIteration:
                            target = None
                        if target and target not in state.visited_eas:
                            if func.end_ea > target >= func.start_ea:
                                state.visited_eas.append(target)
                                new_state = tracing.BranchingTraceState(target, state)
                                new_state.strs = state.strs
                                states.append(new_state)
                            else:
                                self.report_strings(state.strs, state.stack)
                        # Always follow an unconditional jump
                        if mnemonic == "jmp":
                            break
                    elif (
                        "rep" in idc.GetDisasm(state.ea).split(" ")[0]
                        and "scas" not in idc.GetDisasm(state.ea).split(" ")[1]
                    ):
                        self.report_strings(state.strs, state.stack)
                    elif "lea" in mnemonic:
                        self.handle_lea(state)
                    elif "call" in mnemonic:
                        self.handle_call(state)
                    elif "ret" in mnemonic:
                        break
                    elif (
                        idc.get_operand_type(state.ea, POS_FIRST) == idc.o_reg
                    ):  # If we find a target register we were tracking, stop tracking it.
                        self.clear_reg_if_needed(
                            tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_FIRST)), state.regs
                        )
                    state.ea += idc.get_item_size(state.ea)
                self.report_strings(state.strs, state.stack)
                if not states and func_eas:
                    new_state = tracing.BranchingTraceState(func_eas[0])
                    new_state.strs = set()
                    states.append(new_state)
                stack_strings.extend(state.strs)
        self.strings.update(stack_strings)