news 2026/7/22 18:08:29

(9-3-05)智能编程助手(IDA Pro+VS Code+MCP):变量与函数修改操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(9-3-05)智能编程助手(IDA Pro+VS Code+MCP):变量与函数修改操作

本部分的主要功能是提供对程序元素的修改能力,支持重命名局部变量、全局变量和函数,设置全局变量和局部变量的类型,以及修改函数原型。可以读取全局变量的编译时值,例如从C语言声明创建或更新自定义类型,并能刷新反编译器窗口以实时显示修改结果,方便逆向分析中的人工调整和类型标注。

(1)下面代码的功能是定义了一个名为 refresh_decompiler_widget 的函数,用于刷新反编译器窗口,确保所做的更改能够立即显示出来。

def refresh_decompiler_widget(): """刷新反编译器窗口""" widget = ida_kernwin.get_current_widget() if widget is not None: vu = ida_hexrays.get_widget_vdui(widget) if vu is not None: vu.refresh_ctext()

(2)下面代码的功能是定义了一个名为 refresh_decompiler_ctext 的函数,用于刷新指定函数地址的反编译文本,确保反编译器视图是最新的。

def refresh_decompiler_ctext(function_address: int): """刷新函数的反编译文本""" error = ida_hexrays.hexrays_failure_t() cfunc: ida_hexrays.cfunc_t = ida_hexrays.decompile_func(function_address, error, ida_hexrays.DECOMP_WARNINGS) if cfunc: cfunc.refresh_func_ctext()

(3)下面代码的功能是定义了一个名为 rename_local_variable 的函数,用于重命名函数中的局部变量。它首先获取函数对象,然后尝试重命名局部变量,如果失败则抛出错误。

@jsonrpc @idawrite def rename_local_variable( function_address: Annotated[str, "包含变量的函数地址"], old_name: Annotated[str, "变量的当前名称"], new_name: Annotated[str, "变量的新名称(空字符串表示默认名称)"] ): """重命名函数中的局部变量""" func = idaapi.get_func(parse_address(function_address)) if not func: raise IDAError(f"地址{function_address}处未找到函数") if not ida_hexrays.rename_lvar(func.start_ea, old_name, new_name): raise IDAError(f"重命名函数{hex(func.start_ea)}中的局部变量{old_name}失败") refresh_decompiler_ctext(func.start_ea)

(4)下面代码的功能是定义了一个名为 rename_global_variable 的函数,用于重命名全局变量。它通过获取全局变量的地址,然后尝试重命名该变量,如果失败则抛出错误。

@jsonrpc @idawrite def rename_global_variable( old_name: Annotated[str, "全局变量的当前名称"], new_name: Annotated[str, "全局变量的新名称(空字符串表示默认名称)"] ): """重命名全局变量""" ea = idaapi.get_name_ea(idaapi.BADADDR, old_name) if not idaapi.set_name(ea, new_name): raise IDAError(f"将全局变量{old_name}重命名为{new_name}失败") refresh_decompiler_ctext(ea)

(5)下面代码的功能是定义了一个名为 set_global_variable_type 的函数,用于设置全局变量的类型。它通过获取变量地址和新类型信息,然后应用新类型,如果失败则抛出错误。

@jsonrpc @idawrite def set_global_variable_type( variable_name: Annotated[str, "全局变量的名称"], new_type: Annotated[str, "变量的新类型"] ): """设置全局变量的类型""" ea = idaapi.get_name_ea(idaapi.BADADDR, variable_name) tif = get_type_by_name(new_type) if not tif: raise IDAError(f"解析的声明不是变量类型") if not ida_typeinf.apply_tinfo(ea, tif, ida_typeinf.PT_SIL): raise IDAError(f"应用类型失败")

(6)下面代码的功能是定义了一个名为 get_global_variable_value_by_name 的函数,用于读取全局变量的值(如果编译时已知)。它通过变量名获取变量地址,然后调用内部函数获取变量值。

