Ejemplo n.º 1
0
def parse_function_args(ea: int) -> str:
    local_variables = []
    arguments = []
    current = local_variables

    frame = idc.get_func_attr(ea, FUNCATTR_FRAME)
    arg_string = ""
    if frame is None:
        return ""

    start = idc.get_first_member(frame)
    end = idc.get_last_member(frame)
    count = 0
    max_count = 10000
    args_str = ""
    while start <= end and count <= max_count:
        size = idc.get_member_size(frame, start)
        count = count + 1
        if size is None:
            start = start + 1
            continue

        name = idc.get_member_name(frame, start)
        start += size

        if name in [" r", " s"]:
            # Skip return address and base pointer
            current = arguments
            continue
        arg_string += f" {name}"
        current.append(name)
    args_str = ", ".join(arguments)
    if len(args_str) == 0:
        args_str = "void"
    return f"({args_str})"
Ejemplo n.º 2
0
 def name(self):
     if self.is_stack:
         name = idc.get_member_name(self.frame_id, self.stack_offset)
     else:
         name = idc.get_name(self.addr)
     if not name:
         return ''
     return name
Ejemplo n.º 3
0
def build_stack_variable(func_ea):
  stack_vars = dict()

  frame = idc.get_func_attr(func_ea, idc.FUNCATTR_FRAME)
  if not frame:
    return stack_vars

  f_name = get_symbol_name(func_ea)
  #grab the offset of the stored frame pointer, so that
  #we can correlate offsets correctly in referent code
  # e.g., EBP+(-0x4) will match up to the -0x4 offset
  delta = idc.GetMemberOffset(frame, " s")
  if delta == -1:
    delta = 0

  if f_name not in _FUNC_UNSAFE_LIST:
    offset = idc.get_first_member(frame)
    while -1 != _signed_from_unsigned(offset):
      member_name = idc.get_member_name(frame, offset)
      if member_name is None:
        offset = idc.get_next_offset(frame, offset)
        continue
      if (member_name == " r" or member_name == " s"):
        offset = idc.get_next_offset(frame, offset)
        continue

      member_size = idc.GetMemberSize(frame, offset)
      if offset >= delta:
        offset = idc.get_next_offset(frame, offset)
        continue

      member_flag = idc.GetMemberFlag(frame, offset)
      flag_str = _get_flags_from_bits(member_flag)
      member_offset = offset-delta
      stack_vars[member_offset] = {"name": member_name,
                                  "size": member_size,
                                  "flags": flag_str,
                                  "writes": list(),
                                  "referent": list(),
                                  "reads": list(),
                                  "safe": False }

      offset = idc.get_next_offset(frame, offset)
  else:
    offset = idc.get_first_member(frame)
    frame_size = idc.get_func_attr(func_ea, idc.FUNCATTR_FRSIZE)
    flag_str = ""
    member_offset = _signed_from_unsigned(offset) - delta
    stack_vars[member_offset] = {"name": f_name,
                                 "size": frame_size,
                                 "flags": flag_str,
                                 "writes": list(),
                                 "referent": list(),
                                 "reads": list(),
                                 "safe": False }

  return stack_vars
Ejemplo n.º 4
0
def build_stack_variable(func_ea):
  stack_vars = dict()

  frame = idc.get_func_attr(func_ea, idc.FUNCATTR_FRAME)
  if not frame:
    return stack_vars

  f_name = get_symbol_name(func_ea)
  #grab the offset of the stored frame pointer, so that
  #we can correlate offsets correctly in referent code
  # e.g., EBP+(-0x4) will match up to the -0x4 offset
  delta = idc.GetMemberOffset(frame, " s")
  if delta == -1:
    delta = 0

  if f_name not in _FUNC_UNSAFE_LIST:
    offset = idc.get_first_member(frame)
    while -1 != _signed_from_unsigned(offset):
      member_name = idc.get_member_name(frame, offset)
      if member_name is None:
        offset = idc.get_next_offset(frame, offset)
        continue
      if (member_name == " r" or member_name == " s"):
        offset = idc.get_next_offset(frame, offset)
        continue

      member_size = idc.GetMemberSize(frame, offset)
      if offset >= delta:
        offset = idc.get_next_offset(frame, offset)
        continue

      member_flag = idc.GetMemberFlag(frame, offset)
      flag_str = _get_flags_from_bits(member_flag)
      member_offset = offset-delta
      stack_vars[member_offset] = {"name": member_name,
                                  "size": member_size,
                                  "flags": flag_str,
                                  "writes": list(),
                                  "referent": list(),
                                  "reads": list(),
                                  "safe": False }

      offset = idc.get_next_offset(frame, offset)
  else:
    offset = idc.get_first_member(frame)
    frame_size = idc.get_func_attr(func_ea, idc.FUNCATTR_FRSIZE)
    flag_str = ""
    member_offset = _signed_from_unsigned(offset) - delta
    stack_vars[member_offset] = {"name": f_name,
                                 "size": frame_size,
                                 "flags": flag_str,
                                 "writes": list(),
                                 "referent": list(),
                                 "reads": list(),
                                 "safe": False }

  return stack_vars
