news 2026/4/15 14:32:09

(9-3-03)智能编程助手(IDA Pro+VS Code+MCP):

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(9-3-03)智能编程助手(IDA Pro+VS Code+MCP):

(9)下面代码的功能是定义了一个名为 get_function_by_name 的函数,通过函数名获取函数信息。该函数首先尝试直接通过名称获取函数地址,如果失败则使用已解析的函数名到地址的映射来查找,如果仍然未找到则抛出 IDAError 异常。

@jsonrpc @idaread def get_function_by_name( name: Annotated[str, "要获取的函数名"] ) -> Function: """通过函数名获取函数信息""" function_address = idaapi.get_name_ea(idaapi.BADADDR, name) if function_address == idaapi.BADADDR: # 如果映射未创建,则创建它 if len(DEMANGLED_TO_EA) == 0: create_demangled_to_ea_map() # 尝试在映射中查找函数,否则抛出错误 if name in DEMANGLED_TO_EA: function_address = DEMANGLED_TO_EA[name] else: raise IDAError(f"未找到名为{name}的函数") return get_function(function_address)

(10)下面代码的功能是定义了两个函数 get_function_by_address 和 get_current_function,分别用于通过地址获取函数信息和获取当前用户选中的函数信息。这两个函数都使用了 @jsonrpc 和 @idaread 装饰器。

@jsonrpc @idaread def get_function_by_address( address: Annotated[str, "要获取的函数地址"] ) -> Function: """通过地址获取函数信息""" return get_function(parse_address(address)) @jsonrpc @idaread def get_current_address() -> str: """获取用户当前选中的地址""" return hex(idaapi.get_screen_ea()) @jsonrpc @idaread def get_current_function() -> Optional[Function]: """获取用户当前选中的函数""" return get_function(idaapi.get_screen_ea())

(11)下面代码的功能是定义了一个名为 convert_number 的函数,用于将数值(十进制、十六进制)转换为不同的表示形式,包括字节、ASCII字符串、二进制等。该函数还处理了数值大小的估算和转换过程中可能的溢出错误。

@jsonrpc def convert_number( text: Annotated[str, "要转换的数值的文本表示"], size: Annotated[Optional[int], "变量的字节大小"] ) -> ConvertedNumber: """将数值(十进制、十六进制)转换为不同的表示形式""" try: value = int(text, 0) except ValueError: raise IDAError(f"无效的数值:{text}") # 估算数值大小 if not size: size = 0 n = abs(value) while n: size += 1 n >>= 1 size += 7 size //= 8 # 将数值转换为字节 try: bytes_data = value.to_bytes(size, "little", signed=True) except OverflowError: raise IDAError(f"数值{text}对于{size}字节来说太大") # 将字节转换为ASCII字符串 ascii_str = "" for byte in bytes_data.rstrip(b"\x00"): if 32 <= byte <= 126: ascii_str += chr(byte) else: ascii_str = None break return ConvertedNumber( decimal=str(value), hexadecimal=hex(value), bytes=bytes_data.hex(" "), ascii=ascii_str, binary=bin(value) ) T = TypeVar("T")

(12)下面代码的功能是定义了一个名为 paginate 的函数,用于对数据进行分页处理。该函数接受数据列表、偏移量和数量参数,返回分页后的数据和下一个偏移量。

def paginate(data: list[T], offset: int, count: int) -> Page[T]: """对数据进行分页处理""" if count == 0: count = len(data) next_offset = offset + count if next_offset >= len(data): next_offset = None return { "data": data[offset:offset + count], "next_offset": next_offset, }

(13)下面代码的功能是定义了一个名为 pattern_filter 的函数,根据模式过滤数据。该函数目前尚未实现具体的匹配逻辑,但提供了一个框架,用于根据给定的模式和键过滤数据列表。

def pattern_filter(data: list[T], pattern: str, key: str) -> list[T]: """根据模式过滤数据(大小写不敏感的包含匹配)""" if not pattern: return data # TODO:实现/regex/语法的匹配 def matches(item: T) -> bool: return pattern.lower() in item[key].lower() return list(filter(matches, data))