@jsonrpc @idaread def get_global_variable_value_by_name(variable_name: Annotated[str, "全局变量的名称"]) -> str: """ 读取全局变量的值(如果编译时已知) 优先使用此函数,而非`data_read_*`函数。 """ ea = idaapi.get_name_ea(idaapi.BADADDR, variable_name) if ea == idaapi.BADADDR: raise IDAError(f"未找到全局变量{variable_name}") return get_global_variable_value_internal(ea)

(7)下面代码的功能是定义了一个名为 get_global_variable_value_at_address 的函数,该函数通过地址读取全局变量的值(如果编译时已知)。它解析地址并调用内部函数获取变量值。

@jsonrpc @idaread def get_global_variable_value_at_address(ea: Annotated[str, "全局变量的地址"]) -> str: """ 通过地址读取全局变量的值(如果编译时已知) 优先使用此函数,而非`data_read_*`函数。 """ ea = parse_address(ea) return get_global_variable_value_internal(ea)

(8)下面代码的功能是定义了一个名为 get_global_variable_value_internal 的内部函数,用于根据地址读取全局变量的值。它获取变量的类型信息,确定变量大小,然后根据大小读取并返回变量的值。

def get_global_variable_value_internal(ea: int) -> str: """内部函数:根据地址读取全局变量的值""" # 获取变量的类型信息 tif = ida_typeinf.tinfo_t() if not ida_nalt.get_tinfo(tif, ea): # 无类型信息,尝试通过名称推断大小 if not ida_bytes.has_any_name(ea): raise IDAError(f"无法获取地址{ea:#x}处变量的类型信息") size = ida_bytes.get_item_size(ea) if size == 0: raise IDAError(f"无法获取地址{ea:#x}处变量的类型信息") else: # 确定变量大小 size = tif.get_size() # 根据大小读取值 if size == 0 and tif.is_array() and tif.get_array_element().is_decl_char(): return_string = idaapi.get_strlit_contents(ea, -1, 0).decode("utf-8").strip() return f"\"{return_string}\"" elif size == 1: return hex(ida_bytes.get_byte(ea)) elif size == 2: return hex(ida_bytes.get_word(ea)) elif size == 4: return hex(ida_bytes.get_dword(ea)) elif size == 8: return hex(ida_bytes.get_qword(ea)) else: # 其他大小返回原始字节 return ' '.join(hex(x) for x in ida_bytes.get_bytes(ea, size))

(9)下面代码的功能是定义了一个名为 rename_function 的函数,该函数用于重命名函数。首先获取函数对象,然后尝试重命名函数,如果失败则抛出错误。

@jsonrpc @idawrite def rename_function( function_address: Annotated[str, "要重命名的函数地址"], new_name: Annotated[str, "函数的新名称(空字符串表示默认名称)"] ): """重命名函数""" func = idaapi.get_func(parse_address(function_address)) if not func: raise IDAError(f"地址{function_address}处未找到函数") if not idaapi.set_name(func.start_ea, new_name): raise IDAError(f"将函数{hex(func.start_ea)}重命名为{new_name}失败") refresh_decompiler_ctext(func.start_ea)

(10)下面代码的功能是定义了一个名为 set_function_prototype 的函数,该函数用于设置指定函数的原型。它首先获取函数对象,然后尝试应用新的函数原型,如果失败则抛出错误。成功应用后,会刷新反编译器窗口以显示更改。

@jsonrpc @idawrite def set_function_prototype( function_address: Annotated[str, "函数的地址"], prototype: Annotated[str, "函数的新原型"] ): """设置函数的原型""" func = idaapi.get_func(parse_address(function_address)) if not func: raise IDAError(f"地址{function_address}处未找到函数") try: tif = ida_typeinf.tinfo_t(prototype, None, ida_typeinf.PT_SIL) if not tif.is_func(): raise IDAError(f"解析的声明不是函数类型") if not ida_typeinf.apply_tinfo(func.start_ea, tif, ida_typeinf.PT_SIL): raise IDAError(f"应用类型失败") refresh_decompiler_ctext(func.start_ea) except Exception as e: raise IDAError(f"解析原型字符串失败:{prototype}")

