Esempio n. 1
0
def has_locals(ea, lvar_size=1, count_from_first_var=False):
    frame = idaapi.get_frame(ea)

    if frame is None or frame.memqty <= 1:
        return False
    
    if count_from_first_var:
        sida = frame.id
        offset = idc.GetFirstMember(sida)
        return idc.GetFrameLvarSize(ea) > lvar_size+offset
    else:
        return idc.GetFrameLvarSize(ea) > lvar_size
Esempio n. 2
0
def stringify():
    ea = idc.here()
    size_data = get_bitness_bytes(ea)
    f = idaapi.get_func(ea)
    frsize = idc.GetFrameLvarSize(ea)
    position = f.startEA
    size = 0
    while position < f.endEA:
        instr = idautils.DecodeInstruction(position)
        if instr is None:
            print("%x: Not and instruction found" % position)
            break
        mnem = instr.get_canon_mnem()
        if mnem == "mov":
            if instr.Op2.type == idaapi.o_imm and instr.Op1.type == idaapi.o_reg:  #this may be string load
                is_string, size_s = is_this_a_real_string(
                    position + instr.size, instr, size_data)
                if is_string is True:
                    make_string(instr.Op2.value, size_s)
        elif mnem == "lea":
            if instr.Op2.type == idaapi.o_mem and instr.Op1.type == idaapi.o_reg:
                is_string, size_s = is_this_a_real_string(
                    position + instr.size, instr, size_data)
                if is_string is True:
                    make_string(instr.Op2.addr, size_s)
        position += instr.size
Esempio n. 3
0
def walk_members(ea):
    global num_stackframes, num_default_stackframe_members
    frame = idaapi.get_frame(ea)
    if not frame:
        return
    num_stackframes += 1
    sid = frame.id
    s = idaapi.get_struc(sid)
    if s is None or s == idaapi.BADADDR:
        return
    known = set()
    base = idc.GetFrameLvarSize(ea)
    for idx in xrange(0, s.memqty):
        ea = yatools.get_struc_member_by_idx(s, idx)
        if ea in known:
            continue
        m = idaapi.get_member(frame, ea)
        if not m or idaapi.is_special_member(m.id):
            continue
        is_data = m.flag == idaapi.FF_DATA
        is_default_name = idc.GetMemberName(
            sid, ea) == get_default_struc_member_name(False, ea, base)
        size = idaapi.get_member_size(m)
        no_comment = is_nil(idaapi.get_member_cmt(m.id, 0))
        no_repeated = is_nil(idaapi.get_member_cmt(m.id, 1))
        if not s.is_union(
        ) and is_data and size == 1 and is_default_name and no_comment and no_repeated:
            num_default_stackframe_members += 1
            continue
        if m and not idaapi.is_special_member(m.id):
            known.add(ea)
            yield m
Esempio n. 4
0
    def factory(cls, string_location, string_reference, size=INVALID, offset=INVALID, key=INVALID):
        """
        Factory function to generate an EncodedString or EncodedStackString based on type.

        :param string_location:
            Data segment pointer for static strings or stack pointer for stack strings.
        :param string_reference:
            The location the string is referenced from.
            This is required to pull the stack frame when string_location is a stack pointer.
        :param size: The size of the string. Required to use self.get_bytes.
        :param offset: Used when there is an offset based accessing scheme.
        :param key: Used when there is a key that can vary by string.
        """
        if idc.isLoaded(string_location):
            return EncodedString(
                string_location, string_reference, size=size, offset=offset, key=key)

        # otherwise assume string_location is a pointer within the stack
        # (using function_tracingutils's CPU emulator) and create an EncodedStackString object.
        stack = idc.GetFrame(string_reference)
        # FIXME: This method isn't always super accurate because... IDA
        stack_offset = (
                string_location
                + function_tracingutils.RSP_OFFSET
                + idc.GetFrameLvarSize(string_reference)
                - function_tracingutils.STACK_BASE
        )

        return EncodedStackString(
            stack, stack_offset, string_reference=string_reference,
            size=size, offset=offset, key=key)
Esempio n. 5
0
def append_lvar_comment(fva, frame_offset, s, repeatable=False):
    '''
    add the given string as a (possibly repeatable) stack variable comment to the given function.
    does not add the comment if it already exists.
    adds the comment on its own line.

    Args:
      fva (int): the address of the function with the stack variable.
      frame_offset (int): the offset into the stack frame at which the variable is found.
      s (str): the comment text.
      repeatable (bool): if True, set a repeatable comment.

    Raises:
      UnicodeEncodeError: if the given string is not ascii.
    '''
    s = s.encode('ascii')

    stack = idc.GetFrame(fva)
    if not stack:
        raise RuntimeError('failed to find stack frame for function: ' +
                           hex(fva))

    lvar_offset = idc.GetFrameLvarSize(fva) - frame_offset
    if not lvar_offset:
        raise RuntimeError('failed to compute local variable offset')

    if lvar_offset <= 0:
        raise RuntimeError('failed to compute positive local variable offset')

    string = idc.GetMemberComment(stack, lvar_offset, repeatable)
    if not string:
        string = s
    else:
        if s in string:  # ignore duplicates
            return
        string = string + "\\n" + s

    if not idc.SetMemberComment(stack, lvar_offset, string, repeatable):
        raise RuntimeError('failed to set comment')
Esempio n. 6
0
 def locals_size(self):
     return idc.GetFrameLvarSize(self.func_addr)
