帖子idr导出map 导入ida9.1 脚本问题。已修正脚本代码 - 吾爱破解 - 52pojie.cn
分析 Delphi 编译的文件
其中 BASE_ADJUSTMENT 的注释有点问题,测试了正常使用的情况(即dump在ope),给出对 BASE_ADJUSTMENT 的新注释
已测试在IDA9.2中完美运行
非dump在ope的情况需要修改 BASE_ADJUSTMENT ,注释中也备注的比较清除
[Python] 纯文本查看 复制代码 import os
import sys
import random
from idautils import *
from idaapi import *
import idc
import ida_name
import ida_funcs
import ida_nalt
# ---------------------- 配置部分 ----------------------
MAP_FILE_PATH = r"D:\learning\ida9.2\loadmap\41f718bcac1fed649693943444547f7e975a869273f21c107ecc035f68dac275.map" # 替换为你的.map文件路径
IMAGE_BASE = ida_nalt.get_imagebase()
# BASE_ADJUSTMENT: 将.map文件中的"段:偏移"地址转换为 IDA 实际地址的偏移量
# 比如对于 MAP 文件中的一行, parse_borland_symbol_line 函数修正地址
# 0001:00000060 system.kernel32.CloseHandle_00401060
# 由于存在 CloseHandle_00401060 ,会直接使用00401060地址,可以不用设置 BASE_ADJUSTMENT
# 如果不存在 CloseHandle_00401060 ,会使用0001:00000060计算地址 再加上 BASE_ADJUSTMENT
# 即 0001 << 4 + 00000060 = 00001060
# 但实际地址为 401060 ,所以此时 BASE_ADJUSTMENT 就是 IDA 的 IMAGE_BASE
# 大部分情况下设置为 IMAGE_BASE 即可
BASE_ADJUSTMENT = IMAGE_BASE # 特殊情况手动设置
# ----------------------------------------------------
def parse_borland_symbol_line(line, symbols_addresses):
"""解析Borland格式的.map文件行(修正地址计算)"""
line = line.strip()
if (
not line
or ":" not in line
or any(x in line for x in ["Start", "Address", "Program entry"])
):
return symbols_addresses
try:
parts = line.split()
seg_offset = parts[0]
seg, offset = seg_offset.split(":")
# 优先从符号名中提取完整地址(如 `Finalization_711A4A70` -> 0x711A4A70)
if "_" in parts[-1]:
full_addr_str = parts[-1].split("_")[-1]
if (
full_addr_str.isalnum() and len(full_addr_str) == 8
): # 检查是否为8位十六进制
linear_addr = int(full_addr_str, 16)
symbol_name = parts[-1]
symbols_addresses[linear_addr] = symbol_name
print(f"[DEBUG] 直接映射符号: 0x{linear_addr:08X} -> {symbol_name}")
return symbols_addresses
# 回退到段:偏移计算(需确保BASE_ADJUSTMENT正确)
linear_addr = (int(seg, 16) << 4) + int(offset, 16) + BASE_ADJUSTMENT
symbol_name = parts[-1]
symbols_addresses[linear_addr] = symbol_name
print(f"[DEBUG] 计算映射符号: 0x{linear_addr:08X} -> {symbol_name}")
except Exception as e:
print(f"[WARN] 跳过无效行: {line} (错误: {str(e)})")
return symbols_addresses
def is_name_used(name, exclude_ea=idc.BADADDR):
"""检查名称是否已被使用"""
for ea, current_name in Names():
if current_name == name and ea != exclude_ea:
return True
return False
def safe_rename(ea, new_name):
"""安全重命名函数(处理冲突和异常)"""
try:
# 清理旧名称(使用 SN_FORCE 而不是 SN_DELTAIL)
ida_name.set_name(ea, "", ida_name.SN_FORCE | ida_name.SN_NOWARN)
# 处理名称冲突
final_name = new_name
if is_name_used(new_name, ea):
final_name = f"{new_name}_{ea:08X}"
print(f"[NOTE] 名称冲突处理: {new_name} -> {final_name}")
# 强制重命名
if ida_name.set_name(ea, final_name, ida_name.SN_FORCE | ida_name.SN_NOWARN):
print(f"[SUCCESS] 重命名 0x{ea:08X}: {final_name}")
return True
else:
# 回退方案:添加随机后缀
random_suffix = random.randint(0, 999)
fallback_name = f"{final_name}_{random_suffix:03d}"
if ida_name.set_name(
ea, fallback_name, ida_name.SN_FORCE | ida_name.SN_NOWARN
):
print(f"[RETRY] 重命名回退: 0x{ea:08X} -> {fallback_name}")
return True
else:
print(f"[ERROR] 无法重命名 0x{ea:08X}(包括回退方案)")
return False
except Exception as e:
print(f"[ERROR] 重命名失败 @ 0x{ea:08X}: {str(e)}")
return False
# ---------------------- 主逻辑 ----------------------
print("=" * 60)
print(f"正在加载MAP文件: {MAP_FILE_PATH}")
print(f"IDA基址: 0x{IMAGE_BASE:08X}, 调整值: 0x{BASE_ADJUSTMENT:08X}")
print("=" * 60)
# 1. 加载MAP文件
all_symbols = {}
if not os.path.exists(MAP_FILE_PATH):
print(f"[ERROR] 文件不存在: {MAP_FILE_PATH}")
sys.exit(1)
else:
try:
with open(MAP_FILE_PATH, "r") as f:
in_publics = False
for line in f:
if "Address Publics by Value" in line:
in_publics = True
continue
if in_publics:
parse_borland_symbol_line(line, all_symbols)
print(f"[INFO] 成功加载 {len(all_symbols)} 个符号")
except Exception as e:
print(f"[ERROR] 读取MAP文件失败: {str(e)}")
sys.exit(1)
# 2. 应用符号到IDA函数
rename_count = 0
for seg_start in Segments():
for func_ea in Functions(seg_start, idc.get_segm_end(seg_start)):
if func_ea in all_symbols:
if safe_rename(func_ea, all_symbols[func_ea]):
rename_count += 1
else:
# 尝试匹配函数内的地址
for insn_ea in FuncItems(func_ea):
if insn_ea in all_symbols:
print(
f"[HINT] 发现函数内符号匹配: 0x{func_ea:08X} 包含 0x{insn_ea:08X} -> {all_symbols[insn_ea]}"
)
if safe_rename(func_ea, all_symbols[insn_ea]):
rename_count += 1
break
# 3. 结果统计
print("=" * 60)
print(f"处理完成!")
print(f"MAP符号总数: {len(all_symbols)}")
print(f"成功重命名函数: {rename_count}")
print(f"未匹配的符号: {len(all_symbols) - rename_count}")
if rename_count == 0:
print("\n[疑难解答]")
print("1. 检查基址调整值是否正确:")
print(f" IDA基址: 0x{IMAGE_BASE:08X}")
print(f" 当前调整值: 0x{BASE_ADJUSTMENT:08X}")
print("2. 手动测试示例(在IDA Python命令行中执行):")
if all_symbols:
sample_addr = next(iter(all_symbols))
print(
f" ida_name.set_name(0x{sample_addr:08X}, 'TEST_NAME', ida_name.SN_FORCE | ida_name.SN_NOWARN)"
)
print("=" * 60)
部分日志,未匹配函数有两个但是不影响,应该问题不大,具体原因没太深究
[Python] 纯文本查看 复制代码 ============================================================
正在加载MAP文件: D:\learning\ida9.2\loadmap\41f718bcac1fed649693943444547f7e975a869273f21c107ecc035f68dac275.map
IDA基址: 0x00400000, 调整值: 0x00400000
============================================================
[DEBUG] 直接映射符号: 0x00401060 -> system.kernel32.CloseHandle_00401060
......
[INFO] 成功加载 358 个符号
[SUCCESS] 重命名 0x00401060: system.kernel32.CloseHandle_00401060
......
============================================================
处理完成!
MAP符号总数: 358
成功重命名函数: 356
未匹配的符号: 2
============================================================ |