(11)下面代码的功能是定义了一个名为 my_modifier_t 的类,该类继承自类ida_hexrays.user_lvar_modifier_t,用于修改局部变量的类型。类y_modifier_t包含了始化方法和修改局部变量类型的 modify_lvars 方法。

class my_modifier_t(ida_hexrays.user_lvar_modifier_t): """用于修改局部变量类型的自定义修改器""" def __init__(self, var_name: str, new_type: ida_typeinf.tinfo_t): ida_hexrays.user_lvar_modifier_t.__init__(self) self.var_name = var_name self.new_type = new_type def modify_lvars(self, lvars): """修改局部变量的类型""" for lvar_saved in lvars.lvvec: lvar_saved: ida_hexrays.lvar_saved_info_t if lvar_saved.name == self.var_name: lvar_saved.type = self.new_type return True return False

(12)下面代码的功能是定义了一个名为 parse_decls_ctypes 的函数,该函数通过 ctypes 解析 C 类型声明,主要用于在 Windows 平台上获取错误信息。

def parse_decls_ctypes(decls: str, hti_flags: int) -> tuple[int, str]: """通过ctypes解析声明(主要用于Windows平台获取错误信息)""" if sys.platform == "win32": import ctypes assert isinstance(decls, str), "decls必须是字符串" assert isinstance(hti_flags, int), "hti_flags必须是整数" c_decls = decls.encode("utf-8") c_til = None ida_dll = ctypes.CDLL("ida") ida_dll.parse_decls.argtypes = [ ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_int, ] ida_dll.parse_decls.restype = ctypes.c_int messages = [] @ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p) def magic_printer(fmt: bytes, arg1: bytes): if fmt.count(b"%") == 1 and b"%s" in fmt: formatted = fmt.replace(b"%s", arg1) messages.append(formatted.decode("utf-8")) return len(formatted) + 1 else: messages.append(f"不支持的magic_printer格式:{repr(fmt)}") return 0 errors = ida_dll.parse_decls(c_til, c_decls, magic_printer, hti_flags) else: # 注意:上述方法也可能在其他平台上工作,但未经过测试,且可变参数ABI存在差异。 errors = ida_typeinf.parse_decls(None, decls, False, hti_flags) messages = [] return errors, messages

(13)下面代码的功能是定义了一个名为 declare_c_type 的函数,该函数从 C 声明创建或更新本地类型。它解析 C 声明,如果解析成功则返回成功信息,否则抛出错误。

@jsonrpc @idawrite def declare_c_type( c_declaration: Annotated[str, "类型的C声明。例如:typedef int foo_t; struct bar { int a; bool b; };"] ): """从C声明创建或更新本地类型""" # PT_SIL:抑制警告对话框(尽管在此处似乎不必要) # PT_EMPTY:允许空类型(也不必要?) # PT_TYP:带结构体标签打印状态消息 flags = ida_typeinf.PT_SIL | ida_typeinf.PT_EMPTY | ida_typeinf.PT_TYP errors, messages = parse_decls_ctypes(c_declaration, flags) pretty_messages = "\n".join(messages) if errors > 0: raise IDAError(f"解析类型失败:\n{c_declaration}\n\n错误:\n{pretty_messages}") return f"成功\n\n信息:\n{pretty_messages}"

(14)下面代码的功能是定义了一个名为 set_local_variable_type 的函数,该函数用于设置局部变量的类型。它首先解析新类型,然后获取函数对象,尝试重命名局部变量,接着应用新类型,如果失败则抛出错误。

