一份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 相关的学习资料
- The Beginner's Guide to IDAPython
- IDA/python目录下的
idc.py
,这份代码中几乎可以查到所有需要的接口 - http://scz.617.cn:8/misc/201811281121.txt