(14)下面代码的功能是定义了一个名为 list_functions 的函数,用于分页列出数据库中的所有函数。该函数获取所有函数的列表,然后使用 paginate 函数进行分页处理,并使用 @jsonrpc 和 @idaread 装饰器注册为 JSON-RPC 方法。

@jsonrpc @idaread def list_functions( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的函数数量(默认100,0表示剩余所有)"] ) -> Page[Function]: """分页列出数据库中的所有函数""" functions = [get_function(address) for address in idautils.Functions()] return paginate(functions, offset, count)

9.4.3 程序元素枚举与交叉引用

本部分的主要功能是实现程序各类元素的枚举功能,可分页列出函数、全局变量、导入符号、字符串及本地类型(如结构体、枚举),并支持按条件过滤结果。提供函数反编译为伪代码、提取汇编代码的能力,包含地址、指令、注释等详细信息。同时支持查询指定地址或结构体字段的交叉引用,获取程序入口点,以及为地址设置注释,满足静态分析对程序结构的探索需求。

(1)下面代码的功能是定义了一个名为 list_globals_filter 的函数,该函数使用户能够根据提供的过滤器分页列出数据库中匹配的全局变量。它首先收集所有全局变量,然后应用过滤器,并最终返回分页后的结果。

@jsonrpc @idaread def list_globals_filter( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的全局变量数量(默认100,0表示剩余所有)"], filter: Annotated[str, "应用于列表的过滤器(必填参数,空字符串表示无过滤)。大小写不敏感的包含匹配或/regex/语法"] ) -> Page[Global]: """分页、带过滤地列出数据库中匹配的全局变量""" globals_list = [] for addr, name in idautils.Names(): # 跳过函数(仅保留全局变量) if not idaapi.get_func(addr): globals_list.append(Global(address=hex(addr), name=name)) globals_list = pattern_filter(globals_list, filter, "name") return paginate(globals_list, offset, count)

(2)下面代码的功能是定义了一个名为 list_globals_filter 的函数,该函数使用户能够根据提供的过滤器分页列出数据库中匹配的全局变量。它首先收集所有全局变量,然后应用过滤器,并最终返回分页后的结果。

@jsonrpc def list_globals( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的全局变量数量(默认100,0表示剩余所有)"] ) -> Page[Global]: """分页列出数据库中的所有全局变量""" return list_globals_filter(offset, count, "")

(3)下面代码的功能是定义了一个名为 list_imports 的函数,该函数分页列出所有导入的符号及其名称和模块。它通过枚举所有导入模块和符号,收集这些信息,并最终返回分页后的结果。

@jsonrpc @idaread def list_imports( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的导入符号数量(默认100,0表示剩余所有)"] ) -> Page[Import]: """分页列出所有导入的符号及其名称和模块""" nimps = ida_nalt.get_import_module_qty() rv = [] for i in range(nimps): module_name = ida_nalt.get_import_module_name(i) if not module_name: module_name = "<未命名>" def imp_cb(ea, symbol_name, ordinal, acc): if not symbol_name: symbol_name = f"#{ordinal}" acc.append(Import(address=hex(ea), imported_name=symbol_name, module=module_name)) return True imp_cb_w_context = lambda ea, symbol_name, ordinal: imp_cb(ea, symbol_name, ordinal, rv) ida_nalt.enum_import_names(i, imp_cb_w_context) return paginate(rv, offset, count)

(4)下面代码的功能是定义了一个名为 list_strings_filter 的函数,该函数使用户能够根据提供的过滤器分页列出数据库中匹配的字符串。它首先收集所有字符串,然后应用过滤器,并最终返回分页后的结果。

@jsonrpc @idaread def list_strings_filter( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的字符串数量(默认100,0表示剩余所有)"], filter: Annotated[str, "应用于列表的过滤器(必填参数,空字符串表示无过滤)。大小写不敏感的包含匹配或/regex/语法"] ) -> Page[String]: """分页、带过滤地列出数据库中匹配的字符串""" strings_list = [] for item in idautils.Strings(): try: string = str(item) if string: strings_list.append( String(address=hex(item.ea), length=item.length, string=string) ) except: continue strings_list = pattern_filter(strings_list, filter, "string") return paginate(strings_list, offset, count)

(5)下面代码的功能是定义了一个名为 list_strings 的函数,该函数分页列出数据库中的所有字符串。这个函数实际上是对 list_strings_filter 函数的调用,但不使用任何过滤器,即列出所有字符串。

@jsonrpc def list_strings( offset: Annotated[int, "开始列出的偏移量(从0开始)"], count: Annotated[int, "要列出的字符串数量(默认100,0表示剩余所有)"] ) -> Page[String]: """分页列出数据库中的所有字符串""" return list_strings_filter(offset, count, "")

(6)下面代码的功能是定义了一个名为 list_local_types 的函数,该函数列出数据库中的所有本地类型,包括结构体、枚举等用户定义类型,以及它们的C声明。

@jsonrpc @idaread def list_local_types(): """列出数据库中的所有本地类型""" error = ida_hexrays.hexrays_failure_t() locals_list = [] idati = ida_typeinf.get_idati() type_count = ida_typeinf.get_ordinal_limit(idati) for ordinal in range(1, type_count): try: tif = ida_typeinf.tinfo_t() if tif.get_numbered_type(idati, ordinal): type_name = tif.get_type_name() if not type_name: type_name = f"<匿名类型 #{ordinal}>" locals_list.append(f"\n类型 #{ordinal}: {type_name}") if tif.is_udt(): # 如果是用户定义类型(结构体等) c_decl_flags = (ida_typeinf.PRTYPE_MULTI | ida_typeinf.PRTYPE_TYPE | ida_typeinf.PRTYPE_SEMI | ida_typeinf.PRTYPE_DEF | ida_typeinf.PRTYPE_METHODS | ida_typeinf.PRTYPE_OFFSETS) c_decl_output = tif._print(None, c_decl_flags) if c_decl_output: locals_list.append(f" C声明:\n{c_decl_output}") else: simple_decl = tif._print(None, ida_typeinf.PRTYPE_1LINE | ida_typeinf.PRTYPE_TYPE | ida_typeinf.PRTYPE_SEMI) if simple_decl: locals_list.append(f" 简单声明:\n{simple_decl}") else: message = f"\n类型 #{ordinal}: 获取信息失败。" if error.str: message += f": {error.str}" if error.errea != idaapi.BADADDR: message += f"来自(地址: {hex(error.errea)})" raise IDAError(message) except: continue return locals_list

(7)下面代码的功能是定义了一个名为 decompile_checked 的函数,该函数用于带检查的函数反编译,验证反编译器是否可用,并处理可能的错误。

def decompile_checked(address: int) -> ida_hexrays.cfunc_t: """带检查的函数反编译(验证反编译器是否可用)""" if not ida_hexrays.init_hexrays_plugin(): raise IDAError("Hex-Rays反编译器不可用") error = ida_hexrays.hexrays_failure_t() cfunc: ida_hexrays.cfunc_t = ida_hexrays.decompile_func(address, error, ida_hexrays.DECOMP_WARNINGS) if not cfunc: if error.code == ida_hexrays.MERR_LICENSE: raise DecompilerLicenseError("反编译器许可证不可用。请使用`disassemble_function`获取汇编代码。") message = f"地址{hex(address)}反编译失败" if error.str: message += f": {error.str}" if error.errea != idaapi.BADADDR: message += f"(地址: {hex(error.errea)})" raise IDAError(message) return cfunc

(8)下面代码的功能是定义了一个名为 decompile_function 的函数,用于反编译指定地址的函数,并返回反编译后的伪代码。如果IDA窗口处于活动状态,它还会打开伪代码窗口。

@jsonrpc @idaread def decompile_function( address: Annotated[str, "要反编译的函数地址"] ) -> str: """反编译指定地址的函数""" address = parse_address(address) cfunc = decompile_checked(address) if is_window_active(): ida_hexrays.open_pseudocode(address, ida_hexrays.OPF_REUSE) # 打开伪代码窗口 sv = cfunc.get_pseudocode() pseudocode = "" for i, sl in enumerate(sv): sl: ida_kernwin.simpleline_t item = ida_hexrays.ctree_item_t() addr = None if i > 0 else cfunc.entry_ea if cfunc.get_line_item(sl.line, 0, False, None, item, None): ds = item.dstr().split(": ") if len(ds) == 2: try: addr = int(ds[0], 16) except ValueError: pass line = ida_lines.tag_remove(sl.line) if len(pseudocode) > 0: pseudocode += "\n" if not addr: pseudocode += f"/* 行: {i} */ {line}" else: pseudocode += f"/* 行: {i}, 地址: {hex(addr)} */ {line}" return pseudocode
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/8 21:40:12

结合Jupyter Notebook实现数据科学问答分析

结合 Jupyter Notebook 实现数据科学问答分析 在企业数据分析实践中&#xff0c;一个老生常谈的问题是&#xff1a;业务人员有明确的分析需求&#xff0c;却无法直接操作数据&#xff1b;而数据团队忙于响应各类临时查询&#xff0c;疲于奔命。更糟糕的是&#xff0c;每次分析结…

作者头像 李华
网站建设 2026/3/27 17:02:21

【AI模型部署新突破】:为什么顶级开发者都在用Win+Open-AutoGLM组合?

第一章&#xff1a;WinOpen-AutoGLM组合的崛起背景近年来&#xff0c;人工智能与自动化技术的深度融合推动了新一代智能工作流系统的诞生。其中&#xff0c;“WinOpen-AutoGLM”组合因其在Windows平台上的高效集成能力、开源生态的灵活扩展性以及AutoGLM驱动的自然语言自动化执…

作者头像 李华
网站建设 2026/4/14 20:57:56

anything-llm前端界面体验报告:美观与实用兼备的设计理念

AnythingLLM前端界面体验报告&#xff1a;美观与实用兼备的设计理念 在大语言模型&#xff08;LLM&#xff09;技术席卷各行各业的今天&#xff0c;一个尖锐的问题浮出水面&#xff1a;我们是否真的需要每个人都成为AI工程师才能用好这些强大的工具&#xff1f;显然不是。越来越…

作者头像 李华
网站建设 2026/4/2 2:19:24

如何加强对客户选择华为云国际站代理商CloudDC专区的保障?

加强客户选择华为云国际站代理商 CloudDC 专区的保障&#xff0c;核心是构建 “资质 - 技术 - 服务 - 合规 - 成本 - 应急” 的全链路闭环&#xff0c;叠加代理商专属权益与落地兜底&#xff0c;用可量化的 SLA 与可执行的保障动作打消客户顾虑&#xff0c;提升决策确定性。以下…

作者头像 李华
网站建设 2026/4/15 13:23:54

8 个降AI率工具,研究生必备推荐!

8 个降AI率工具&#xff0c;研究生必备推荐&#xff01; AI降重工具&#xff1a;研究生论文的得力助手 在当前学术研究日益依赖人工智能技术的背景下&#xff0c;越来越多的研究生开始面临一个共同的问题——如何有效降低论文中的AIGC率&#xff0c;同时保持内容的逻辑性和语义…

作者头像 李华
网站建设 2026/4/3 18:27:50

破茧成蝶:软件测试工程师的专业成长路径与心法‌

在快速迭代的数字化时代&#xff0c;软件质量已成为企业的生命线。作为质量的守护者&#xff0c;软件测试工程师的角色日益重要&#xff0c;却也面临着技术爆炸、方法论革新和职业天花板等多重挑战。“测试专业成长”因此不再是一个可选话题&#xff0c;而是每一位从业者必须持…

作者头像 李华