コード例 #1
0
def test_list_squash_fs(request):
    pack_id = ReqParams.one(request, 'pack_id')

    fs_image = FsImage(pack_id)
    fs_image.enum_files()

    return sys_app_ok_p({})
コード例 #2
0
def pack_delete(request):
    pack_id = ReqParams.one(request, 'pack_id')

    # delete fw_files_storage
    # delete fw_files
    # delete pack_files_storage
    # delete pack_files

    file_list = FwFileDO.search_files_of_pack(pack_id)
    for file in file_list:
        FwFilesStorage.delete(file['file_id'])

    # if len(file_list) > 0:
    FwFileDO.delete_many_of_pack(pack_id)

    pack_info = PackFileDO.fetch_pack(pack_id)
    PackFilesStorage.delete(pack_info['file_id'])

    PackFileDO.delete(pack_id)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='删除固件包',
                    desc='删除指定固件包(ID=%s)的信息,' % pack_id)

    return sys_app_ok_p([])
コード例 #3
0
def com_sourcecode_files_tree(request):
    pack_id, tree_type = ReqParams.many(request, ['pack_id', 'tree_type'])
    file_list = SourceCodeFileDO.search_files_of_pack(pack_id)

    if tree_type is None or len(tree_type) == 0 or tree_type == 'normal':
        tree_type = 'normal'
        exec_tree = {}
    elif tree_type == 'antd':
        exec_tree = []
    else:
        tree_type = 'normal'
        exec_tree = {}

    # 对每个文件做树的各级节点定位和创建
    for file in file_list:
        # 获取文件路径
        file_path = file['file_path']
        file_id = file['file_id']

        if file_path is None or len(file_path) == 0:
            continue

        if tree_type == 'normal':
            MyTree.file_path_insert_into_tree(exec_tree, file_path, file_id)
        elif tree_type == 'antd':
            MyTree.file_path_insert_into_antd_tree(exec_tree, file_path,
                                                   file_id)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='查询组件源码文件目录树',
                    desc='获取组件源码文件目录树(模式为:%s)' % (tree_type))

    return sys_app_ok_p(exec_tree)
コード例 #4
0
def test_angr_reaching_definitions(request):
    file_id, file_name, func_addr = ReqParams.many(request, ['file_id', 'file_name', 'func_addr.hex'])
    file_path = os.path.join(MyPath.samples(), file_name)

    project = angr.Project(file_path, load_options={'auto_load_libs': False})
    # cfg = project.analyses.CFGFast()
    cfg = project.analyses.CFGEmulated()

    function = FunctionParse.func_by_addr(func_addr, cfg=cfg)

    tmp_kb = angr.KnowledgeBase(project)
    reaching_definition = project.analyses.ReachingDefinitions(
        subject=function, kb=tmp_kb, observe_all=True
    )

    # nose.tools.assert_equal(reaching_definition.subject.__class__ is Subject, True)

    def _result_extractor(rda):
        unsorted_result = map(
            lambda x: {'key': x[0],
                       'register_definitions': x[1].register_definitions._storage,
                       'stack_definitions': x[1].stack_definitions._storage,
                       'memory_definitions': x[1].memory_definitions._storage},
            rda.observed_results.items()
        )
        return list(sorted(
            unsorted_result,
            key=lambda x: x['key']
        ))

    result = _result_extractor(reaching_definition)

    pass
コード例 #5
0
def test_bin_info(request):
    file_name, load_options = ReqParams.many(request, ['file_name', 'load_options.int'])
    file_path = os.path.join(MyPath.samples(), 'bin', file_name)

    # bw_result = binwalk.scan(file_path, signature=True, opcodes=True)
    bw_result = binwalk.scan('--signature', '--opcodes', file_path)
    bw_result = binwalk.scan('--signature', file_path)
    return sys_app_ok_p({})

    if load_options == 1:
        proj = angr.Project(file_path, load_options={
            'main_opts': {
                'backend': 'blob',
                'base_addr': 0x10000,
                'entry_point': 0x10000,
                'arch': 'ARM',
                'offset': 0,
            }
        })
    else:
        # proj = angr.Project(file_path)
        proj = angr.Project(file_path, load_options={'auto_load_libs': False, 'main_opts': {}, })

    boyscout = proj.analyses.BoyScout()

    # proj2 = angr.Project(file_path, arch=angr.SimARM(endness="Iend_BE"),
    #                      load_options={
    #                          'backend': 'blob',
    #                          'base_addr': 0x10000,
    #                          'entry_point': 0x10000,
    #                          'arch': 'ARM',
    #                          'offset': 0,
    #                      })
    # girlscout = proj2.analyses.GirlScout(pickle_intermediate_results=True)
    return sys_app_ok_p({'arch': boyscout.arch, 'endianness': boyscout.endianness})
