def yatest_create_struct_in_stack_vars_with_renaming(self): """ test creation of struct from stack vars used to find a bug (structure is correctly applied on var if renamed) """ # create structure ident, sida = self.get_function_sid_without_del( True, local_size=complex_struc3_size, count_from_first_var=True) self.assertNotEqual(sida, -1) sidb = idc.AddStrucEx(0, 'create_struct_in_stack_vars_with_renaming', 0) self.assertNotEqual(sidb, -1) size = self.create_complex2(sidb, complex_struc3) self.assertEqual(complex_struc3_size, size) # set first var prototype offset = idc.GetFirstMember(sida) member_id = idc.GetMemberId(sida, offset) self.assertNotEqual(member_id, -1) self.assertTrue( idc.SetType(member_id, "create_struct_in_stack_vars_with_renaming* x;")) self.assertEqual("create_struct_in_stack_vars_with_renaming *", idc.GetType(idc.GetMemberId(sida, offset))) idc.SetMemberName(sida, offset, "var1") yaunit.save("create_struct_in_stack_vars_with_renaming", sida) yaunit.save("create_struct_in_stack_vars_with_renaming_offset", offset)
def functions_iter(): functions = set() exports = get_export_list() for func_ea in idautils.Functions(): if func_ea in functions: continue # functions with chunks appear once for each of them.. functions.add(func_ea) code, blocks = get_code_and_blocks(func_ea) crefs_to = get_func_code_refs_to(func_ea) crefs_from = get_func_code_refs_from(func_ea, code.iterkeys()) f = func.Function(func_ea, code, blocks, crefs_to, crefs_from) f.ftype = idc.GetType(func_ea) f.name = idc.GetFunctionName(func_ea) if func_ea in exports: f.exported = True yield f typed_imports = get_typed_imports() for imp_ea, ftype in typed_imports: crefs_to = get_func_code_refs_to(imp_ea) f = func.Function(imp_ea, None, None, crefs_to, None) f.ftype = ftype f.level = -1 # special level for imported functions yield f
def collect_function_vars(func_ea, blockset): DEBUG_PUSH() if is_function_unsafe(func_ea, blockset): _FUNC_UNSAFE_LIST.add(get_symbol_name(func_ea)) # Check for the variadic function type; Add the variadic function # to the list of unsafe functions func_type = idc.GetType(func_ea) if (func_type is not None) and ("(" in func_type): args = func_type[func_type.index('(') + 1:func_type.rindex(')')] args_list = [x.strip() for x in args.split(',')] if "..." in args_list: _FUNC_UNSAFE_LIST.add(get_symbol_name(func_ea)) stack_vars = build_stack_variable(func_ea) processed_blocks = set() while len(blockset) > 0: block_ea = blockset.pop() if block_ea in processed_blocks: DEBUG("ERROR: Attempting to add same block twice: {0:x}".format( block_ea)) continue processed_blocks.add(block_ea) _process_basic_block(func_ea, block_ea, {"stack_vars": stack_vars}) DEBUG_POP() return stack_vars
def export_func_names(fname): s = idautils.Strings(False) s.setup(strtypes=idautils.Strings.STR_UNICODE | idautils.Strings.STR_C) jsontable = [] for v in s: if v is None: print("Failed to retrieve string index") else: xrefs = [x.frm for x in idautils.XrefsTo(v.ea)] if len(xrefs) != 1: continue print("%x: len=%d type=%d -> '%s'" % (v.ea, v.length, v.type, unicode(v))) d = {} d['string'] = unicode(v) d['str_type'] = v.type func = idaapi.get_func(xrefs[0]) if func is None: continue d['func_name'] = idc.GetFunctionName(func.startEA) d['func_demangled'] = demangle(d['func_name']) d['func_c_decl'] = idc.GetType(func.startEA) d['func_comment'] = idaapi.get_func_cmt(func, 1) jsontable.append(d) f = open(fname,'w') json.dump(jsontable,f,indent=4) f.close()
def fields(self, reload=False): if reload or not self._fields: self._fields = {} m = 0 while True: if m >= idc.GetStrucSize(self.id): break n = idc.GetMemberName(self.id, m) if n == idc.BADADDR: break sz = idc.GetMemberSize(self.id, m) mid = idc.GetMemberId(self.id, m) tp = idc.GetType(mid) fld = { 'offset': m, 'id': mid, 'name': n, 'size': sz, 'type': [tp, None] } if n != '': fld['type'][1] = idc.GetMemberFlag(self.id, m) self._fields[m] = fld m = idc.GetStrucNextOff(self.id, m) if m == idc.BADADDR: break return self._fields
def yacheck_create_struct_in_stack_vars(self): sida = yaunit.load("create_struct_in_stack_vars") offset = yaunit.load("create_struct_in_stack_vars_offset") stype = idc.GetType(idc.GetMemberId(sida, offset)) self.assertNotEqual(None, stype) stype = fix_ptr_type(stype) self.assertEqual("create_struct_in_stack_vars*", stype)
def yacheck_set_field_prototype(self): for field_type, name, prototype in set_field_prototype: sid = idc.GetStrucIdByName(name) self.assertNotEqual(sid, idaapi.BADADDR) for k in range(0, get_size(field_type, -1) - 1): self.assertEqual(field_type, idc.GetMemberFlag(sid, k) & idaapi.DT_TYPE) mid = idc.GetMemberId(sid, k) self.assertEqual(prototype, idc.GetType(mid))
def yacheck_reference_loop(self): for k in range(0, 2): sid = idc.GetStrucIdByName('refloop' + str(k)) self.assertNotEqual(sid, idaapi.BADADDR) self.assertEqual(idc.GetMemberName(sid, 0), 'refloop_field' + str(k)) mid = idc.GetMemberId(sid, 0) self.assertNotEqual(mid, -1) self.assertEqual(idc.GetType(mid), 'refloop' + str(1 - k) + ' *')
def get_type(cls, function): '''Get function type.''' ctype = idc.GetType(function) if not ctype: ctype = idc.GuessType(function) if not ctype: ctype = '' return ctype
def yacheck_create_struct_in_stack_vars_with_renaming(self): sida = yaunit.load("create_struct_in_stack_vars_with_renaming") offset = yaunit.load("create_struct_in_stack_vars_with_renaming_offset") self.assertEqual("var1", idc.GetMemberName(sida, offset)) stype = fix_ptr_type(idc.GetType(idc.GetMemberId(sida, offset))) self.assertEqual("create_struct_in_stack_vars_with_renaming*", stype)
def build_stack_args(f): stackArgs = dict() name = idc.Name(f) end = idc.GetFunctionAttr(f, idc.FUNCATTR_END) _locals = idc.GetFunctionAttr(f, idc.FUNCATTR_FRSIZE) _uses_bp = 0 != (idc.GetFunctionFlags(f) & idc.FUNC_FRAME) frame = idc.GetFrame(f) if frame is None: return stackArgs func_type = idc.GetType(f) if (func_type is not None) and ("(" in func_type): args = func_type[ func_type.index('(')+1: func_type.rindex(')') ] args_list = [ x.strip() for x in args.split(',')] if "..." in args_list: return stackArgs if name in RECOVER_DEBUG_FL: return stackArgs #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 -1 == delta: #indicates that it wasn't found. Unsure exactly what to do # in that case, punting for now delta = 0 offset = idc.GetFirstMember(frame) while -1 != _signed_from_unsigned(offset): memberName = idc.GetMemberName(frame, offset) if memberName is None: # gaps in stack usage are fine, but generate trash output # gaps also could indicate a buffer that IDA doesn't recognize offset = idc.GetStrucNextOff(frame, offset) continue if (memberName == " r" or memberName == " s"): #the return pointer and start pointer, who cares offset = idc.GetStrucNextOff(frame, offset) continue memberSize = idc.GetMemberSize(frame, offset) if offset >= delta: offset = idc.GetStrucNextOff(frame, offset) continue memberFlag = idc.GetMemberFlag(frame, offset) #TODO: handle the case where a struct is encountered (FF_STRU flag) flag_str = _get_flags_from_bits(memberFlag) stackArgs[offset-delta] = {"name":memberName, "size":memberSize, "flags":flag_str, "writes":list(), "referent":list(), "reads":list(), "safe": False} offset = idc.GetStrucNextOff(frame, offset) return stackArgs
def readEA(self, ea): self.name = idc.GetFunctionName(ea) if not self.name: raise self.NotFunctionError(ea) self.ea = ea tp = idc.GetType(ea) or idc.GuessType(ea) if tp: self.parseType(tp, skipName=True) return self
def include(self): t = idc.GetType(self.offset) # if failed getting type, there's no annotation here if t is None: return False # if type equals guessed type, no need to save annotation if t == idc.GuessType(self.offset): return False return True
def make_strings_const(): s = idautils.Strings(False) s.setup(strtypes=idautils.Strings.STR_UNICODE | idautils.Strings.STR_C) for v in s: gt = idc.GetType(v.ea) if not gt: gt = idc.GuessType(v.ea) if gt and not gt.startswith("const "): idc.SetType(v.ea, "const " + gt)
def send_names(self): """ Used to send all the names to the server. Usecase: Previously analyzed IDB """ for head in idautils.Names(): if not SkelUtils.func_name_blacklist(head[1]): mtype = idc.GetType(head[0]) if mtype and not mtype.lower().startswith("char["): self.skel_conn.push_name(head[0], head[1])
def calConstantNumber(ea): i = 0; curStrNum = 0 numeric = 0 #print idc.GetDisasm(ea) while i <= 1: if (idc.GetOpType(ea,i ) == 5): addr = idc.GetOperandValue(ea, i) if (idc.SegName(addr) == '.rodata') and (idc.GetType(addr) == 'char[]') and (i == 1): curStrNum = curStrNum + 1 else : numeric = numeric + 1 i = i + 1 return numeric,curStrNum;
def setStrucPntr(self, sid, ofs, name, tp=None): vnm = idc.GetMemberName(sid, ofs) if not vnm or vnm in (idc.BADADDR, -1): idc.AddStrucMember(sid, name, ofs, idc.FF_QWRD, -1, 8) vnm = name if vnm != name: idc.SetMemberName(sid, ofs, name) sz = idc.GetMemberSize(sid, ofs) if sz != 8: idc.SetMemberType(sid, ofs, idc.FF_QWRD, -1, 1) mid = idc.GetMemberId(sid, ofs) t = idc.GetType(mid) or '' if tp and t.replace(' ', '') != tp.replace(' ', ''): idc.SetType(mid, tp + ';')
def getExportType(name, ep): try: DEBUG("Processing export name: {} at: {:x}\n".format(name, ep)) args, conv, ret = getFromEMAP(name) except KeyError as ke: tp = idc.GetType(ep); if tp is None or "__" not in tp: #raise Exception("Cannot determine type of function: {0} at: {1:x}".format(name, ep)) sys.stdout.write("WARNING: Cannot determine type of function: {0} at: {1:x}".format(name, ep)) return (0, cfg_pb2.ExternalFunction.CalleeCleanup, "N") return parseTypeString(tp, ep) return args, conv, ret
def getExportType(name, ep): try: args, conv, ret = getFromEMAP(name) except KeyError as ke: tp = idc.GetType(ep) if tp is None: #raise Exception("Cannot determine type of function: {0} at: {1:x}".format(name, ep)) sys.stdout.write( "WARNING: Cannot determine type of function: {0} at: {1:x}". format(name, ep)) return (0, CFG_pb2.ExternalFunction.CalleeCleanup, "N") return parseTypeString(tp, ep) return args, conv, ret
def ParseTypes(plt_ea): # parse types if idc.GetType(plt_ea) == None: try: demangle = idc.demangle_name(idc.get_func_name(plt_ea), 1) if demangle == None: return guess = '__int64 A' + demangle[demangle.index('('):demangle. index(')') + 1] ret = idc.SetType(plt_ea, guess) if ret != True: print('Fail call ParseTypes(0x%x)' % (plt_ea)) except Exception as e: print("Raise Exception in arseTypes(0x%x)" % (plt_ea)) print(e) return
def getTypeVtbl(self, descr): if not descr.get('id'): return descr mid = idc.GetMemberId(descr['id'], 0) if not mid or mid == idc.BADADDR: return descr t = idc.GetType(mid) or '' t = t.replace('*', '').replace(' ', '') if 'VTABLE' not in t: return descr svid = idc.GetStrucIdByName(t) if not svid or svid == idc.BADADDR: return descr idc.SetStrucName(svid, descr['name'] + 'Vtbl') descr['vtblid'] = svid descr['vtblnm'] = descr['name'] + 'Vtbl' return descr
def yatest_create_struct_in_stack_vars(self): """ test creation of struct from stack vars used to find a bug when creating struct for stack vars and naming vars """ # create structure ident, sida = self.get_function_sid_without_del(True, local_size=complex_struc3_size, count_from_first_var=True) self.assertNotEqual(sida, -1) sidb = idc.AddStrucEx(0, 'create_struct_in_stack_vars', 0) self.assertNotEqual(sidb, -1) size = self.create_complex2(sidb, complex_struc3) self.assertEqual(complex_struc3_size, size) # set first var prototype offset = idc.GetFirstMember(sida) member_id = idc.GetMemberId(sida, offset) self.assertNotEqual(member_id, -1) self.assertTrue(idc.SetType(member_id, "create_struct_in_stack_vars* x;")) self.assertEqual("create_struct_in_stack_vars *", idc.GetType(idc.GetMemberId(sida, offset))) yaunit.save("create_struct_in_stack_vars", sida) yaunit.save("create_struct_in_stack_vars_offset", offset)
def postprocess(self): try: if self.cmdname == "MakeFunction": if idc.GetFunctionAttr(self.addr, 0) is not None: # Push "MakeFunction" change pass elif self.cmdname == "DeclareStructVar": g_logger.error("Fixme : declare Struct variable") elif self.cmdname == "SetType": newtype = idc.GetType(self.addr) if newtype is None: newtype = "" else: newtype = SkelUtils.prepare_parse_type( newtype, self.addr) self.skel_conn.push_type(int(self.addr), newtype) elif self.cmdname == "OpStructOffset": g_logger.debug("A struct member is typed to struct offset") except KeyError: g_logger.debug("Got unimplemented ops %s", self.cmdname) return 0
def postprocess(self): try: if "MakeComment" in self.cmdname: if idc.Comment(self.addr) is not None: self.skel_conn.push_comment(self.addr, idc.Comment(self.addr)) if idc.GetFunctionCmt(self.addr, 0) != "": self.skel_conn.push_comment( self.addr, idc.GetFunctionCmt((self.addr), 0)) elif "MakeRptCmt" in self.cmdname: if idc.GetCommentEx(self.addr, 1) != "": self.skel_conn.push_comment( self.addr, idc.GetCommentEx(self.addr, 1)) if idc.GetFunctionCmt(self.addr, 1) != "": self.skel_conn.push_comment( self.addr, idc.GetFunctionCmt(self.addr, 1)) elif self.cmdname == "MakeFunction": if idc.GetFunctionAttr(self.addr, 0) is not None: pass #push_change("idc.MakeFunction", shex(idc.GetFunctionAttr( # self.addr, 0)), shex(idc.GetFunctionAttr(self.addr, 4))) elif self.cmdname == "DeclareStructVar": print "Fixme : declare Struct variable" elif self.cmdname == "SetType": newtype = idc.GetType(self.addr) if newtype is None: newtype = "" else: newtype = SkelUtils.prepare_parse_type( newtype, self.addr) self.skel_conn.push_type(int(self.addr), newtype) # XXX IMPLEMENT elif self.cmdname == "OpStructOffset": print "Fixme, used when typing a struct member/stack var/data pointer to a struct offset " except KeyError: pass return 0
def __init__(self): self.addr = None self.flags = None self.names = [ 'Function name', 'Address', 'Segment', 'Length', 'Locals', 'Arguments', 'R', 'F', 'L', 'S', 'B', 'T', '=' ] self.handlers = { 0: lambda: None, 1: lambda: self.ptr().format(self.addr), 2: lambda: '{}'.format(idc.SegName(self.addr)), 3: lambda: self.halfptr().format( idc.GetFunctionAttr(self.addr, idc.FUNCATTR_END) - self.addr), 4: lambda: self.set_if_true( idc.GetFunctionAttr(self.addr, idc.FUNCATTR_FRSIZE)), 5: lambda: self.set_if_true( idc.GetFunctionAttr(self.addr, idc.FUNCATTR_ARGSIZE)), 6: lambda: self.is_true(not self.flags & idc.FUNC_NORET, 'R'), 7: lambda: self.is_true(self.flags & idc.FUNC_FAR, 'F'), 8: lambda: self.is_true(self.flags & idc.FUNC_LIB, 'L'), 9: lambda: self.is_true(self.flags & idc.FUNC_STATIC, 'S'), 10: lambda: self.is_true(self.flags & idc.FUNC_FRAME, 'B'), 11: lambda: self.is_true(idc.GetType(self.addr), 'T'), 12: lambda: self.is_true(self.flags & idc.FUNC_BOTTOMBP, '=') }
def find(self, **kwargs): res = [] if kwargs.get('func'): f = kwargs.get('func') if isinstance(f, basestring): f = idaapi.get_name_ea(idc.BADADDR, f) res = self.checkFunc(f, **kwargs) or [] else: for funcea in idautils.Functions(): tp = idc.GetType(funcea) if tp is None or self.stname not in tp: continue r = self.checkFunc(funcea, **kwargs) if r: res += r if kwargs.get("silent"): return res if len(res): dictchooser.DictChooser('.'.join(self.name) + " usage", res, jumpProc=self.jump).Show() else: Logger.info("Nothing found")
def fixup_this_arg_types(cfunc): ''' Modifies a cfuncptr_t such that its first argument is a pointer to the Type that has this cfunc in its vtable (and is named 'this') ''' # Don't do anything if the type has already been set if idc.GetType(cfunc.entry_ea) is not None: return t = get_type_by_func(cfunc.entry_ea) if t is None: return tinfo = t.tinfo tinfo.create_ptr(tinfo) #TODO: add missing this argument? if len(cfunc.arguments) == 0: return cfunc.arguments[0].set_lvar_type(tinfo) cfunc.arguments[0].name = "this" cfunc.get_func_type(tinfo) idaapi.set_tinfo2(cfunc.entry_ea, tinfo)
0 #Hardcoded to 0 until we figure out what the 'size' info actually means } data['exports'].append(e) #iterate through functions for func in idautils.Functions(): #if func from library skip flags = idc.GetFunctionFlags(func) if flags & FUNC_LIB or flags & FUNC_THUNK or flags & FUNC_HIDDEN: continue #get procedure name name = idc.GetFunctionName(func) #get procedure callconv func_info = idc.GetType(func) callconv = getCallConv(func_info) start = idc.GetFunctionAttr(func, FUNCATTR_START) end = idc.GetFunctionAttr(func, FUNCATTR_END) cur_addr = start asm = '' ops = '' insns_list = [] flow_insns = [] while cur_addr <= end: next_instr = idc.NextHead(cur_addr, end) #get size instr
def postprocess(self): global skel_conn try: if self.cmdname == "MakeComment": if idc.GetCommentEx(self.addr, 0) is not None: skel_conn.push_comment(self.addr, idc.GetCommentEx((self.addr), 0)) elif idc.GetCommentEx(self.addr, 1) is not None: skel_conn.push_comment(self.addr, idc.GetCommentEx((self.addr), 1)) elif idc.GetFunctionCmt(self.addr, 0) != "": skel_conn.push_comment(self.addr, idc.GetCommentEx((self.addr), 0)) elif idc.GetFunctionCmt(self.addr, 1) != "": skel_conn.push_comment( self.addr, idc.GetFunctionCmt(self.addr, 1).replace("\n", "\\n").replace( "\"", "\\\"")) if self.cmdname == "MakeRptCmt": if idc.GetCommentEx(self.addr, 0) is not None: skel_conn.push_comment( self.addr, idc.GetCommentEx(self.addr, 0).replace("\n", "\\n").replace( "\"", "\\\"")) elif idc.GetCommentEx(self.addr, 1) is not None: skel_conn.push_comment( self.addr, idc.GetCommentEx(self.addr, 1).replace("\n", "\\n").replace( "\"", "\\\"")) elif idc.GetFunctionCmt(self.addr, 0) != "": skel_conn.push_comment( self.addr, idc.GetFunctionCmt(self.addr, 0).replace("\n", "\\n").replace( "\"", "\\\"")) elif idc.GetFunctionCmt(self.addr, 1) != "": skel_conn.push_comment( self.addr, idc.GetFunctionCmt(self.addr, 1).replace("\n", "\\n").replace( "\"", "\\\"")) elif self.cmdname == "MakeName": # idc.Jump(self.addr) if (idc.GetFunctionAttr(self.addr, 0) == self.addr): fname = GetFunctionName(self.addr) if fname != "": if not CheckDefaultValue(fname): skel_conn.push_name(self.addr, fname) else: fname = idc.GetTrueName(self.addr) if fname != "" and not CheckDefaultValue(fname): skel_conn.push_name( self.addr, fname.replace("\n", "\\n").replace("\"", "\\\"")) else: # ok, on regarde ce qui est pointe if GetOpType(self.addr, 0) in [o_near, o_imm, o_mem]: if GetOpType(self.addr, 1) in [o_near, o_imm, o_mem]: print "[P] You must be on the top of function or at the global address to set the name in log file" else: add = idc.GetOperandValue(self.addr, 0) fname = idc.GetTrueName(add) if fname != "" and not CheckDefaultValue( fname): skel_conn.push_name( add, fname.replace("\n", "\\n").replace( "\"", "\\\"")) else: print "[P] You must be on the top of function or at the global address to set the name in log file" elif GetOpType(self.addr, 1) in [o_near, o_imm, o_mem]: add = idc.GetOperandValue(self.addr, 1) fname = idc.GetTrueName(add) if fname != "" and not CheckDefaultValue(fname): skel_conn.push_name( add, fname.replace("\n", "\\n").replace("\"", "\\\"")) else: print "[P] You must be on the top of function or at the global address to set the name in log file" elif self.cmdname == "MakeFunction": if idc.GetFunctionAttr(self.addr, 0) is not None: pass #push_change("idc.MakeFunction", shex(idc.GetFunctionAttr( # self.addr, 0)), shex(idc.GetFunctionAttr(self.addr, 4))) elif self.cmdname == "DeclareStructVar": print "Fixme : declare Struct variable" elif self.cmdname == "AddStruct": print "Fixme : adding structure" elif self.cmdname == "SetType": newtype = idc.GetType(self.addr) if newtype is None: newtype = "" else: newtype = prepare_parse_type(newtype, self.addr) push_change("idc.SetType", shex(self.addr), newtype) elif self.cmdname == "OpStructOffset": print "Fixme, used when typing a struct member/stack var/data pointer to a struct offset " except KeyError: pass return 0
def signature(self): '''The C signature of the function.''' return idc.GetType(self.startEA)