虽然 API 可能很麻烦,但在静态分析期间,您要查找的大部分信息都可以从 IDA“轻松”获得。其中一些有点通用,而其他部分需要根据处理器类型进行不同的处理。
要检查操作数是否对内存执行读或写访问,您可以使用以下命令:
import idaapi
import idautils
import idc
OPND_WRITE_FLAGS = {
0: idaapi.CF_CHG1,
1: idaapi.CF_CHG2,
2: idaapi.CF_CHG3,
3: idaapi.CF_CHG4,
4: idaapi.CF_CHG5,
5: idaapi.CF_CHG6,
}
OPND_READ_FLAGS = {
0: idaapi.CF_USE1,
1: idaapi.CF_USE2,
2: idaapi.CF_USE3,
3: idaapi.CF_USE4,
4: idaapi.CF_USE5,
5: idaapi.CF_USE6,
}
def print_insn_mem_interaction(ea):
insn = idautils.DecodeInstruction(ea)
# The features are needed for operand flags.
feature = insn.get_canon_feature()
for op in insn.Operands:
# You always get 6 operands. Some of them are set to `o_void` to indicate
# that they are not used.
if op.type == idaapi.o_void:
break
# There are 3 types of memory references in IDA. We want all 3.
is_mem = op.type in (idaapi.o_mem, idaapi.o_phrase, idaapi.o_displ)
# Extract per-operand read/write status from the feature.
is_write = feature & OPND_WRITE_FLAGS[op.n]
is_read = feature & OPND_READ_FLAGS[op.n]
if not is_mem:
# Operand does not access memory.
continue
# Ugly line for the display. Sorry.
action = 'memory {}'.format('/'.join(filter(bool, ('read' if is_read else None, 'write' if is_write else None))))
print 'Operand[{}]<{}> : {}'.format(op.n, idc.GetOpnd(ea, op.n), action)
但是,告诉访问的地址是另一回事。
o_displ
和o_phrase
操作数的解析特定于处理器类型,并且完全没有记录(实际上,文档说“随心所欲”)。如果您对适用于 x86 和 x64 的解析器感兴趣,可以在此处查看我的代码。
如果您需要使用任何其他架构,我建议您使用更脚本友好的反汇编程序。在这方面,Capstone可能是一个不错的选择。
最后,如果您需要实际地址,您可能不得不求助于动态分析。