Ejemplo n.º 5
0
 def add_member(self, offset, name, size):
     if get_member_name(self._sid, 0) == "Dummy":
         del_struc_member(self._sid, 0)
     flag = {1: FF_BYTE, 2: FF_WORD, 4: FF_DWORD, 8: FF_QWORD}.get(size)
     if flag is None:
         raise ValueError("size")
     err_code = add_struc_member(self._sid, name, offset, flag | FF_DATA,
                                 -1, size)
     if err_code != 0:
         raise Exception("err_code = %d" % err_code)
Ejemplo n.º 6
0
    def get_struc_name(self):

        x = self.target.operands['x']
        m = self.target.operands['m']

        xtype = x.type
        xtype.remove_ptr_or_array()
        typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')

        sid = idc.get_struc_id(typename)
        member = idc.get_member_name(sid, m)

        return '%s::%s' % (typename, member)
Ejemplo n.º 7
0
    def get_struc_name(self):

        x = self.target.operands['x']
        m = self.target.operands['m']

        xtype = x.type
        xtype.remove_ptr_or_array()
        typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '',
                                      '')

        sid = idc.get_struc_id(typename)
        member = idc.get_member_name(sid, m)

        return '%s::%s' % (typename, member)
Ejemplo n.º 8
0
def loadMembersIDA7(struc, sid):
    '''Returns list of tuples of (offset, memberName, member)'''
    #mixing idc & idaapi, kinda annoying but need low-level idaapi for a
    # type access, but cant dig into structs...
    members = []
    off = idaapi.get_struc_first_offset(struc)
    while off != idc.BADADDR:
        logger.debug('struc offset: 0x%x (%d)', off, off)
        member = idaapi.get_member(struc, off)
        if (member == 0) or (member is None):
            pass  #not really an error, i guess
        else:
            members.append((off, idc.get_member_name(sid, off), member))
        off = idaapi.get_struc_next_offset(struc, off)
    members.sort(key=lambda mem: mem[0])
    return members
Ejemplo n.º 9
0
def loadMembersIDA7(struc, sid):
    '''Returns list of tuples of (offset, memberName, member)'''
    #mixing idc & idaapi, kinda annoying but need low-level idaapi for a 
    # type access, but cant dig into structs...
    members = []
    off = idaapi.get_struc_first_offset(struc) 
    while off != idc.BADADDR:
        logger.debug('struc offset: 0x%x (%d)', off, off)
        member = idaapi.get_member(struc, off)
        if (member == 0) or (member is None):
            pass    #not really an error, i guess
        else:
            members.append( (off, idc.get_member_name(sid, off), member) )
        off = idaapi.get_struc_next_offset(struc, off )
    members.sort(key = lambda mem: mem[0])
    return members
Ejemplo n.º 10
0
def get_stackVariables(func_addr):
    #print func_addr
    args = []
    stack = idc.get_frame_id(func_addr)
    if not stack:
            return 0
    firstM = idc.get_first_member(stack)
    lastM = idc.get_last_member(stack)
    i = firstM
    while i <=lastM:
        mName = idc.get_member_name(stack,i)
        mSize = idc.get_member_size(stack,i)
        if mSize:
                i = i + mSize
        else:
                i = i+4
        if mName not in args and mName and 'var_' in mName:
            args.append(mName)
    return len(args)
Ejemplo n.º 11
0
def get_stack_arg(func_addr):
    print func_addr
    args = []
    stack = idc.get_frame_id(func_addr)
    if not stack:
        return []
    firstM = idc.get_first_member(stack)
    lastM = idc.get_last_member(stack)
    i = firstM
    while i <= lastM:
        mName = idc.get_member_name(stack, i)
        mSize = idc.get_member_size(stack, i)
        if mSize:
            i = i + mSize
        else:
            i = i + 4
        if mName not in args and mName and ' s' not in mName and ' r' not in mName:
            args.append(mName)
    return args