コード例 #6
0
def test_angr_backward_slice(request):
    file_name, func_addr = ReqParams.many(request, ['file_name', 'func_addr.hex'])
    file_path = os.path.join(MyPath.samples(), file_name)

    project = angr.Project(file_path, load_options={"auto_load_libs": False})

    cfg = project.analyses.CFGEmulated(keep_state=True, state_add_options=angr.sim_options.refs,
                                       context_sensitivity_level=2)

    cdg = project.analyses.CDG(cfg)

    ddg = project.analyses.DDG(cfg)

    target_node = cfg.get_any_node(func_addr)
    bs = project.analyses.BackwardSlice(cfg, cdg=cdg, ddg=ddg, targets=[(target_node, -1)])
    # bs.dbg_repr()

    node_has_type = False
    for node in bs.taint_graph.nodes():
        # param taint_type: Type of the taint, might be one of the following: 'reg', 'tmp', 'mem'.
        # print(node.stmt_idx)
        if hasattr(node, 'type'):
            print(node.type)
            node_has_type = True
        # if n.type == taint_type and n.addr == simrun_addr and n.stmt_id == stmt_idx:
        #     taint = n
    print('node type %s found' % ('' if node_has_type else 'not'))

    # VSA_DDG
    # vsa_ddg = project.analyses.VSA_DDG()
    return sys_app_ok()
コード例 #7
0
def auto_vuler_association(request):
    pack_id = ReqParams.one(request, 'pack_id')
    task_id = start_check_component_task(pack_id)
    if task_id is None:
        return sys_app_ok_p("自动组件漏洞关联正在运行中")

    return sys_app_ok_p(MyTask.fetch_exec_info(task_id))
コード例 #8
0
def function_info(request):
    # 从请求中取参数:文件 ID、函数地址
    file_id, func_addr, extra_info = ReqParams.many(
        request, ['file_id', 'func_addr.hex', 'extra_info'])

    # 获取指定函数的汇编、中间码等代码信息
    codes_dict = FunctionsService.func_codes(file_id, func_addr)
    infos_dict = codes_dict

    if extra_info is not None:
        # 取出首尾空格后分割成列表(用逗号分隔)
        extra_list = extra_info.strip().split(',')
        if 'props' in extra_list:
            # 如指定 props 则附加函数属性信息
            props_dict = FunctionsService.func_props(file_id, func_addr)
            infos_dict['props'] = props_dict
        if 'vars' in extra_list:
            # 如指定 props 则附加函数变量信息
            vars_dict = VarsService.extract_vars(file_id, func_addr)
            infos_dict['vars'] = vars_dict

    infos_dict['vulnerabe'] = {
        'flag': '0',
        'desc': '非脆弱性函数'
    }  # 0:非脆弱性函数 1:脆弱性函数
    infos_dict['taint'] = {'flag': '0', 'desc': '非污点函数'}  # 0:非污点函数 1:非污点函数
    func_name = infos_dict.get('function_name')

    if func_name is not None:
        vulner_info = func_vulner_col.find_one(
            {'func_name': {
                '$regex': func_name
            }})

        if vulner_info is not None:
            infos_dict['vulnerabe'] = {
                'flag': '1',
                'desc': '脆弱性函数'
            }  # 0:非脆弱性函数 1:脆弱性函数

        taint_info = func_taint_col.find_one(
            {'func_name': {
                '$regex': func_name
            }})

        if taint_info is not None:
            infos_dict['taint'] = {
                'flag': '1',
                'desc': '污点函数'
            }  #  0:非污点函数 1:非污点函数

    # 保存操作日志
    LogRecords.save('',
                    category='query',
                    action='查询函数分析信息',
                    desc='查询代码分析后的函数信息,文件ID=%s,函数地址=0x%x' %
                    (file_id, func_addr))
    return sys_app_ok_p(infos_dict)
