IDA Python 常用API(持续更新)

环境:IDAPro 7.6

(注意IDAPro 7.4版本后,IDA Python的API版本与7.4之前的版本发生了很多变化,具体区别请看https://hex-rays.com/products/ida/support/ida74_idapython_no_bc695_porting_guide.shtml

常见模块

在IDA中.有三个重要的库.分别是IDC,idautils,idaapi

模块 功能
IDC 封装IDA与IDC函数的兼容性模块.
idautils 高级实用的模块
idaapi 允许访问更加底层的数据

获取IDA界面地址

功能 函数
取当前地址 idc.here() 或 idc.get_screen_ea()
获取最小地址(可以使用的) ida_ida.inf_get_min_ea()
获取最大地址(可以使用的) ida_ida.inf_get_max_ea()
获取所选范围的起始地址 idc.read_selection_start()
获取所选范围的结束地址 idc.read_selection_end()
import idc
print('当前地址:'+hex(idc.here()))
print('基址:'+hex(ida_ida.inf_get_min_ea())))

获取地址的数值

功能 函数
以1字节为单位获取地址处的值 idc.get_wide_byte(addr)
以2字节(字)的单位获取 idc.get_wide_word(addr)
以4字节的单位获取 idc.get_wide_dword(addr)
以8字节的单位获取 idc.get_qword(addr)
判断是否是字节 ida_bytes.is_byte
import idc
import ida_bytes
print('当前地址:'+hex(idc.here()))
print('值'+hex(idc.get_wide_byte(idc.here())))

修改指令数值

功能 函数
修改addr地址的值为value.每次修改1个字节 ida_bytes.patch_byte(addr,value)
每次修改2个字节 ida_bytes.patch_word(addr,value)
每次修改4个字节 ida_bytes.patch_Dword(addr,value)
每次修改8个字节 ida_bytes.patch_Qword(addr,value)
import idc
import ida_bytes
addr = idc.here()
value_before = idc.get_wide_byte(addr)
print("修改之前:"+ hex(value_before))

ida_bytes.patch_byte(addr,0x90)

value_after = idc.get_wide_byte(addr)
print("修改之后:"+ hex(value_after))

Untitled

汇编指令操作

功能 函数
获取地址处的汇编语句 idc.GetDisasm(addr) 或 idc.generate_disasm_line(addr,flags)
获取指定地址位置的操作数.参数1是地址.参数2是操作数索引.如 mov ebp,esp中: 操作数1是ebp ,操作数2是esp mov则是汇编指令不是操作数 idc.print_operand(addr,index)
获取汇编操作指令(如mov、add) idc.print_insn_mnem(addr)
获取操作数的类型 idc.get_operand_type(addr,index)
获取指定索引操作数中的值: 如 calll 0x00402004 对应汇编为: FF 15 04 20 40 00 FF15=Call 而操作数的值则为04 20 40 00 (小端) 使用函数之后获取则为地址 00402004 idc.get_operand_value(addr,index)
获取下一行汇编 idc.next_head(addr)
获取上一行汇编 idc.PrevHead(addr)
import idc
import idaapi
import idautils

ea = idc.here();
print("基址为: " + hex(idaapi.get_imagebase()))
print("当前汇编: " + idc.GetDisasm(ea))
print("当前汇编指令为: " + idc.print_insn_mnem(ea))
print("当前操作数为: " + idc.print_operand(ea,0))

Untitled

段操作

功能 函数
获取段的名字(参数为当前的地址) idc.get_segm_name(addr)
获取段的开始地址 idc.get_segm_start(addr)
获取段的结束地址 idc.get_segm_end(addr)
获取第一个段 idc.get_first_seg(addr)
获取下一个段 idc.get_next_seg(addr)
返回一个列表记录所有段的地址 idautil.Segments()
import idc
import idaapi
import idautils

for seg_addr in idautils.Segments():
segname = idc.get_segm_name(seg_addr)
segstart = idc.get_segm_start(seg_addr)
segend = idc.get_segm_end(seg_addr)
print("段名:" + segname + "起始地址:" + hex(segstart) + "结束地址:" + hex(segend));

Untitled

函数操作

功能 函数
获取指定地址之间的所有函数 idautils.Functions(startaddr,endaddr)
获取指定地址的函数名 idc.get_func_name(addr)
获取函数的注释 get_func_cmt(addr, repeatable) repeatable:0/1 0是获取常规注释 1是获取重复注释
设置函数注释 idc.set_func_cmt(ea, cmt, repeatable)
弹出框框要求用户进行选择 参数则是信息 idc.choose_func(title)
返回: addr 距离函数的偏移形式 idc.get_func_off_str(addr)
寻找函数结尾,如果函数存在则返回结尾地址,否则返回BADADDR idc.find_func_end(addr)
设置函数结尾 ida_funcs.set_func_end(ea, newend) newend:新的结束地址
设置函数开头 ida_funcs.set_func_start(addr, newstart)
设置地址处的名字 idc.set_name(ea, name, SN_CHECK) Ex函数也使用set_name
获取首个函数 idc.get_prev_func(ea)
获取下一个函数 idc.get_next_func(ea)
import idc
import idaapi
import idautils

