def get_args_rule(self, func_name, ea): CUSTOM_FUNC = get_custom_func() if func_name in SINK_FUNC: args_rule = SINK_FUNC[func_name]['args_rule'] elif func_name in CUSTOM_FUNC: args_rule = CUSTOM_FUNC[func_name]['args_rule'] elif hexstr(ea) in CUSTOM_FUNC: args_rule = CUSTOM_FUNC[hexstr(ea)]['args_rule'] else: args_rule = False return args_rule
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_imp_ghidra_funcs(self, code=0): """ 导入Ghidra函数列表 """ ghidra_filepath = os.path.join(os.getcwd(), 'ghidra_func_addrs.csv') ghidra_path = ida_kernwin.ask_str(ghidra_filepath, 0, '导入的Ghidra导出函数文件路径') func_addrs = list(idautils.Functions()) make_func_addrs = [] if ghidra_path and ghidra_path != '': if os.path.exists(ghidra_path): with open(ghidra_path, 'rb') as f: next(f) reader = csv.reader(f) for row in reader: addr = int(row[0].strip('\"'), 16) if ida_funcs.add_func(addr) == True: make_func_addrs.append(addr) else: if addr not in func_addrs: FELogger.info("创建函数%s失败" % hexstr(addr)) FELogger.info("Ghidra导出函数文件:%s,已导入" % ghidra_path) else: FELogger.erro("未找到Ghidra导出函数文件:%s" % ghidra_path) else: FELogger.warn("请输入Ghidra导出函数文件路径") FELogger.info("成功创建%d个新函数" % len(make_func_addrs))
def dbg_bpt(self, tid, ea): """ 触发断点时的处理函数 """ func_name_t = idc.print_operand(ea, 0) point_hit_count = self.inc_break_point_hit_count(ea) if is_func_call(ea): # 如果当前地址是函数调用(即调用前) args_rule = self.get_args_rule(func_name_t, ea) if args_rule == False: FELogger.console('临时断点%s' % hexstr(ea)) else: up_func_name = ida_funcs.get_func_name(ea) func_hit_count = self.inc_break_func_hit_count(up_func_name) FELogger.console(func_name_t + ' - ' + up_func_name + '-' * 60) FELogger.console( 'tid - %d - %d, pointHit: %d, funcHit: %d' % (tid, time.time(), point_hit_count, func_hit_count)) FELogger.console(('%s - before' + '-' * 30) % func_name_t) ida_dbg.refresh_debugger_memory() before_info = self.get_before_run_info(args_rule) elif is_func_call(ida_bytes.prev_head(ea, 0)): # 如果当前地址的上一条地址是函数调用(即调用后) func_ea = ida_bytes.prev_head(ea, 0) func_name = idc.print_operand(func_ea, 0) args_rule = self.get_args_rule(func_name, func_ea) FELogger.console(('%s - after ' + '-' * 30) % func_name) # ida_dbg.refresh_debugger_memory() after_info = self.get_after_run_info(args_rule) else: FELogger.console('临时断点%s' % hexstr(ea)) # 是否单步调试 if self.step_dbg == False: ida_dbg.continue_process() return 0
def OnGetLine(self, n): d = self.items[n] data = [str(d.vuln), d.name, hexstr(d.ea)] for x in [d.vuln, d.addr2]: if x != None: data.append(hexstr(x)) else: continue for x in [d.str1, d.str2, d.other1]: if x != None: data.append(x) else: continue return data
def build_result(items): lines = [] for item in items: data = [str(item.vuln), item.name, hexstr(item.ea)] for x in [item.addr1, item.addr2]: if x != None: data.append(hexstr(x)) else: continue for x in [item.str1, item.str2, item.other1]: if x != None: data.append(repr(x)) else: continue data.append('\n') lines.append('\t'.join(data)) return lines
def get_after_run_info(self, args_rule): """ 获取某函数执行后的返回值 # TODO 添加参数的变化 """ runtime_info = {} args = self.get_xdbg_reg_var() rv = ida_idd.regval_t() ida_dbg.get_reg_val('PC', rv) FELogger.console('PC: %s' % hexstr(rv.ival)) arg_v = args[arm_regset.ret].ival #str_t = FEStrMgr.get_string_from_mem(arg_v) #runtime_info[arm_regset.ret] = [hexstr(arg_v), repr(str_t)] #FELogger.console('ret: %s => %s' % (hexstr(arg_v), repr(str_t))) FELogger.console('%s: %s' % (arm_regset.ret, hexstr(arg_v))) return runtime_info
def trace_next(self, blk, node, reg): """ 下一轮回溯 """ for ref_addr in self.get_all_ref(blk.start_ea): block = self.get_blk(ref_addr) if block: FELogger.info("基本块跳转\t"+hexstr(ref_addr)+"\t"+idc.generate_disasm_line(ref_addr, 0)) node_t = self.create_tree_node(ref_addr, prev=node) self.dfs(node_t, reg, block)
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 add_tmp_func(self, info_only=False): """ 添加临时sink函数 info_only: 在添加函数信息的同时是否添加断点 """ input_str = ida_kernwin.ask_text( 0, '', "请输入任意函数名/函数地址,及各参数类型(none, int, str),可输入多行\n例如:\nstrcmp str str") try: rules = [x.strip() for x in input_str.strip().split('\n')] for rule in rules: tgt_t = rule.split(' ')[0].strip() args_rule = [x.strip() for x in rule.split(' ')[1:]] if not tgt_t in self.tmp_func_dict: if tgt_t.startswith('0x'): addr_t = int(tgt_t, 16) addr_hexstr = hexstr(addr_t) CUSTOM_FUNC[addr_hexstr] = {'args_rule': args_rule} self.tmp_func_dict[addr_hexstr] = [addr_t] if info_only == False: ida_dbg.add_bpt(addr_t, 0, idc.BPT_DEFAULT) else: for func_addr_t in idautils.Functions(): func_name_t = ida_funcs.get_func_name(func_addr_t) if func_name_t == tgt_t: CUSTOM_FUNC[func_name_t] = { 'args_rule': args_rule } self.tmp_func_dict[func_name_t] = [] for xref_addr_t in idautils.CodeRefsTo( func_addr_t, 0): self.tmp_func_dict[func_name_t].append( xref_addr_t) if info_only == False: ida_dbg.add_bpt( xref_addr_t, 0, idc.BPT_DEFAULT) else: continue break else: continue else: CUSTOM_FUNC[tgt_t] = {'args_rule': args_rule} for xref_addr_t in self.tmp_func_dict[tgt_t]: if info_only == False: ida_dbg.add_bpt(xref_addr_t, 0, idc.BPT_DEFAULT) else: continue FELogger.info("已添加断点:%s" % rule) except Exception as e: FELogger.info("输入信息有误:%s" % e)
def fix_len_args_run_info(self, args_rule, args): """ 获取定长参数函数的寄存器信息 """ run_info = {} for idx in range(len(args_rule)): str_reg = 'R%s' % idx arg_t = args_rule[idx] if arg_t == 'none': # 跳过无关的参数 continue elif arg_t == 'int': run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) elif arg_t == 'str': arg_v = args[str_reg].ival if arg_v != 0: str_t = FEStrMgr.get_string_from_mem(arg_v) else: str_t = '' run_info[str_reg] = [hexstr(arg_v), repr(str_t)] FELogger.console('%s: %s => %s' % (str_reg, hexstr(arg_v), repr(str_t))) else: run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) return run_info
def btn_dfs_test_1(self, code=0): addr_t = ida_kernwin.ask_str('', 0, '请输入回溯起点地址') reg_t = ida_kernwin.ask_str('', 0, '请输入回溯寄存器') if (addr_t and addr_t != '') and (reg_t and reg_t != ''): try: addr_t = int(addr_t, 16) except Exception: FELogger.warn("无效地址") return FELogger.info("从地址%s回溯寄存器%s" % (hexstr(addr_t), reg_t)) tracer = FEArgsTracer(addr_t, reg_t) source_addr = tracer.run() print('source_addr: ', source_addr) else: FELogger.warn("请输入起点地址和寄存器")
def btn_dfs_test_2(self, code=0): tgt_t = ida_kernwin.ask_str('', 0, '请输入函数名') reg_t = ida_kernwin.ask_str('', 0, '请输入回溯寄存器') if (tgt_t and tgt_t != '') and (reg_t and reg_t != ''): for func_addr_t in idautils.Functions(): func_name_t = ida_funcs.get_func_name(func_addr_t) if func_name_t == tgt_t: for xref_addr_t in idautils.CodeRefsTo(func_addr_t, 0): if ida_funcs.get_func(xref_addr_t): FELogger.info("从地址%s回溯寄存器%s" % (hexstr(xref_addr_t), reg_t)) tracer = FEArgsTracer(xref_addr_t, reg_t, max_node=256) source_addr = tracer.run() print('source_addr: ', source_addr) break else: FELogger.warn("请输入函数名和寄存器")
def get_before_run_info(self, args_rule): """ 获取某函数执行前的寄存器信息 """ runtime_info = {} args = self.get_xdbg_reg_var() rv = ida_idd.regval_t() ida_dbg.get_reg_val('PC', rv) FELogger.console('PC: %s' % hexstr(rv.ival)) # 判断是否包含变长参数 if args_rule[-1] == '...': runtime_info = self.var_len_args_run_info(args_rule, args) elif args_rule[-1] == 'va_list': # TODO 支持va_list参数解析,暂时同“...” runtime_info = self.var_len_args_run_info(args_rule, args) else: runtime_info = self.fix_len_args_run_info(args_rule, args) return runtime_info
def var_len_args_run_info(self, args_rule, args): """ 获取变长参数函数的寄存器信息 """ run_info = {} fmt_t = '' for idx in range(len(args_rule) - 1): str_reg = 'R%s' % idx arg_t = args_rule[idx] if arg_t == 'none': # 跳过无关参数 continue elif arg_t == 'int': run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) elif arg_t == 'str': arg_v = args[str_reg].ival if arg_v != 0: str_t = FEStrMgr.get_string_from_mem(arg_v) else: str_t = '' run_info[str_reg] = [hexstr(arg_v), repr(str_t)] FELogger.console('%s: %s => %s' % (str_reg, hexstr(arg_v), repr(str_t))) elif arg_t == 'fmt': arg_v = args[str_reg].ival fmt_t = FEStrMgr.get_string_from_mem(arg_v) run_info[str_reg] = [hexstr(arg_v), repr(fmt_t)] FELogger.console('%s: %s => %s' % (str_reg, hexstr(arg_v), repr(fmt_t))) else: run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) # 判断是否包含格式字符串 if fmt_t != '': fmt_list = FEStrMgr.parse_format_string(str_t) args_num = len(fmt_list) + idx + 1 # 判断变长参数总个数 if idx + 1 == args_num: pass # n<=4 寄存器 elif idx + 1 < args_num and args_num <= 4: for jdx in range(len(fmt_list)): str_reg = 'R%s' % (idx + jdx + 1) if 's' in fmt_list[jdx]: arg_v = args[str_reg].ival str_t = FEStrMgr.get_string_from_mem(arg_v) run_info[str_reg] = [hexstr(arg_v), repr(str_t)] FELogger.console('%s: %s => %s' % (str_reg, hexstr(arg_v), repr(str_t))) else: run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) # n>4 寄存器+栈 else: stack_num = args_num - 4 sp_addr = args[arm_regset.stack].ival for jdx in range(4 - idx - 1): str_reg = 'R%s' % (idx + jdx + 1) if 's' in fmt_list[jdx]: arg_v = args[str_reg].ival str_t = FEStrMgr.get_string_from_mem(arg_v) run_info[str_reg] = [hexstr(arg_v), repr(str_t)] FELogger.console('%s: %s => %s' % (str_reg, hexstr(arg_v), repr(str_t))) else: run_info[str_reg] = [hexstr(args[str_reg].ival), None] FELogger.console('%s: %s' % (str_reg, hexstr(args[str_reg].ival))) run_info[arm_regset.stack] = [] for kdx in range(stack_num): stack_v = ida_bytes.get_wide_dword(sp_addr) if 's' in fmt_list[jdx + kdx + 1]: if stack_v == 0: str_t = '' else: str_t = FEStrMgr.get_string_from_mem(stack_v) run_info[arm_regset.stack].append( [hexstr(sp_addr), hexstr(stack_v), repr(str_t)]) FELogger.console( 'stack: %s - %s => %s' % (hexstr(sp_addr), hexstr(stack_v), repr(str_t))) else: run_info[arm_regset.stack].append( [hexstr(sp_addr), hexstr(stack_v), None]) FELogger.console('stack: %s - %s' % (hexstr(sp_addr), hexstr(stack_v))) sp_addr += 4 else: pass return run_info
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
def get_next_reg(self, addr, reg): """ 寻找下一个赋值来源寄存器 返回寄存器名或None """ reg_t = reg addr_t = addr mnem = get_mnem(addr_t) line = idc.generate_disasm_line(addr_t, 0) if mnem.startswith('BLX') and addr_t != self.trace_addr: FELogger.info("途径函数\t"+hexstr(addr)+"\t"+line) func_name = idc.print_operand(addr_t, 0) func_addr = name_to_addr(func_name) if func_addr is not None: if reg_t == 'R0': does_return = ida_funcs.get_func(func_addr).does_return() if does_return == True: FELogger.info("找到赋值点\t"+hexstr(addr)+"\t"+line) return None else: if func_name in SOURCE_FUNC and reg_t == SOURCE_FUNC[func_name]['dest']: reg_t = SOURCE_FUNC[func_name]['src'] if reg_t == 'None': FELogger.info("找到赋值点\t"+hexstr(addr)+"\t"+line) return None else: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) inst_list_t = INST_LIST reg_re = re.compile(reg_t + '\\D|' + reg_t + '\\Z') if reg_re.search(line): if mnem in reduce(lambda x, y: x + y, [value for value in inst_list_t.values()]): op1 = idc.print_operand(addr_t, 0).split("!")[0] if mnem in inst_list_t['load_multi']: # 找到 LDM R1, {R0-R3} regs = self.parse_operands(mnem, addr_t) if reg_t not in regs: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: FELogger.info("找到赋值点\t"+hexstr(addr)+"\t"+line) return None else: if op1 != reg_t or mnem in inst_list_t['other']: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) elif mnem in inst_list_t['arithmetic']: # 停止 ADD R0, SP; ADD R0, SP, #10 # 回溯R0 ADD R0, R1; ADD R0, #10 # 回溯R1 ADD R0, R1, #10; ADD R0, R1, R2 op2_tmp = idc.print_operand(addr_t, 1) if idc.get_operand_type(addr_t, 2) == ida_ua.o_void: if idc.get_operand_type(addr_t, 1) == ida_ua.o_reg: if op2_tmp == 'SP': FELogger.info("取消回溯SP\t"+hexstr(addr)+"\t"+line) return None else: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) elif idc.get_operand_type(addr_t, 3) == ida_ua.o_void: op3_tmp = idc.print_operand(addr_t, 2) if op2_tmp == 'SP' or op3_tmp == 'SP': FELogger.info("取消回溯SP\t"+hexstr(addr)+"\t"+line) return None elif reg_t == op2_tmp or reg_t == op3_tmp: FELogger.info("复杂运算\t"+hexstr(addr)+"\t"+line) return None else: reg_t = op2_tmp FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: op3_tmp = idc.print_operand(addr_t, 2) op4_tmp = idc.print_operand(addr_t, 3) if op2_tmp == 'SP' or op3_tmp == 'SP' or op4_tmp == 'SP': FELogger.info("取消回溯SP\t"+hexstr(addr)+"\t"+line) return None elif reg_t == op2_tmp or reg_t == op3_tmp or reg_t == op4_tmp: FELogger.info("复杂运算\t"+hexstr(addr)+"\t"+line) return None else: reg_t = op2_tmp FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) elif mnem in inst_list_t['move']: # 停止 MOV R0, SP; MOV R0, SP, #10 # 找到 MOV R0, #10 # 回溯R1 MOV R0, R1 # 回溯D8 VMOV R0, R1, D16 if mnem.startswith('VMOV'): op3_tmp = idc.print_operand(addr_t, 2) reg_t = op3_tmp FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: op2_tmp = idc.print_operand(addr_t, 1) if op2_tmp == 'SP': FELogger.info("取消回溯SP\t"+hexstr(addr)+"\t"+line) return None elif idc.get_operand_type(addr_t, 1) == ida_ua.o_reg: reg_t = op2_tmp FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) elif mnem in ['MOVT', 'MOVTGT', 'MOVTLE']: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: FELogger.info("找到赋值点\t"+hexstr(addr)+"\t"+line) return None elif mnem in inst_list_t['load']: # 找到 LDR R0, =xxxxxxx # 停止 LDR R0, [SP, #10] # 回溯R1 LDR R0, [R1, #10] # 回溯R0 LDR R0, [R0, R1, #10] if idc.get_operand_type(addr_t, 1) == ida_ua.o_mem: FELogger.info("找到赋值点\t"+hexstr(addr)+"\t"+line) return None else: regs_tmp = self.parse_operands(mnem, addr_t) if 'SP' in regs_tmp: FELogger.info("取消回溯SP\t"+hexstr(addr)+"\t"+line) return None elif reg_t in regs_tmp: FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: reg_t = regs_tmp[0] FELogger.info("回溯"+reg_t+"\t"+hexstr(addr)+"\t"+line) else: FELogger.info("未知指令\t"+hexstr(addr)+"\t"+line) else: FELogger.info("未知指令\t"+hexstr(addr)+"\t"+line) else: pass return reg_t
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)