コード例 #9
0
def pack_exec_files_tree(request):
    pack_id, tree_type = ReqParams.many(request, ['pack_id', 'tree_type'])

    start_check_component_task(pack_id)
    # # # 检查组件关联
    # # check_component(pack_id, FileType.EXEC_FILE)
    # # 修改为任务处理方式进行检查组件关联 关联组件标记,相似度匹配计算,标记漏洞(version/edbid)
    # # 启动编译任务
    # extra_info = {'task_type': TaskType.COMPONENT_CHECK,
    #               'task_name': '检查组件关联',
    #               'task_desc': '检查组件关联,相似度匹配计算,标记漏洞(version/edbid)'}
    # task = MyTask(check_component, (pack_id,), extra_info=extra_info)
    # task_id = task.get_task_id()

    # 读取所有可执行文件
    exec_list = FwFileDO.search_files_of_pack(pack_id, FileType.EXEC_FILE)

    if tree_type is None or len(tree_type) == 0 or tree_type == 'normal':
        # file_path_insert_into_tree 树,初始化为字典
        tree_type = 'normal'
        exec_tree = {}
    elif tree_type == 'antd':
        # file_path_insert_into_antd_tree 树,初始化为数组
        exec_tree = []
    else:
        tree_type = 'normal'
        exec_tree = {}

    # 对每个文件做树的各级节点定位和创建
    for exec_file in exec_list:
        # 获取文件路径
        file_path = exec_file['file_path']
        file_id = exec_file['file_id']

        component = exec_file['component']
        # if exec_file['component'] is not None:
        #     component = exec_file['component']
        # else:
        #     component = 0

        if file_path is None or len(file_path) == 0:
            continue

        if tree_type == 'normal':
            MyTree.file_path_insert_into_tree(exec_tree, file_path, file_id,
                                              component)
        elif tree_type == 'antd':
            MyTree.file_path_insert_into_antd_tree(exec_tree, file_path,
                                                   file_id, component)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='读取固件包文件结构',
                    desc='获取指定固件包(ID=%s)的文件结构(模式为:%s)' % (pack_id, tree_type))

    return sys_app_ok_p(exec_tree)
コード例 #10
0
def test_angr_constraints(request):
    # state 的 constraints
    file_id, file_name, func_addr = ReqParams.many(request, ['file_id', 'file_name', 'func_addr.hex'])
    file_path = os.path.join(MyPath.samples(), file_name)

    project = angr.Project(file_path, load_options={"auto_load_libs": False})
    cfg = project.analyses.CFG()

    return sys_app_ok()
コード例 #11
0
def test_angr_vars(request):
    file_id, file_name, func_addr = ReqParams.many(request, ['file_id', 'file_name', 'func_addr.hex'])

    func_parse = FunctionParse(file_id, func_addr)
    props = func_parse.get_props()

    # _test_func(file_name)

    return sys_app_ok_p(props)
コード例 #12
0
def taintmodify(request):
    # 从请求中取参数:文件 ID
    func_name, hazard, solution = ReqParams.many(request, ['func_name', 'hazard', 'solution'], protocol='POST')

    TaintdictDO.update(func_name, hazard, solution)
    # 保存操作日志
    LogRecords.save('', category='statistics', action='自定义污点函数-删除',
                    desc='污点函数(func_name=%s)的信息,' % func_name)

    return sys_app_ok_p([])
コード例 #13
0
def test_angr_identifier(request):
    file_id, file_name, func_addr = ReqParams.many(request, ['file_id', 'file_name', 'func_addr.hex'])
    file_path = os.path.join(MyPath.samples(), file_name)

    project = angr.Project(file_path, load_options={"auto_load_libs": False})
    # p = angr.Project(os.path.join(bin_location, "tests", "i386", "identifiable"))
    idfer = project.analyses.Identifier(require_predecessors=False)
    seen = dict()
    for addr, symbol in idfer.run():
        seen[addr] = symbol

    return sys_app_ok()
コード例 #14
0
def read_sys_config(request):
    read_all = ReqParams.one(request, 'all_config.int')

    # 从数据库中读取系统配置
    config = SystemConfig.read_db(read_all)

    # 保存操作日志
    LogRecords.save(config,
                    category='system_config',
                    action='读取系统配置',
                    desc='读取系统各项配置参数')

    return sys_app_ok_p(config)
