Example #1
0
 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
Example #2
0
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
Example #3
0
    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))
Example #4
0
    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
Example #5
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
Example #6
0
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
Example #7
0
    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
Example #8
0
 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)
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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
Example #12
0
    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("请输入起点地址和寄存器")
Example #13
0
 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("请输入函数名和寄存器")
Example #14
0
    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
Example #15
0
    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
Example #16
0
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
Example #17
0
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
Example #18
0
    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
Example #19
0
    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)