关于如何在 Python 中以编程方式映射、重命名和重新键入变量的简短 tl; dr 代码示例。
编辑:将代码添加到 set_lvar_type 以允许使用类型的字符串(我花了很长时间才解决这个问题)。现在您可以执行以下操作:
mapping = [ 'accum', 'v7', 'v4', 'shift', 'v5', 'v6', 'ptr', 'v2', 'v3' ]
for n, x, y in chunk_tuple(mapping, 3):
if map_lvar(x, y, ea) and \
set_lvar_type(y, 'int32_t', ea) and \
rename_lvar(y, n, ea):
print("set {}".format(n))

请注意,int作为一种类型不起作用,但int32_t会
其余代码见github。不要指望这会在 IDA 6.x 上工作,尽管可能会。我从来没有试过。
import re
from itertools import islice
import ida_hexrays
import idaapi
import idautils
import idc
def map_lvar(src, dst, ea):
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
lvars1 = [n for n in vu.cfunc.lvars if n.name == src]
lvars2 = [n for n in vu.cfunc.lvars if n.name == dst]
if len(lvars1) == 1 and len(lvars2) == 1:
print("mapping {} to {}".format(lvars1[0].name, lvars2[0].name))
# we might need to change the lvar type?
vu.set_lvar_type(lvars1[0], lvars2[0].type())
vu.map_lvar(lvars1[0], lvars2[0])
else:
print("couldn't find one of the vars {} or {}".format(src, dst))
def set_lvar_type(src, t, ea):
if isinstance(t, str):
type_tuple = idaapi.get_named_type(None, t, 1)
tif = idaapi.tinfo_t()
tif.deserialize(None, type_tuple[1], type_tuple[2])
if tif:
t = tif
else:
print("couldn't convert {} into tinfo_t".format(t))
return False
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
if not vu:
return False
lvars = [n for n in vu.cfunc.lvars if n.name == src]
if len(lvars) == 1:
print("changing type of {} to {}".format(lvars[0].name, t))
return vu.set_lvar_type(lvars[0], t)
else:
print("couldn't find var {}".format(src))
return False
def rename_lvar(src, dst, ea):
def make_unique_name(name, taken):
if name not in taken:
return name
fmt = "%s_%%i" % name
for i in range(3, 1024):
tmpName = fmt % i
if tmpName not in taken:
return tmpName
return "i_give_up"
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
names = [n.name for n in vu.cfunc.lvars]
if dst in names:
dst = make_unique_name(dst, names)
lvars = [n for n in vu.cfunc.lvars if n.name == src]
if len(lvars) == 1:
print("renaming {} to {}".format(lvars[0].name, dst))
vu.rename_lvar(lvars[0], dst, 1)
# how to close the view without a widget object?
# idautils.close_pseudocode (nope)
# ida_kerwin.close_widget (nope)
else:
print("couldn't find var {}".format(src))