コード例 #15
0
def taintdel(request):
    # 从请求中取参数:文件 ID
    func_name = ReqParams.one(request, 'func_name')
    ret = TaintdictDO.delete(func_name)

    # 保存操作日志
    LogRecords.save('', category='statistics', action='自定义污点函数-删除',
                    desc='污点函数(func_name=%s)的信息,' % func_name)

    if ret:
        return sys_app_ok_p('删除成功')
    else:
        return sys_app_ok_p('删除失败')
コード例 #16
0
def taint_func_list(request):
    # 从请求中取参数:文件 ID
    file_id = ReqParams.one(request, 'file_id')

    # 查找函数列表分析结果
    # 查询文件 CFG 分析的标记
    is_cfg = CfgAnalyzeService.has_cfg_analyze(file_id)
    if not is_cfg:
        # 启动分析任务
        task_id = CfgAnalyzeService.start_cfg_task(file_id)
        # 保存操作日志
        LogRecords.save({
            'task_id': task_id,
            'file_id': file_id
        },
                        category='analysis',
                        action='分析CFG',
                        desc='对二进制文件做调用流程图分析')

        # 返回响应:任务初始化的信息
        return sys_app_ok_p(MyTask.fetch_exec_info(task_id))

    # 启动分析任务
    functions = FilesService.functions_list(file_id)
    if len(functions) == 0:
        return sys_app_err(Error.FW_FILE_NO_CFG_ANALYZE)

    taint_func_list = []

    taint_funcs = []

    taint_list = func_taint_col.find()

    for taint_info in taint_list:
        taint_funcs.append(taint_info.get('func_name'))
    for func_info in functions:
        func_name = func_info.get('name')
        for taint_func_info in taint_funcs:
            if taint_func_info == func_name:
                taint_func_list.append(taint_func_info)

    # 保存操作日志
    LogRecords.save('',
                    category='query',
                    action='查询污点函数列表',
                    desc='查询指定固件文件(ID=%s)在代码分析中产生的函数列表' % file_id)

    return sys_app_ok_p({
        'taint_num': len(taint_func_list),
        'taint_func_list': taint_func_list
    })
コード例 #17
0
def test_zip_file(request):
    file_id = ReqParams.one(request, 'file_id')

    file_path = FwFilesStorage.export(file_id)
    if file_path is None:
        return sys_app_err('FW_FILE_NOT_FOUND')

    # compress_files = _test_zipfile(file_path)

    # compress_files = _test_patool(file_path)

    compress_files = _test_py7zr(file_path)

    return sys_app_ok_p(compress_files)
コード例 #18
0
def pack_edit(request):
    pack_id, manufacturer, model, version = ReqParams.many(
        request, ['pack_id', 'manufacturer', 'model', 'version'],
        protocol='POST')

    PackFileDO.save_manufacturer(pack_id, manufacturer, model, version)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='编辑指定固件包信息',
                    desc='编辑指定固件包信息 厂商 型号(ID=%s)的信息' % pack_id)

    return sys_app_ok_p([])
コード例 #19
0
def pack_info(request):
    pack_id = ReqParams.one(request, 'pack_id')

    # 读取指定固件包的信息
    pack_service = PackInfoService(pack_id, None)
    info = pack_service.pack_summary()

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='查询包信息',
                    desc='查询指定固件包(ID=%s)的信息,统计其文件数量,查询任务信息' % pack_id)

    return sys_app_ok_p(info)
コード例 #20
0
def async_com_download(request):
    com_download_url = ReqParams.one(request, 'url', protocol='POST')
    # 启动下载任务
    extra_info = {'task_type': TaskType.REMOTE_DOWNLOAD,
                  'task_name': '组件源码下载',
                  'task_desc': '下载组件源码入库存储桶'}
    task = MyTask(_proc_component_tasks, (com_download_url, MyPath.component()), extra_info=extra_info)
    task_id = task.get_task_id()

    # 保存操作日志
    LogRecords.save({'task_id': task_id}, category='download', action='组件源码下载',
                    desc='下载组件源码入库存储桶')

    # 返回响应:任务初始化的信息
    return sys_app_ok_p(MyTask.fetch_exec_info(task_id))
