天天看点

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脚本编写

继续阅读