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