Ejemplo n.º 12
0
def StructMembers(sid):
    """
    Get a list of structure members information (or stack vars if given a frame).

    @param sid: ID of the structure.

    @return: List of tuples (offset, name, size)

    @note: If 'sid' does not refer to a valid structure,
           an exception will be raised.
    @note: This will not return 'holes' in structures/stack frames;
           it only returns defined structure members.
    """
    m = idc.get_first_member(sid)
    if m == -1:
        raise Exception("No structure with ID: 0x%x" % sid)
    while (m != ida_idaapi.BADADDR):
        name = idc.get_member_name(sid, m)
        if name:
            yield (m, name, idc.get_member_size(sid, m))
        m = idc.get_next_offset(sid, m)
Ejemplo n.º 13
0
def StructMembers(sid):
    """
    Get a list of structure members information (or stack vars if given a frame).

    @param sid: ID of the structure.

    @return: List of tuples (offset, name, size)

    @note: If 'sid' does not refer to a valid structure,
           an exception will be raised.
    @note: This will not return 'holes' in structures/stack frames;
           it only returns defined structure members.
    """
    sptr = ida_struct.get_struc(sid)
    if sptr is None:
        raise Exception("No structure with ID: 0x%x" % sid)
    for m in sptr.members:
        name = idc.get_member_name(sid, m.soff)
        if name:
            size = ida_struct.get_member_size(m)
            yield (m.soff, name, size)
Ejemplo n.º 14
0
def get_member_name(sid, cur_offset):
    if idaapi.IDA_SDK_VERSION <= 699:
        mn = idc.GetMemberName(sid, cur_offset)
    else:
        mn = idc.get_member_name(sid, cur_offset)
    return mn
Ejemplo n.º 15
0
    def fill_function(self, ida_func, user=None, state=None):
        """
        Grab all relevant information from the specified user and fill the @ida_func.
        """

        # == function name === #
        _func = self.pull_function(ida_func, user=user, state=state)
        if _func is None:
            return

        if compat.get_func_name(ida_func.start_ea) != _func.name:
            compat.set_ida_func_name(ida_func.start_ea, _func.name)

        # === comments === #
        # set the func comment
        func_comment = self.pull_comment(_func.addr, user=user, state=state)
        if func_comment is None:
            func_comment = ""
            #idc.set_func_cmt(_func.addr, func_comment, 1)
            #compat.set_ida_comment(_func.addr, func_comment, 1, func_cmt=True)

        # set the disassembly comments
        func_cmt_end = "\n"
        for start_ea, end_ea in idautils.Chunks(ida_func.start_ea):
            for head in idautils.Heads(start_ea, end_ea):
                if head == _func.addr:
                    continue

                comment = self.pull_comment(head, user=user, state=state)
                if comment is not None:
                    func_cmt_end += f"\n{hex(head)}: {comment}"
                    #compat.set_decomp_comments(_func.addr, {head: comment})
                    #compat.set_ida_comment(head, comment, 0, func_cmt=False)
        func_comment += func_cmt_end
        compat.set_ida_comment(_func.addr, func_comment, 1, func_cmt=True)

        # === stack variables === #
        existing_stack_vars = {}
        frame = idaapi.get_frame(ida_func.start_ea)
        if frame is None or frame.memqty <= 0:
            _l.debug(
                "Function %#x does not have an associated function frame. Skip variable name sync-up.",
                ida_func.start_ea)
            return

        frame_size = idc.get_struc_size(frame)
        last_member_size = idaapi.get_member_size(
            frame.get_member(frame.memqty - 1))

        for i in range(frame.memqty):
            member = frame.get_member(i)
            stack_offset = member.soff - frame_size + last_member_size
            existing_stack_vars[stack_offset] = member

        for offset, stack_var in self.pull_stack_variables(
                ida_func, user=user, state=state).items():
            ida_offset = stack_var.get_offset(StackOffsetType.IDA)
            # skip if this variable already exists
            if ida_offset in existing_stack_vars:
                type_str = self._get_type_str(
                    existing_stack_vars[ida_offset].flag)
            else:
                type_str = None

            if ida_offset in existing_stack_vars:
                if idc.get_member_name(frame.id, existing_stack_vars[ida_offset].soff) == stack_var.name \
                        and type_str is not None \
                        and stack_var.type == type_str:
                    continue
                # rename the existing variable
                idaapi.set_member_name(frame,
                                       existing_stack_vars[ida_offset].soff,
                                       stack_var.name)
                # TODO: retype the existing variable

        # ===== update the psuedocode ==== #
        compat.refresh_pseudocode_view(_func.addr)