Esempio n. 7
0
    def detect_prologue(self):
        """Check wheater the function prologue is present or not."""
        #
        # Common prologue is as follows:
        #
        # mflr    %r0                    ; if not leaf proc, get ret address
        # stwu    %sp, -0x1A8(%sp)       ; allocate stack space
        # stmw    %r28, 0x1A8+var_10(%sp); store temp regs
        # stw     %r0, 0x1A8+arg_4(%sp)  ; store ret address
        #
        try:
            # Check the instructions from the first basic block
            # to find common function prologue
            bb = self.lir_function[0]

            # Check only in the first three instructions
            for inst in bb:
                # STEP 1.A
                #
                # Check if it modifies %sp and get the number of allocated
                # bytes.
                if inst.analyzed:
                    continue

                if inst.type == self.iset.PPC_stwu and \
                    inst[0].is_reg_n(self.iset.SP) and \
                    inst[1].is_displ and \
                    inst[1].value[0] == self.iset.SP:

                    #
                    # Mark instruction as already analyzed and as part of the 
                    # standard prologue instruction to avoid output representation.
                    #
                    inst.analyzed = True
                    self.lir_function.add_prologue_address(inst.address)

                    # Add the stack size found.
                    stack_size = abs(self.get_signed_value( inst[1].value[1] ))
                    self.lir_function.stack_size = stack_size

                    break

            if self.lir_function.stack_size != 0:
                print "    Stack allocation found 0x%X (%d) bytes. Double check: " % \
                        (self.lir_function.stack_size,
                        self.lir_function.stack_size),

                # TODO: Check any difference with get_frame_size()
                frame_size = self.debugger.get_frame_size(inst.address)

                if self.lir_function.stack_size == frame_size:
                    print "OK"
                else:
                    print "INVALID (should be %d bytes)" % frame_size

            else:
                print "[-] Stack allocation NOT found. Using debugger detection:",

                # TODO : Remove IDA specific function call.
                frame_size = idc.GetFrameLvarSize(inst.address)
                self.lir_function.stack_size = frame_size
                print "OK (%d bytes)" % frame_size

            # STEP 1.B
            #
            # Obtain information about the method used to access
            # local variables.
            #
            # If we can't find a register used as a copy of sp, then
            # we asume IOS-style using SP like this:
            #
            #   add  rd, sp, imm
            #
            # TODO : why is there a slice in the enum below?
            for index, inst in enumerate(bb[1 : ], 1):
                # Start generating the high-level representation
                # of the current function to decompile the binary.
                # Indicate the prologue-related addresses to avoid
                # decompiling them.

                if inst.type == self.iset.PPC_mr and inst[1].is_reg_n(self.iset.SP):
                    # Seems that we've found an SP being moved to another
                    # register.
                    self.lir_function.add_prologue_address(inst.address)
                    self.lir_function.add_stack_access_register(inst[0].value)

                    # Mark the instruction but before stop looking, confirm the
                    # finding by looking for that store operation on that
                    # register (backup).
                    #
                    # 018000BC stw     %r31, 28(%sp) ; Find this STW given
                    # 018000C0 mr      %r31, %sp     ;  this MR instruction.
                    #
                    # TODO: stack pointer definition !!!!!!!!!!!!!
                    inst.analyzed = True

                    for i in bb[index : 0 : -1]:  # walk backwards.

                        op0_value = i[0].value

                        if i.type in [self.iset.PPC_stw, self.iset.PPC_stwu] and \
                            op0_value in self.lir_function.stack_access_registers:

                            # Stack register backup operation found
                            i.analyzed = True
                            self.lir_function.add_prologue_address(i.address)
                    break

            # Output stack access information found.
            stack_access_registers = self.lir_function.stack_access_registers
            stack_access_registers = [
                self.iset.GPR_NAMES[r] for r in stack_access_registers]

            if self.iset.SP in self.lir_function.stack_access_registers:
                stack_access_type = "    Stack accessed via stack-pointer: "
            else:
                stack_access_type = "    Stack accessed via frame-pointer: "

            print "%s %s" % (stack_access_type, ", ".join(stack_access_registers))

            # STEP 2
            # Another instruction should save %lr in case we aren't processing
            # a leaf procedure.
            # Look for the second isntruction of this sequence:
            #
            # mflr    %r0
            # ...
            # stw     %r0, 0xE0+arg
            for inst in bb:

                if inst.analyzed or not inst.type == self.iset.PPC_mflr:
                    continue

                lr_backup_reg = inst[0].value # dest reg for %lr
                lr_store_found = False              # flag
                inst.analyzed = True

                self.lir_function.add_prologue_address(inst.address)

                # Check only in the first n instructions
                for inst in bb:

                    if inst.analyzed:
                        continue

                    if inst.type == self.iset.PPC_stw and \
                        inst[0].is_reg_n(lr_backup_reg):

                        # Found LR store operation from previous move
                        self.lir_function.add_prologue_address(inst.address)
                        inst.analyzed = True

                        lr_store_found = True
                        self.lir_function.leaf_procedure = False

                        break

                if not lr_store_found:
                    raise PowerPc32GccIdiomAnalyzerException(
                        "Could not locate link register backup instruction")

            if self.lir_function.leaf_procedure is True:
                print "    Current function is a leaf procedure."
            else:
                print "    Current function is NOT a leaf procedure."

        except MiddleIrException, err:
            print format_exc() + '\n'

            raise PowerPc32GccIdiomAnalyzerException(err)