コード例 #21
0
def test_angr_cfg(request):
    file_name = ReqParams.one(request, 'file_name')


    file_path = os.path.join(MyPath.samples(), file_name)
    project = angr.Project(file_path, load_options={'auto_load_libs': False})
    main_symbol = project.loader.main_object.get_symbol('main')
    start_addr = main_symbol.rebased_addr
    start_state = project.factory.blank_state(addr=start_addr)
    start_state.stack_push(0x0)
    project.factory.full_init_state(add_options={angr.options.STRICT_PAGE_ACCESS, angr.options.ENABLE_NX,
                                         angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY, angr.options.USE_SYSTEM_TIMES})
    cfg = project.analyses.CFG()
    functions = cfg.kb.functions
    return sys_app_ok_p(functions)
コード例 #22
0
def info(request):
    pack_id = ReqParams.one(request, 'pack_id')

    com_info = PackCOMFileDO.fetch_pack(pack_id)
    # 读取指定固件包的信息
    files_stat = get_sourcecode_files_stat(pack_id)
    pack_info = dict(com_info, **files_stat)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='查询组件源码包信息',
                    desc='查询组件源码包的信息,统计其文件数量,查询任务信息')

    return sys_app_ok_p(pack_info)
コード例 #23
0
def async_fwdownload(request):
    # 获取下载URL
    fw_download_url, ftp_user, ftp_password = ReqParams.many(request, ['url', 'user', 'password'], protocol='POST')

    # 启动下载任务
    extra_info = {'task_type': TaskType.REMOTE_DOWNLOAD,
                  'task_name': '固件下载',
                  'task_desc': '下载固件入库存储桶并进行文件抽取操作'}
    task = MyTask(_proc_tasks, (fw_download_url, settings.FW_PATH, ftp_user, ftp_password), extra_info=extra_info)
    task_id = task.get_task_id()

    # 保存操作日志
    LogRecords.save({'task_id': task_id}, category='download', action='固件下载',
                    desc='下载固件入库存储桶并进行文件抽取操作')

    # 返回响应:任务初始化的信息
    return sys_app_ok_p(MyTask.fetch_exec_info(task_id))
コード例 #24
0
def taintadd(request):
    # 从请求中取参数:文件 ID
    func_name, hazard, solution = ReqParams.many(request, ['func_name', 'hazard', 'solution'], protocol='POST')

    # find func_name in taint_dict
    if TaintdictDO.search_func_name(func_name) is None:
        print("add func_name")
        # 新的 fun ID
        fun_id = StrUtils.uuid_str()
        TaintdictDO.save(fun_id, func_name, hazard, solution)

        # 保存操作日志
        LogRecords.save('', category='statistics', action='自定义污点函数-增加',
                        desc='污点函数(ID=%s)的信息,' % fun_id)
        return sys_app_ok_p('添加成功')
    else:
        print("already has func_name")
        return sys_app_ok_p(['函数已存在'])
コード例 #25
0
def list_name(request):
    component_name = ReqParams.one(request, 'name')
    com_info = PackCOMFileDO.fetch_name(component_name)
    """ 获取源码包所有的文件统计信息 """
    # info_list = []
    # for pack in com_list:
    #     # 各个包的所含文件信息
    #     files_stat = get_sourcecode_files_stat(pack['pack_id'])
    #     pack_info = dict(pack, **files_stat)
    #     info_list.append(pack_info)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='组件源码查询_按名称查询',
                    desc='组件源码查询_按名称查询')

    return sys_app_ok_p(com_info)
