def btn_get_one_sink_func_xref(self, code=0): """ 查看某个危险函数调用地址 """ tgt_t = ida_kernwin.ask_str('', 0, '请输入要查看的危险函数名') if tgt_t in SINK_FUNC: cols = [['', 0 | ida_kernwin.Choose.CHCOL_DEC], ['函数名', 10 | ida_kernwin.Choose.CHCOL_PLAIN], ['函数地址', 10 | ida_kernwin.Choose.CHCOL_HEX]] items = [] mgr_t = FESinkFuncMgr() xref_list = mgr_t.get_one_func_xref(tgt_t) if not xref_list: FELogger.warn("未找到函数%s" % tgt_t) return tmp_list = [] for xref_addr in xref_list: data = AnalysisChooseData(vuln=0, name=tgt_t, ea=xref_addr) items.append(data) tmp_list.append(xref_addr) self.sink_func_xref_dict[tgt_t] = tmp_list chooser = AnalysisChooser(title='危险函数调用地址', cols=cols, item=items) chooser.Show() else: FELogger.warn("未支持函数")
def btn_func_xref_count(self, code=0): """ 函数调用次数统计 """ xref_count_dict = OrderedDict() for func_addr_t in idautils.Functions(): count = len(list(idautils.CodeRefsTo(func_addr_t, 0))) xref_count_dict[ida_funcs.get_func_name(func_addr_t)] = [ func_addr_t, count ] ordered_list = sorted(list(xref_count_dict.items()), key=lambda x: x[1][1], reverse=True) cols = [['', 0 | ida_kernwin.Choose.CHCOL_DEC], ['函数名', 15 | ida_kernwin.Choose.CHCOL_PLAIN], ['地址', 10 | ida_kernwin.Choose.CHCOL_HEX], ['次数', 10 | ida_kernwin.Choose.CHCOL_PLAIN]] items = [] for x in ordered_list: data = AnalysisChooseData(vuln=0, name=x[0], ea=x[1][0], other1=str(x[1][1])) items.append(data) chooser = AnalysisChooser(title='函数调用次数统计', cols=cols, item=items) chooser.Show()
def system_func_analysis(func_name, xref_list): """ system系列函数漏洞分析 """ vuln_flag = 0 addr1 = 0 str1 = '' func_name_t = func_name xref_list_t = xref_list items = [] vuln_rule = SINK_FUNC[func_name_t]['vuln_rule'] vuln_reg = vuln_rule[0]['vuln_regs'][0] FELogger.info('检测%s漏洞' % vuln_rule[0]['vuln_type']) for xref_addr_t in xref_list_t: FELogger.info("从%s回溯来源地址%s" % (hexstr(xref_addr_t), vuln_reg)) tracer = FEArgsTracer(xref_addr_t, vuln_reg) source_addr = tracer.run() print('source_addr: ', source_addr) # 判断是否找到目标地址 if source_addr == []: FELogger.info("目标地址未找到%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: for cmd_addr in source_addr: addr1 = cmd_addr # 判断字符串是否来自内存 if idc.get_operand_type(cmd_addr, 1) == ida_ua.o_mem: cmd_str = FEStrMgr.get_mem_string(cmd_addr) # 判断是否找到字符串 if cmd_str == []: FELogger.info("硬编码命令未找到%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: vuln_flag = 0 str1 = cmd_str[0] else: FELogger.info("命令来自外部%s" % hexstr(xref_addr_t)) vuln_flag = 1 data = AnalysisChooseData(vuln=vuln_flag, name=func_name_t, ea=xref_addr_t, addr1=addr1, str1=str1) items.append(data) return items
def btn_get_sink_func_addr(self, code=0): """ 查看危险函数地址列表 """ cols = [['', 0 | ida_kernwin.Choose.CHCOL_DEC], ['函数名', 10 | ida_kernwin.Choose.CHCOL_PLAIN], ['函数地址', 10 | ida_kernwin.Choose.CHCOL_HEX]] items = [] mgr_t = FESinkFuncMgr() for func_name, func_addr in mgr_t.gen_sink_func_addr(): data = AnalysisChooseData(vuln=0, name=func_name, ea=func_addr) items.append(data) chooser = AnalysisChooser(title='危险函数地址', cols=cols, item=items) chooser.Show()
def check_src_reg(xref_addr_t, src_reg, siz_addr_t=0): vuln_flag = 0 addr1 = 0 str1 = '' if siz_addr_t == 0: str_siz_addr = '' else: str_siz_addr = hexstr(siz_addr_t) FELogger.info("从%s回溯来源地址%s" % (hexstr(xref_addr_t), src_reg)) src_tracer = FEArgsTracer(xref_addr_t, src_reg) src_source_addr = src_tracer.run() print('src_source_addr: ', src_source_addr) # 判断是否找到字符串来源地址 if src_source_addr == []: FELogger.info("未找到目标地址%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: for src_addr in src_source_addr: addr1 = src_addr src_str = FEStrMgr.get_mem_string(src_addr) # 判断是否找到字符串 if src_str == []: FELogger.info('来源字符串未找到%s' % hexstr(xref_addr_t)) vuln_flag = 1 else: # 判断来源地址是否为内存 str1 = src_str[0] if idc.get_operand_type(src_addr, 1) != ida_ua.o_mem: vuln_flag = 1 else: vuln_flag = 0 data = AnalysisChooseData(vuln=vuln_flag, name=func_name_t, ea=xref_addr_t, addr1=addr1, str1=str1, other1=str_siz_addr) items.append(data)
def btn_get_all_sink_func_xref(self, code=0): """ 查看所有危险函数调用地址 """ cols = [['', 0 | ida_kernwin.Choose.CHCOL_DEC], ['函数名', 10 | ida_kernwin.Choose.CHCOL_PLAIN], ['函数地址', 10 | ida_kernwin.Choose.CHCOL_HEX]] items = [] mgr_t = FESinkFuncMgr() for func_name, xref_list in mgr_t.gen_sink_func_xref(): tmp_list = [] for xref_addr in xref_list: data = AnalysisChooseData(vuln=0, name=func_name, ea=xref_addr) items.append(data) tmp_list.append(xref_addr) self.sink_func_xref_dict[func_name] = tmp_list chooser = AnalysisChooser(title='危险函数调用地址', cols=cols, item=items) chooser.Show()
def check_fmt_reg(xref_addr_t, fmt_reg, vuln_regs, siz_addr_t=0, parse=False): vuln_flag = 0 addr1 = 0 str1 = '' if siz_addr_t == 0: str_siz_addr = '' else: str_siz_addr = hexstr(siz_addr_t) FELogger.info("从%s回溯格式字符串%s" % (hexstr(xref_addr_t), fmt_reg)) tracer = FEArgsTracer(xref_addr_t, fmt_reg) source_addr = tracer.run() print('source_addr: ', source_addr) # 判断是否找到字符串来源地址 if source_addr == []: FELogger.info("未找到目标地址%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: for fmt_addr in source_addr: addr1 = fmt_addr fmt_str = FEStrMgr.get_mem_string(fmt_addr) # 判断是否找到字符串 if fmt_str == []: FELogger.info('格式字符串未找到%s' % hexstr(xref_addr_t)) vuln_flag = 1 str1 = '' else: FELogger.info('找到格式字符串%s' % hexstr(xref_addr_t)) str1 = fmt_str[0] if parse == False: vuln_flag = 0 else: fmt_list = FEStrMgr.parse_format_string(str1) # 判断字符串中的格式字符 if fmt_list != [] and 's' in ''.join(fmt_list): if vuln_regs[-1] == '...': args_num = len(fmt_list) + len(vuln_regs) - 1 if args_num > 4: fmt_list = fmt_list[:( 4 - (len(vuln_regs) - 1))] for idx in range(len(fmt_list)): if 's' in fmt_list[idx]: str_reg = 'R%s' % (len(vuln_regs) - 1 + idx) FELogger.info( "从%s回溯字符串%s" % (hexstr(xref_addr_t), str_reg)) str_tracer = FEArgsTracer(xref_addr_t, str_reg, max_node=256) str_source_addr = str_tracer.run() print('str_source_addr: ', str_source_addr) if str_source_addr == []: FELogger.info("未找到%s字符串地址" % str_reg) vuln_flag = 1 break else: for str_addr in str_source_addr: if idc.get_operand_type( str_addr, 1) == ida_ua.o_mem: vuln_flag = 0 else: vuln_flag = 1 break else: continue else: vuln_flag = 1 else: FELogger.info("格式字符串不包含s转换符号") vuln_flag = 0 data = AnalysisChooseData(vuln=vuln_flag, name=func_name_t, ea=xref_addr_t, addr1=addr1, str1=str1, other1=str_siz_addr) items.append(data)
def printf_func_analysis(func_name, xref_list): """ printf系列函数漏洞分析 """ def check_fmt_reg(xref_addr_t, fmt_reg, vuln_regs, siz_addr_t=0, parse=False): vuln_flag = 0 addr1 = 0 str1 = '' if siz_addr_t == 0: str_siz_addr = '' else: str_siz_addr = hexstr(siz_addr_t) FELogger.info("从%s回溯格式字符串%s" % (hexstr(xref_addr_t), fmt_reg)) tracer = FEArgsTracer(xref_addr_t, fmt_reg) source_addr = tracer.run() print('source_addr: ', source_addr) # 判断是否找到字符串来源地址 if source_addr == []: FELogger.info("未找到目标地址%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: for fmt_addr in source_addr: addr1 = fmt_addr fmt_str = FEStrMgr.get_mem_string(fmt_addr) # 判断是否找到字符串 if fmt_str == []: FELogger.info('格式字符串未找到%s' % hexstr(xref_addr_t)) vuln_flag = 1 str1 = '' else: FELogger.info('找到格式字符串%s' % hexstr(xref_addr_t)) str1 = fmt_str[0] if parse == False: vuln_flag = 0 else: fmt_list = FEStrMgr.parse_format_string(str1) # 判断字符串中的格式字符 if fmt_list != [] and 's' in ''.join(fmt_list): if vuln_regs[-1] == '...': args_num = len(fmt_list) + len(vuln_regs) - 1 if args_num > 4: fmt_list = fmt_list[:( 4 - (len(vuln_regs) - 1))] for idx in range(len(fmt_list)): if 's' in fmt_list[idx]: str_reg = 'R%s' % (len(vuln_regs) - 1 + idx) FELogger.info( "从%s回溯字符串%s" % (hexstr(xref_addr_t), str_reg)) str_tracer = FEArgsTracer(xref_addr_t, str_reg, max_node=256) str_source_addr = str_tracer.run() print('str_source_addr: ', str_source_addr) if str_source_addr == []: FELogger.info("未找到%s字符串地址" % str_reg) vuln_flag = 1 break else: for str_addr in str_source_addr: if idc.get_operand_type( str_addr, 1) == ida_ua.o_mem: vuln_flag = 0 else: vuln_flag = 1 break else: continue else: vuln_flag = 1 else: FELogger.info("格式字符串不包含s转换符号") vuln_flag = 0 data = AnalysisChooseData(vuln=vuln_flag, name=func_name_t, ea=xref_addr_t, addr1=addr1, str1=str1, other1=str_siz_addr) items.append(data) func_name_t = func_name xref_list_t = xref_list items = [] vuln_rule = SINK_FUNC[func_name_t]['vuln_rule'] args_rule = SINK_FUNC[func_name_t]['args_rule'] for xref_addr_t in xref_list_t: for rule in vuln_rule: FELogger.info('检测%s漏洞' % rule['vuln_type']) if rule['vuln_type'] == 'format_string': fmt_reg = rule['vuln_regs'][0] check_fmt_reg(xref_addr_t, fmt_reg, args_rule, parse=False) else: vuln_regs = rule['vuln_regs'] if vuln_regs[-1] == '...': fmt_reg = vuln_regs[-2] if len(vuln_regs) == 3: siz_reg = vuln_regs[0] else: siz_reg = None else: fmt_reg = vuln_regs[-1] if len(vuln_regs) == 2: siz_reg = vuln_regs[0] else: siz_reg = None # 判断是否有size参数 if siz_reg != None: FELogger.info("从%s回溯字符串长度%s" % (hexstr(xref_addr_t), siz_reg)) siz_tracer = FEArgsTracer(xref_addr_t, siz_reg, max_node=256) siz_source_addr = siz_tracer.run() print('siz_source_addr: ', siz_source_addr) # 判断是否找到size的地址 if siz_source_addr == []: FELogger.info("未找到size地址%s" % hexstr(xref_addr_t)) check_fmt_reg(xref_addr_t, fmt_reg, args_rule, parse=True) else: for siz_addr_t in siz_source_addr: # 判断size是否为立即数 if idc.get_operand_type(siz_addr_t, 1) != ida_ua.o_imm: check_fmt_reg(xref_addr_t, fmt_reg, args_rule, siz_addr_t, parse=True) else: num = idc.print_operand(siz_addr_t, 1) data = AnalysisChooseData(vuln=0, name=func_name_t, ea=xref_addr_t, addr1=siz_addr_t, str1='', other1=num) items.append(data) else: check_fmt_reg(xref_addr_t, fmt_reg, args_rule, parse=True) return items
def str_func_analysis(func_name, xref_list): """ str操作类函数漏洞分析 """ def check_src_reg(xref_addr_t, src_reg, siz_addr_t=0): vuln_flag = 0 addr1 = 0 str1 = '' if siz_addr_t == 0: str_siz_addr = '' else: str_siz_addr = hexstr(siz_addr_t) FELogger.info("从%s回溯来源地址%s" % (hexstr(xref_addr_t), src_reg)) src_tracer = FEArgsTracer(xref_addr_t, src_reg) src_source_addr = src_tracer.run() print('src_source_addr: ', src_source_addr) # 判断是否找到字符串来源地址 if src_source_addr == []: FELogger.info("未找到目标地址%s" % hexstr(xref_addr_t)) vuln_flag = 1 else: for src_addr in src_source_addr: addr1 = src_addr src_str = FEStrMgr.get_mem_string(src_addr) # 判断是否找到字符串 if src_str == []: FELogger.info('来源字符串未找到%s' % hexstr(xref_addr_t)) vuln_flag = 1 else: # 判断来源地址是否为内存 str1 = src_str[0] if idc.get_operand_type(src_addr, 1) != ida_ua.o_mem: vuln_flag = 1 else: vuln_flag = 0 data = AnalysisChooseData(vuln=vuln_flag, name=func_name_t, ea=xref_addr_t, addr1=addr1, str1=str1, other1=str_siz_addr) items.append(data) func_name_t = func_name xref_list_t = xref_list items = [] vuln_rule = SINK_FUNC[func_name_t]['vuln_rule'] vuln_regs = vuln_rule[0]['vuln_regs'] src_reg = vuln_regs[0] siz_reg = None if len(vuln_regs) == 2: siz_reg = vuln_regs[1] FELogger.info('检测%s漏洞' % vuln_rule[0]['vuln_type']) for xref_addr_t in xref_list_t: # 判断是否有size参数 if siz_reg != None: FELogger.info("从%s回溯字符串长度%s" % (hexstr(xref_addr_t), siz_reg)) siz_tracer = FEArgsTracer(xref_addr_t, siz_reg, max_node=256) siz_source_addr = siz_tracer.run() print('siz_source_addr: ', siz_source_addr) # 判断是否找到size的地址 if siz_source_addr == []: FELogger.info("未找到size地址%s" % hexstr(xref_addr_t)) data = AnalysisChooseData(vuln=1, name=func_name_t, ea=xref_addr_t) items.append(data) else: for siz_addr_t in siz_source_addr: # 判断size是否为立即数 if idc.get_operand_type(siz_addr_t, 1) != ida_ua.o_imm: check_src_reg(xref_addr_t, src_reg, siz_addr_t) else: num = idc.print_operand(siz_addr_t, 1) data = AnalysisChooseData(vuln=0, name=func_name_t, ea=xref_addr_t, addr1=siz_addr_t, str1='', other1=num) items.append(data) else: check_src_reg(xref_addr_t, src_reg) return items