当使用堆栈偏移用于经由获得的可变ida_hexrays.lvar_t.stk.get_stkoff()或ida_hexrays.vdloc_t.stkoff()结果“正确的”,和8或16之间变化作为手动测量字节出或相比于从所获得的结果:
id = idc.get_frame_id(here())
for member in idautils.StructMembers(id):
offset, name, size = member
不正确的偏移量来自:
func = idaapi.get_func(ea)
vu = idaapi.open_pseudocode(func.start_ea, 0)
[n.get_stkoff() for n in vu.cfunc.lvars if n.is_stk_var()]
[编辑]:差异似乎是由伪代码 vu 报告相对于最小 SPD 的偏移量引起的,而其他一切都使用序言后的 SPD(下面的代码)
def GetPseudoStackOffsetCorrection(funcea):
func = ida_funcs.get_func(funcea)
return func.frsize + func.frregs + idc.get_spd(idc.get_min_spd_ea(func.start_ea))
[编辑 2]:这种替代方法有时有效。它通过查看位于lvar_t.defea(假设“定义在 ea”)的 insn并从那里计算来起作用。然而 10% 的时间lvar.defea点在条件 jmp 上,所以再次 - 非常笨拙
def get_stkoff_from_lvar(lvar, debug=1):
ea = idc.get_item_head(lvar.defea)
func = ida_funcs.get_func(ea)
if not func:
return idc.BADADDR
for n in range(2):
if idc.get_operand_type(ea, n) == idc.o_displ:
offset = idc.get_operand_value(ea, n) + func.frsize - func.fpd
if debug:
lvar_name = lvar.name
sid = idc.get_frame_id(func.start_ea)
frame_name = idc.get_member_name(sid, offset)
print("[debug] offset:0x{:x}, lvar_name:{}, frame_name:{}"
.format(offset, lvar_name, frame_name))
return offset
[编辑]:除了kludges(我不想使用)我的
[...]“重命名,重新键入和重新映射”(使用正则表达式)包有问题,我最近注意到它没有更新“堆栈”(在程序集中可见)调用时的名称,vu.rename_lvar就像通过执行重命名时通常发生的那样N
如果没有准确的偏移量,代码在重var_18命名伪代码变量v1(例如)时就无法重命名相应的堆栈变量。
任何解决这个一般问题的方法都是受欢迎的,尽管优先考虑允许伪代码变量的正确堆栈位置的解决方案是最好的,因为我将很快通过flare-emu尝试“观察变量”。
这些是测试函数的一些结果,用于比较我收到的相互矛盾的结果,并向自己确认没有神奇的“只扣除 func.frregs”类型的答案。
功能 1.
func.flags : FUNC_FRAME | FUNC_PURGED_OK | FUNC_SP_READY
func.frregs : 8
func.frsize : c0
func.fpd : a0
ida_frame.frame_off_retaddr : c8
ida_frame.frame_off_lvars : 0
ida_frame.frame_off_args : d0
ida_frame.frame_off_savregs : c0
name lvar_offset1 stk_offset
-------------- ------------ ----------
range 0x30 0x28
guide 0x38 0x30
ImageBase 0x58 0x50
_stack_padding 0xd8 0xd0
功能二
func.flags : FUNC_FRAME | FUNC_PURGED_OK | FUNC_SP_READY
func.frregs : 8
func.frsize : 1c0
func.fpd : 190
ida_frame.frame_off_retaddr : 1c8
ida_frame.frame_off_lvars : 0
ida_frame.frame_off_args : 1d0
ida_frame.frame_off_savregs : 1c0
name lvar_offset1 stk_offset
------------------------- ------------ ----------
lpTopLevelExceptionFilter 0x50 0x40
LibFileName 0x88 0x78
Handle 0xc8 0xb8
lpProcName 0x110 0x100
hObject 0x198 0x188
hModule 0x1a0 0x190
功能三
func.flags : FUNC_FRAME | FUNC_PURGED_OK | FUNC_SP_READY
func.frregs : 8
func.frsize : 40
func.fpd : 20
ida_frame.frame_off_retaddr : 48
ida_frame.frame_off_lvars : 0
ida_frame.frame_off_args : 50
ida_frame.frame_off_savregs : 40
name lvar_offset1 stk_offset
------ ------------ ----------
accum1 0x20 0x20
accum2 0x2c 0x2c
如果需要,我可以提供测试代码,虽然它不小。
[编辑:附上测试代码,警告:不漂亮]
# test code:
# sync_lvars_to_stk(func_ea)
def get_func_flag_names(f):
return [x for x in [k for k in dir(idc)
if k.startswith('FUNC_')]
if f.flags & getattr(idc, x)]
def _get_vu(ea, vu):
if vu: return vu
return idaapi.open_pseudocode(idaapi.get_func(ea).start_ea, 0)
def get_lvars(ea, vu=None):
vu = _get_vu(ea, vu)
return [n.get_stkoff() for n in vu.cfunc.lvars if n.is_stk_var()]
def dump_stkvars(ea=None, iteratee=None):
def get_member_tinfo(sid, offset):
s = ida_struct.get_struc(sid)
m = ida_struct.get_member(s, offset)
tif = ida_typeinf.tinfo_t()
try:
if ida_struct.get_member_tinfo(tif, m):
return tif
except TypeError:
pass
results = []
sid = idc.get_frame_id(ea)
for member in idautils.StructMembers(sid):
o = AttrDict()
o.offset, o.name, o.size = member
o.mid = idc.get_member_id(sid, o.offset)
o.name = idc.get_member_name(sid, o.offset)
o.size = idc.get_member_size(sid, o.offset)
o.flags = idc.get_member_flag(sid, o.offset)
tif = get_member_tinfo(sid, o.offset)
o.tifname = str(tif) if tif else ''
o.sid = sid
if callable(iteratee): iteratee(o)
results.append(o)
return results
def indexBy(o, key):
r = {}
for x in o:
r[x[key]] = x
return r
def sync_lvars_to_stk(ea, vu=None):
vu = _get_vu(ea, vu)
func = idaapi.get_func(ea)
print("\n{:28}: {}\n{:28}: {:3x}\n{:28}: {:3x}\n{:28}: {:3x}\n{:28}: {:3x}\n{:28}: {:3x}\n{:28}: {:3x}\n{:28}: {:3x}\n"
.format(
"func.flags", " | ".join(get_func_flag_names(func)),
"func.frregs", func.frregs,
"func.frsize", func.frsize,
"func.fpd", func.fpd,
"ida_frame.frame_off_retaddr", ida_frame.frame_off_retaddr(func),
"ida_frame.frame_off_lvars", ida_frame.frame_off_lvars(func),
"ida_frame.frame_off_args", ida_frame.frame_off_args(func),
"ida_frame.frame_off_savregs", ida_frame.frame_off_savregs(func),
))
stkvars = indexBy(dump_stkvars(ea), 'name')
lvars = []
if vu and func:
stk_lvars = [(n.name, n.tif.get_size(),
n.location.stkoff(),
) for n in vu.cfunc.lvars if n.location.is_stkoff()]
for name, size, offset in stk_lvars:
o = AttrDict()
o.update({
'name': name,
'size': size,
'lvar_offset': offset,
})
lvars.append(o)
lvars = indexBy(lvars, 'name')
lvar_names = lvars.keys()
for name in lvar_names:
if name in stkvars:
print({
'name': name,
'lvar_offset': lvars[name].lvar_offset,
'stk_offset': stkvars[name].offset,
})
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self