@jsonrpc @idawrite def set_local_variable_type( function_address: Annotated[str, "包含变量的反编译函数地址"], variable_name: Annotated[str, "变量名"], new_type: Annotated[str, "变量的新类型"] ): """设置局部变量的类型""" try: # 某些版本的IDA不支持此构造函数 new_tif = ida_typeinf.tinfo_t(new_type, None, ida_typeinf.PT_SIL) except Exception: try: new_tif = ida_typeinf.tinfo_t() # parse_decl需要类型后带分号 ida_typeinf.parse_decl(new_tif, None, new_type + ";", ida_typeinf.PT_SIL) except Exception: raise IDAError(f"解析类型失败:{new_type}") func = idaapi.get_func(parse_address(function_address)) if not func: raise IDAError(f"地址{function_address}处未找到函数") if not ida_hexrays.rename_lvar(func.start_ea, variable_name, variable_name): raise IDAError(f"未找到局部变量:{variable_name}") modifier = my_modifier_t(variable_name, new_tif) if not ida_hexrays.modify_user_lvars(func.start_ea, modifier): raise IDAError(f"修改局部变量失败:{variable_name}") refresh_decompiler_ctext(func.start_ea)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 21:07:15

Open-AutoGLM框架实战指南:5步实现企业级AI自动化部署

第一章:Open-AutoGLM框架实战指南:5步实现企业级AI自动化部署在企业级AI系统部署中,Open-AutoGLM框架通过模块化设计与自动化流水线能力,显著提升了模型集成与服务发布的效率。该框架支持从数据预处理、模型微调到API封装的一体化…

作者头像 李华
网站建设 2026/7/20 21:25:34

数据库包含多个患者的详细信息,包括他们的名字、入院日期、检查结果等。为了确保数据的准确性和便于分析,医生需要对患者数据进行排序,并将排序应用到相关的列中

下面内容摘录自《用R探索医药数据科学》专栏文章的部分内容(原文5050字)。 2篇2章13节:R语言中Stringr扩展包进行字符串的查阅、大小转换和排序_r语言stringi包-CSDN博客 R语言是数据科学和统计分析的强大工具,尤其在处理字符串数…

作者头像 李华
网站建设 2026/7/21 18:24:41

图标字体生成实战指南:告别图标管理混乱时代

图标字体生成实战指南:告别图标管理混乱时代 【免费下载链接】icons Official open source SVG icon library for Bootstrap. 项目地址: https://gitcode.com/gh_mirrors/ic/icons 还在为项目中图标文件散乱、加载缓慢而烦恼吗?🤔 每次…

作者头像 李华
网站建设 2026/7/20 13:18:45

Dify镜像支持Let‘s Encrypt自动签发SSL证书

Dify镜像集成Let’s Encrypt:让AI应用安全上线“零门槛” 在今天,一个没有HTTPS的Web服务几乎等同于“裸奔”。尤其当你的系统涉及大语言模型(LLM)、用户对话记录、知识库内容甚至API密钥时,明文传输无异于把钥匙留在门…

作者头像 李华
网站建设 2026/7/21 23:26:28

优质期刊分享! 医学-公共健康与卫生 学科领域!

期刊名称:JMIR Public Health and Surveillance JCR: Q1 中科院:2区 影响因子:3.5 ISSN: 2369-2960 期刊类型: SCI/SSCI/AHCI 收录数据库: SCI(SCIE) 学科领域:医学-公共健康…

作者头像 李华
网站建设 2026/7/21 14:05:36

5个场景下让文本识别效率翻倍的终极解决方案

5个场景下让文本识别效率翻倍的终极解决方案 【免费下载链接】Text-Grab Use OCR in Windows quickly and easily with Text Grab. With optional background process and popups. 项目地址: https://gitcode.com/gh_mirrors/te/Text-Grab 还在为截图文字无法编辑而烦恼…

作者头像 李华