for seg in idautils.Segments():
segname = idc.get_segm_name(seg)
segstart = idc.get_segm_start(seg)
segend = idc.get_segm_end(seg)
if (segname == '.text'):
for funcaddr in Functions(segstart,segend):
funname = idc.get_func_name(funcaddr)
funend = idc.find_func_end(funcaddr)
funnext = idc.get_next_func(funcaddr)
funnextname = idc.get_func_name(funnext)
print("当前函数名: " + funname + "当前结束地址: " + hex(funend) +"下一个函数地址: " + hex(funnext) + "下一个函数名: " + funnextname)
ea = idc.get_screen_ea()
funnextoffset = idc.get_func_off_str(ea)
print("当前选择地址距离当前函数的偏移为: "+ funnextoffset)

Untitled

数据查询

在IDAPython中如果我们想查询某些 数据 代码 二进制 都可以用都搜索函数。

搜索函数可以是向上搜索 也可以是向下搜索. 搜索失败就会返回-1 也就是BADADDR。

而搜索功能也常常用于去除花指令当中。

功能 函数
查找二进制找到返回地址没找到返回-1(BADADDR) idc.find_binary(ea, flag, searchstr, radix=16, from_bc695=False)
从ea开始寻找下一个数据地址 ida_search.find_data(ea, sflag)
从ea开始寻找下一个代码地址 ida_search.find_code(ea, sflag)
跳转到ea位置 ida_kernwin.jumpto(ea)

flags取值:

SEARCH_DOWN 向下搜索
SEARCH_UP 向上搜索
SEARCH_NEXT 获取下一个找到的对象。
SEARCH_CASE 指定大小写敏感度
SEARCH_UNICODE 搜索 Unicode 字符串。
import idc
import idaapi
import idautils

addr = idc.here()
value = idc.find_binary(ea,SEARCH_DOWN,'C4 00 C4')
value1 = idc.find_code(ea,SEARCH_DOWN)
value2 = idc.find_data(ea,SEARCH_DOWN)
print("当前位置:"+hex(addr))
print("C4 00 C4 所在位置:"+hex(value))
print("下一处代码位置:"+hex(value1))
print("下一处数据位置:"+hex(value2))

Untitled

数据校验函数

数据校验函数有一个参数flag,得到flag后可以直接进行校验

功能 函数
获取标志 ida_bytes.get_full_flags(ea)
判断是否为代码 ida_bytes.is_code(f) f即标志
判断是否为数据 ida_bytes.is_data(f)
import idc
import idaapi
import idautils
import ida_bytes
addr = idc.here()
value = idc.find_binary(ea,SEARCH_DOWN,'C4 00 C4')
value1 = idc.find_code(ea,SEARCH_DOWN)
value2 = idc.find_data(ea,SEARCH_DOWN)
print("当前位置:"+hex(addr))
print("C4 00 C4 所在位置:"+hex(value))
print("下一处代码位置:"+hex(value1))
print("下一处数据位置:"+hex(value2))
flag1 = ida_bytes.get_full_flags(value1)
flag2 = ida_bytes.get_full_flags(value2)
#print(flag)
print(str(hex(value1)) +"处是不是代码?:" + str(ida_bytes.is_code(flag1)))
print(str(hex(value2)) +"处是不是代码?:" + str(ida_bytes.is_code(flag2)))

Untitled

交叉引用

在IDA的操作中 我们常常会对一个函数按X快捷键来查看谁引用了

功能 函数
获取地址处引用位置 A调用B 对B函数地址使用此函数则找到A调用 返回列表.遍历列表则可以找出所有引用位置. 参数1是ea也就是地址,参数2告诉IDA是否跟踪这些代码. idautils.CodeRefsTo(ea, flow)
返回ea的代码引用了何处的代码. 返回一个列表 idautils.CodeRefsFrom(ea, flow)
返回一个列表告诉ea位置的数据被谁引用了 idautils.DataRefsTo(ea)
告诉我们ea引用了谁. idautils.DataRefsFrom(ea)
import idc
import idaapi
import idautils
import ida_bytes
addr = idc.here()
for i in CodeRefsTo(addr,False):
print(hex(i))
print("当前汇编: " + idc.GetDisasm(i))

Untitled

除了上述通过地址来查找引用的方式外,还可以通过函数名来进行查找交叉引用:

1、先通过idc.get_name_ea_simple(fun_name)找到函数的线性地址

2、再使用for i in CodeRefsTo(addr,False)得到所有引用的地址

一个例子:https://hotspurzzz.github.io/2021/11/12/IDA-Python 批量脚本分析程序/

官网API文档:

https://www.hex-rays.com/wp-content/static/products/ida/support/idapython_docs/

参考链接:

https://www.cnblogs.com/iBinary/p/14642662.html

文章作者: HotSpurzzZ
文章链接: http://example.com/2021/11/17/IDA Python 常用API(持续更新)/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HotSpurzzZ