一份IDA Python的学习与使用记录

0x00 常见的遍历

函数的遍历

for fn in idautils.Functions():
    print hex(fn), idc.get_func_name(fn)

除此之外,还可以使用idc.get_next_func(ea)idc.get_prev_func(ea)获取下一个和上一个函数

block的遍历

ida_gdl.py中定义了FlowChart和BasicBlock两个类
idaapi.FlowChart()可针对函数或者一段区域生成图
函数内block的遍历

f_blocks = idaapi.FlowChart(idaapi.get_func(fn), flags=idaapi.FC_PREDS)
for block in f_blocks:
    print hex(block.start_ea)

其中指定FC_PREDS,可用来查看block的前驱节点
block后继节点的遍历

for succ in block.succs():
    print hex(succ.start_ea)

block前驱节点的遍历

for pred in block.preds():
    print hex(pred.start_ea)

如果preds()返回的是空集,检查flags是否被设置成FC_PREDS,更详细的flag资料见[https://www.hex-rays.com/products/ida/support/sdkdoc/group___f_c__.html]
查看指定的block

id = 0x1
f_blocks = idaapi.FlowChart(idaapi.get_func(fn), flags=idaapi.FC_PREDS)
block = f_blocks[id]
print block.id

汇编指令的遍历

BasicBlock类中这样定义的block:[start_ea, end_ea)
遍历block中的所有汇编指令

curr_addr = block.start_ea
while curr_addr < block.end_ea:
    print idc.GetDisasm(curr_addr)
    curr_addr = idc.NextHead(curr_addr, block.end_ea)

如果需要获得block的最后一条指令,可以这样写:

addr = idc.PrevHead(block.end_ea)
print idc.GetDisasm(addr)

0x01 数据的访问

函数与函数地址

  • 获取函数名称 idc.get_func_name(ea),ea在函数内部即可
  • 获取函数属性 idc.get_func_attr(ea, attr),这可以用来查看函数的首位地址,函数的FLAG等
idc.get_func_attr(ea, FUNCATTR_START)
idc.get_func_attr(ea, FUNCATTR_END)
idc.get_func_attr(ea, FUNCATTR_FLAGS)

指令

  • 获取助记符 idc.print_insn_mnem(ea)
  • 获取操作数 print_operand(ea, n)
  • 获取操作数类型 get_operand_type(ea, n)

0x02 Tips

为了方便在ida中直接输入使用,可以对Python代码整理成一行,下面是两个例子
查看当前函数的所有block

for block in idaapi.FlowChart(idaapi.get_func(idc.get_screen_ea())) : print "%d: [0x%x, 0x%x)" % ( block.id, block.startEA, block.endEA)

查看指定block的后继节点

id=0x1;successors=idaapi.FlowChart(idaapi.get_func(idc.get_screen_ea()))[id].succs()
for block in successors: print "%d: [0x%x, 0x%x)" % ( block.id, block.startEA, block.endEA)

0x03 相关的学习资料

posted @ 2020-03-26 20:04  go2sleep  阅读(2026)  评论(0编辑  收藏  举报