应用安全 --- IDA Pro脚本 之 批量导出反编译和反汇编
import idc import idaapi import idautils import os import redef sanitize_filename(name, max_length=100):"""清理文件名,移除非法字符并限制长度"""# 移除或替换非法字符name = re.sub(r'[<>:"/\\|?*]', '_', name)# 移除多余的下划线name = re.sub(r'_+', '_', name)# 限制长度if len(name) > max_length:name = name[:max_length]# 确保文件名不为空if not name or name.isspace():name = "unknown_function"return name.strip()def export_complete_function_info(output_dir="exported_functions"):""" 导出所有函数的反汇编和反编译代码(修复文件名问题)""" print(f"开始导出函数信息到目录: {output_dir}")# 创建输出目录(确保路径存在)try:if not os.path.exists(output_dir):os.makedirs(output_dir, exist_ok=True)print(f"目录已创建: {os.path.abspath(output_dir)}")except Exception as e:print(f"创建目录失败: {e}")# 使用当前目录作为备选output_dir = "."print(f"使用当前目录: {os.path.abspath(output_dir)}")# 获取函数列表functions = list(idautils.Functions())total_functions = len(functions)print(f"找到 {total_functions} 个函数")exported_count = 0hexrays_available = False# 检查Hex-Rays反编译器是否可用try:import ida_hexrayshexrays_available = Trueprint("Hex-Rays反编译器可用")except:print("Hex-Rays反编译器不可用,仅导出反汇编代码")for i, func_ea in enumerate(functions):func_name = idc.get_func_name(func_ea)# 创建安全的文件名safe_name = sanitize_filename(func_name)filename = f"{safe_name}_{func_ea:08X}.txt"filepath = os.path.join(output_dir, filename)# 进一步确保文件路径不会太长if len(filepath) > 200:# 如果路径太长,使用更短的文件名filename = f"func_{func_ea:08X}.txt"filepath = os.path.join(output_dir, filename)try:# 确保目录存在(再次检查)os.makedirs(os.path.dirname(filepath), exist_ok=True)with open(filepath, 'w', encoding='utf-8', errors='ignore') as f:# 写入函数基本信息f.write(f"函数名称: {func_name}\n")f.write(f"起始地址: 0x{func_ea:08X}\n")# 获取函数对象func = idaapi.get_func(func_ea)if func:f.write(f"结束地址: 0x{func.end_ea:08X}\n")f.write(f"函数大小: {func.end_ea - func.start_ea} 字节\n")f.write("\n" + "="*70 + "\n")f.write("反汇编代码 (包含地址信息):\n")f.write("="*70 + "\n\n")# 导出反汇编代码if func:ea = func.start_eawhile ea < func.end_ea and ea != idc.BADADDR:if idc.is_code(idc.get_full_flags(ea)):# 获取地址和反汇编指令address = f"0x{ea:08X}"disasm = idc.GetDisasm(ea)# 获取注释comment = idc.get_cmt(ea, 0)if comment:f.write(f"{address}: {disasm:<50} // {comment}\n")else:f.write(f"{address}: {disasm}\n")# 移动到下一条指令next_ea = idc.next_head(ea, func.end_ea)if next_ea == idc.BADADDR or next_ea <= ea:breakea = next_ea# 导出反编译代码(如果可用)if hexrays_available:f.write("\n" + "="*70 + "\n")f.write("反编译代码 (Hex-Rays):\n")f.write("="*70 + "\n\n")try:cfunc = ida_hexrays.decompile(func_ea)if cfunc:f.write(str(cfunc))else:f.write("// 反编译失败\n")except Exception as e:f.write(f"// 反编译错误: {str(e)}\n")else:f.write("\n// Hex-Rays反编译器不可用\n")exported_count += 1if i % 100 == 0: # 每100个函数打印一次进度print(f"进度: {i+1}/{total_functions}")except Exception as e:print(f"导出函数 {func_name} 时出错: {str(e)}")# 尝试使用更简单的文件名try:simple_filename = f"func_{func_ea:08X}.txt"simple_filepath = os.path.join(output_dir, simple_filename)with open(simple_filepath, 'w', encoding='utf-8', errors='ignore') as f:f.write(f"函数名称: {func_name}\n地址: 0x{func_ea:08X}\n")f.write(f"原始文件名过长,使用简化文件名保存\n")print(f"使用简化文件名成功保存: {simple_filename}")exported_count += 1except Exception as e2:print(f"简化文件名也失败: {e2}")print(f"导出完成! 成功导出 {exported_count}/{total_functions} 个函数")print(f"文件保存在: {os.path.abspath(output_dir)}")# 在IDA输出窗口显示完成信息idc.msg(f"\n函数导出完成: {exported_count}/{total_functions} 个函数已导出到 {output_dir}\n")# 简化版本:只使用地址作为文件名 def export_simple_version(output_dir="simple_export"):"""使用简化文件名导出,避免路径过长问题"""print("使用简化版本导出...")if not os.path.exists(output_dir):os.makedirs(output_dir, exist_ok=True)functions = list(idautils.Functions())exported_count = 0for func_ea in functions:func_name = idc.get_func_name(func_ea)filename = f"func_{func_ea:08X}.txt"filepath = os.path.join(output_dir, filename)try:with open(filepath, 'w', encoding='utf-8', errors='ignore') as f:f.write(f"Function: {func_name}\n")f.write(f"Address: 0x{func_ea:08X}\n\n")func = idaapi.get_func(func_ea)if func:f.write("Disassembly:\n")f.write("-" * 50 + "\n")ea = func.start_eawhile ea < func.end_ea:if idc.is_code(idc.get_full_flags(ea)):disasm = idc.GetDisasm(ea)f.write(f"0x{ea:08X}: {disasm}\n")next_ea = idc.next_head(ea, func.end_ea)if next_ea == idc.BADADDR:breakea = next_eaexported_count += 1except Exception as e:print(f"导出失败 {func_name}: {e}")print(f"简化版本导出完成: {exported_count} 个函数")# 立即执行导出(使用修复版本) if __name__ == "__main__":# 先尝试完整版本try:export_complete_function_info("exported_functions")except Exception as e:print(f"完整版本失败: {e}")print("尝试简化版本...")export_simple_version("simple_export")
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/911638.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!