天天看點

idapython 記錄idapython 版本api變化基礎api通過api列印所有段名稱、起始位址和結束位址列印所有段中所有函數位址和函數名擷取目前位址的函數的首位址和尾位址進階api使用api列印某個函數所有彙編代碼和位址列印所有不會ret的函數搜尋api搜尋位元組搜尋字元串find_code擷取資料結尾位址搜尋帶有0xa的位址參考

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腳本編寫

繼續閱讀