コード例 #26
0
def list_make(request):
    print('list_make')
    pack_id, arch, tree_type, component_name = ReqParams.many(
        request, ['pack_id', 'arch', 'tree_type', 'component_name'])

    # 读取所有可执行文件
    exec_list = MakeCOMFileDO.search_files_of_pack(pack_id, FileType.MAKE_FILE,
                                                   arch, component_name)

    if tree_type is None or len(tree_type) == 0 or tree_type == 'normal':
        # file_path_insert_into_tree 树,初始化为字典
        tree_type = 'normal'
        exec_tree = {}
    elif tree_type == 'antd':
        # file_path_insert_into_antd_tree 树,初始化为数组
        exec_tree = []
    else:
        tree_type = 'normal'
        exec_tree = {}

    # 对每个文件做树的各级节点定位和创建
    for exec_file in exec_list:
        # 获取文件路径
        path = exec_file['file_path']
        # 保留make_component之后目录
        file_path = path.split('make_component')[1]
        file_id = exec_file['file_id']
        if file_path is None or len(file_path) == 0:
            continue

        if tree_type == 'normal':
            MyTree.file_path_insert_into_tree(exec_tree, file_path, file_id)
        elif tree_type == 'antd':
            MyTree.file_path_insert_into_antd_tree(exec_tree, file_path,
                                                   file_id)

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='读取固件包文件结构',
                    desc='获取指定固件包(ID=%s)的文件结构(模式为:%s)' % (pack_id, tree_type))

    return sys_app_ok_p(exec_tree)
コード例 #27
0
def test(request):
    value = ReqParams.one(request, 'value', protocol='GET')
    # 启动下载任务
    extra_info = {
        'task_type': TaskType.REMOTE_DOWNLOAD,
        'task_name': 'test组件源码下载',
        'task_desc': 'test下载组件源码入库存储桶'
    }
    task = MyTask(_proc_inverted_tasks, (value, MyPath.component()),
                  extra_info=extra_info)
    task_id = task.get_task_id()

    # 保存操作日志
    LogRecords.save({'task_id': task_id},
                    category='download',
                    action='test组件源码下载',
                    desc='test下载组件源码入库存储桶')

    # 返回响应:任务初始化的信息
    return sys_app_ok_p(MyTask.fetch_exec_info(task_id))
コード例 #28
0
def test_angr_plot_graph(request):
    file_id, file_name, func_addr = ReqParams.many(request, ['file_id', 'file_name', 'func_addr.hex'])
    if len(file_id) == 0:
        if len(file_name) == 0:
            return sys_app_err_p('INVALID_REQ_PARAM', 'file_id 或 file_name 必填其一')
        file_path = os.path.join(MyPath.samples(), file_name)
        project = angr.Project(file_path, load_options={'auto_load_libs': False})
        start_state = project.factory.blank_state(addr=func_addr)
        start_state.stack_push(0x0)
        with hook0(project):
            cfg = project.analyses.CFGEmulated(fail_fast=True, starts=[func_addr], initial_state=start_state,
                                         context_sensitivity_level=2, keep_state=True, call_depth=100, normalize=True)
        graph_file = os.path.join(MyPath.temporary(), StrUtils.uuid_str())
        plot_cfg(cfg, graph_file, asminst=True, vexinst=False, func_addr={func_addr: True},
                 debug_info=False, remove_imports=True, remove_path_terminator=True)
    else:
        func_parse = FunctionParse(file_id, func_addr)
        content = func_parse.cfg_graph()

    return sys_app_ok()
コード例 #29
0
def call_graph_a(request):
    # 从请求中取参数:文件 ID、函数地址、画图模式
    file_id, func_addr, simple = ReqParams.many(
        request, ['file_id', 'func_addr.hex', 'simple.int'])

    # 获取 call_graph 图形数据
    func_parse = FunctionParse(file_id, func_addr)
    graph_data = func_parse.cg_graph(simple != 1)

    # 保存操作日志
    LogRecords.save('',
                    category='query',
                    action='生成函数调用图',
                    desc='生成指定函数的调用关系图,文件ID=%s,函数地址=0x%x' %
                    (file_id, func_addr))

    return sys_app_ok_p({
        'file_id': file_id,
        'func_addr': func_addr,
        'call_graph': graph_data
    })
コード例 #30
0
def vuler_association(request):
    print('vuler_association')
    file_id, version, name, edb_id = ReqParams.many(
        request, ['file_id', 'version', 'name', 'edb_id'])

    rv = FwFileDO.set_component_extra_props(file_id, {
        'version': version,
        'name': name,
        'edb_id': edb_id
    })

    # 保存操作日志
    LogRecords.save('',
                    category='statistics',
                    action='组件手动漏洞关联',
                    desc='组件手动漏洞关联(漏洞编号 版本 名称)')

    if rv.matched_count == 1:
        return sys_app_ok_p('组件手动漏洞关联成功')
    else:
        return sys_app_ok_p('组件手动漏洞关联失败,文件未找到')