idapython 版本api變化
api變化
官方文檔
基礎api
-->
為api變動:
idc.ScreenEA()--> idc.get_screen_ea() 擷取目前光标所在行的位址, 傳回一個 int 類型
idc.MaxEA()--> ida_ida.inf_get_min_ea() 擷取目前idb 的最小位址 和 最大位址
idc.SegName(ea) --> idc.get_segm_name(ea) ea是一個變量存儲目前位址, 這個api 是擷取目前位址所在的段
idc.GetDisasm(ea) 擷取目前位址的反彙編代碼
idc.GetMnem(ea) --> idc.print_insn_mnem 擷取目前位址的操作碼
idc.GetOpnd(ea,0)--> idc.print_operand 擷取目前位址的操作數,第二個參數表示哪一個操作數
idc.SegStart(ea) --> idc.get_segm_start 擷取目前位址的段起始位址
idc.SegEnd(ea) --> idc.get_segm_end 擷取目前位址的段尾位址
idc.NextSeg(ea) -->idc.get_next_seg 擷取下一個段的起始位址
idautils.Segments() 傳回一個可疊代的對象數組
idc.GetFunctionName(func) -->idc.get_func_name 通過位址,擷取函數的名稱
idautils.Functions() 傳回一個可疊代的函數首位址數組,
idaapi.get_func(ea) 擷取目前位址的函數首位址和尾位址
idc.NextFunction(ea) --> idc.get_next_func 擷取下一個函數位址
idc.PrevFunction(ea) --> idc.get_prev_func 擷取前一個函數位址
idc.GetFunctionAttr(ea,FUNCATTR_START) --> idc.get_func_attr 擷取一個函數的邊界位址
idc.GetDunctionAttr(ea,FUNCATTR_END) 擷取一個函數的邊界位址
idc.NextHead --> idc.next_head (目前位址,函數結尾) 擷取一個目前指令的下一行位址,第二個參數為結尾
通過api列印所有段名稱、起始位址和結束位址
import idautils
import idc
ea = here()
for seg in idautils.Segments():
print( idc.get_segm_name(seg),hex(idc.get_segm_start(seg)),hex(idc.get_segm_end(seg)))
#print(idc.GetDisasm(ea))
列印所有段中所有函數位址和函數名
import idautils
import idc
for func in idautils.Functions():
print (hex(func),idc.get_func_name(func))
擷取目前位址的函數的首位址和尾位址
import idautils
import idc
ea = idc.get_screen_ea()
print (ea)
func = idaapi.get_func(ea)
print (type(func))
print ("Start:0x%x , End:0x%x"%(func.start_ea,func.end_ea))
進階api
擁有 9種狀态
FUNC_NORET 表示某個函數是否有傳回值,本身的值是1,
FUN_FAR 不常見,用于标志程式是否使用分段記憶體, 值為2
FUN_USERFAR 不常見,官方文檔描述為 "user has specified far-ness of the function" 它的值是 32
FUN_LIB 表示用于尋找庫函數的代碼,它的值是4
FUNC_STATIC 作用域是被該函數在編譯的是否是一個靜态函數, 在 c語言中靜态函數被預設是認為全局的,如果作者吧這個函數定義為靜态函數,那麼這個函數隻能被本檔案中的函數通路.利用靜态函數的判定我們可以更好地了解源代碼的結構.
FUNC_FRAME 表示函數是否使用了 ebp寄存器, 使用ebp寄存器的程式一般是windows 程式
FUNC_BOTTOMBP 和 FUNC_FRAME 一樣,用于跟着幀指針(ebp),它的作用是識别函數中幀指針是否等于堆棧指針 esp
FUNC_HIDDEN 帶有FUNC_HIDDEN 标志的函數意味着他們是隐藏的,這個函數需要展開才能檢視
FUNC_THUNK 表示這個函數是否是一個 thunk 函數, thunk 函數表示的是一個簡單的跳轉函數
idautils.Funcltems(ea)
來擷取該函數中所有指令位址的集合
疊代器沒有 len() 屬性, 通過強制轉換将其放入 list中可以實作擷取指令的操作,
idc.next_head(ea)
idc.prev_head(ea)
擷取目前位址的下一條指令 或前一個 相當于 - 目前指令長度or +目前指令長度
ida_bytes.next_addr(ea)
、
ida_bytes.prev_addr(ea)
擷取目前位址的下一個位址 或前一個 相當于 -1 +1
使用api列印某個函數所有彙編代碼和位址
import idautils
import idc
ea = idc.get_screen_ea()
print (ea)
start = idc.get_func_attr(ea,FUNCATTR_START)
end = idc.get_func_attr(ea,FUNCATTR_END)
print("start:",hex(start))
print("end:",hex(end))
cur_addr = start
while cur_addr < end:
print (hex(cur_addr),idc.GetDisasm(cur_addr))
cur_addr = idc.next_head(cur_addr,end)
列印所有不會ret的函數
import idautils
import idc
ea = idc.get_screen_ea()
print (ea)
for func in idautils.Functions():
flags = idc.get_func_attr(func, FUNCATTR_FLAGS)
if flags & FUNC_NORET:
print (hex(func),"FUNC_NORET",get_func_name(func))
搜尋api
idc.find_binary(目前位址,flag,searcstr,radix=16)
來進行位元組或者二進制的搜尋, flag 代表搜尋方向或條件
- SEARCH_UP, SEARCH_DOWN 用來指明搜尋方向
- SEARCH_NEXT 用來擷取下一個已經找到的對象
- SEARCH_CASE 用來指明是否區分大小寫
- SEARCH_NOSHOW 來指明是否顯示搜尋的進度
- SEARCH_UNICODE 用來将所有搜尋字元串視為 Unicode
searcstr 是我們要查找的狀态,
radix 參數在寫處理器子產品時使用, 一般用不到, 留白即可
這個搜尋的是 彙編代碼中函數名稱之類的, 不是記憶體中的字元串
ida_bytes.is_code(f) 如果該位址為代碼則傳回True
ida_bytes.is_data(f) 如果該位址為資料傳回true
idc.idUnknown(f) 無法鑒别是資料還是代碼則傳回True
ida_bytes.is_head(f) 如果為函數開頭則傳回true
ida_bytes.is_tail(f) 如果為函數結尾則傳回true
ida_bytes.get_full_flags(位址) 以上一系列判斷函數,都不能直接傳遞位址, 需要通過GetFlags(ea) 對位址進行轉換
ida_search.find_code(位址,标志) 擷取下一個代碼指令的位址, 比如我們需要擷取某一塊資料的結尾時,如果目前的 ea 是代碼位址, idc.FindCode 将傳回下一個代碼指令的位址
ida_search.find_data(位址,标志) 擷取下一個資料塊類型位址的起始.
ida_search.find_imm(位址,标志,值)
搜尋位元組
import idautils
pattern = '48 01 D0' #add rax, rdx
addr = ida_ida.inf_get_min_ea()
for x in range(0,10):
addr = idc.find_binary(addr+1,SEARCH_DOWN,pattern)
print(hex(addr))
搜尋字元串
import idautils
pattern = "succeed."
cur_addr = ida_ida.inf_get_min_ea()
end_addr = ida_ida.inf_get_max_ea()
while cur_addr<end_addr:
cur_addr = ida_search.find_text(cur_addr,0,0,pattern,SEARCH_DOWN)
if cur_addr == idc.BADADDR:
break
else:
print (hex(cur_addr),idc.GetDisasm(cur_addr))
cur_addr = idc.next_head(cur_addr)
find_code擷取資料結尾位址
import idautils
ea = idc.get_screen_ea()
print (hex(ea),idc.GetDisasm(ea))
addr = idc.find_code(ea,SEARCH_DOWN|SEARCH_NEXT)
print (hex(addr),idc.GetDisasm(addr))
搜尋帶有0xa的位址
import idautils
addr = ida_ida.inf_get_min_ea()
while True:
addr,operand = ida_search.find_imm(addr,SEARCH_DOWN|SEARCH_NEXT,0xa)
#print(hex(addr),operand)
if addr != BADADDR:
print (hex(addr),idc.GetDisasm(addr),"Operand",operand)
else:
break
參考
idapython腳本編寫