Ejemplo n.º 16
0
def test_cpu_context():
    """Tests function_tracer and and cpu_context."""
    import idc

    from kordesii.utils import function_tracing

    # Test on encryption function.
    tracer = function_tracing.get_tracer(0x00401024)
    context = tracer.context_at(0x00401024)

    operands = context.operands
    assert len(operands) == 2
    assert operands[0].text == '[ebp+arg_0]'
    assert operands[0].value == 0
    # arg_0 should be 8 bytes from stack pointer.
    assert operands[0].addr == context.registers.esp + 8 == 0x117f804
    assert operands[1].text == 'eax'
    assert operands[1].value == context.registers.eax == 1

    # Test get_original_location()
    # context = tracer.context_at(0x00401017)
    # data_ptr = context.registers.edx
    data_ptr = operands[0].addr
    assert context.get_variable_name(data_ptr) == '$ F401000.arg_0'
    ip, orig_location = context.get_original_location(data_ptr)
    assert ip is None  # ip is None, because arg_0 never gets copied explicictly.
    assert isinstance(orig_location, tuple)
    frame_id, stack_offset = orig_location
    assert idc.get_member_name(frame_id, stack_offset) == 'arg_0'

    # Now execute this instruction and see if arg_0 has be set with the 1 from eax.
    context.execute(context.ip)
    assert operands[0].value == 1

    # Test getting all possible values passed into arg_0 using using depth.
    strings = []
    for context in tracer.iter_context_at(0x00401003, depth=1):
        assert context.ip == 0x00401003
        # mov     eax, [ebp+arg_0]
        strings.append(context.read_data(context.operands[1].value))
    assert strings == [
        'Idmmn!Vnsme ', 'Vgqv"qvpkle"ukvj"ig{"2z20',
        'Wkf#rvj`h#aqltm#el{#ivnsp#lufq#wkf#obyz#gld-',
        'Keo$mw$wpvkjc$ej`$ehwk$cmraw$wle`a*',
        'Dfla%gpwkv%mji`v%lk%rjji%fijqm+',
        'Egru&ghb&biau&cgen&ngrc&rnc&irnct(',
        '\\cv}3g{v3pargv3qfg3w|}4g3qavrx3g{v3t\x7fr``=',
        'C\x7frer7c\x7fr7q{xxs7zve|7~d7cry7~yt\x7frd9', '+()./,-"#*',
        '`QFBWFsQL@FPPb', 'tSUdFS', '\x01\x13\x10n\x0e\x05\x14',
        '-",5 , v,tr4v,trv4t,v\x7f,ttt', '@AKJDGBA@KJGDBJKAGDC',
        '!\x1d\x10U\x05\x14\x06\x01U\x02\x1c\x19\x19U\x19\x1a\x1a\x1eU\x17\x07\x1c\x12\x1d\x01\x10\x07U\x01\x1a\x18\x1a\x07\x07\x1a\x02[',
        '4\x16\x05\x04W\x16\x19\x13W\x15\x02\x04\x04\x12\x04W\x04\x03\x16\x1b\x1b\x12\x13W\x1e\x19W\x04\x16\x19\x13W\x13\x05\x1e\x11\x03\x04Y',
        '.\x12\x1fZ\x10\x1b\x19\x11\x1f\x0eZ\x12\x0f\x14\x1dZ\x15\x14Z\x0e\x12\x1fZ\x18\x1b\x19\x11Z\x15\x1cZ\x0e\x12\x1fZ\r\x13\x1e\x1fZ\x19\x12\x1b\x13\x08T',
        'LMFOGHKNLMGFOHKFGNLKHNMLOKGNKGHFGLHKGLMHKGOFNMLHKGFNLMJNMLIJFGNMLOJIMLNGFJHNM'
    ]

    # Test pulling arguments from a call.
    tracer = function_tracing.get_tracer(0x0040103A)

    context = tracer.context_at(0x0040103A)
    operands = context.operands
    assert len(operands) == 1
    assert operands[0].is_func_ptr
    assert operands[0].value == 0x00401000
    # First, attempt to pull the arguments from the stack without get_function_args()
    first_arg_ptr = context.read_data(context.registers.esp,
                                      data_type=function_tracing.DWORD)
    second_arg = context.read_data(context.registers.esp + 4,
                                   data_type=function_tracing.BYTE)
    assert context.read_data(first_arg_ptr) == "Idmmn!Vnsme "
    assert second_arg == 1
    # Now try with get_function_args()
    args = context.get_function_args()
    assert len(args) == 2
    assert context.read_data(args[0]) == "Idmmn!Vnsme "
    assert args[1] == 1
Ejemplo n.º 17
0
 def name(self):
     return get_member_name(self._sid, self._offset)