记录ida脚本
IDA Python 脚本编程
内存分为:
- 本地内存
- 调试内存
常用脚本接口介绍
寄存器操作(调试)
idc.get_reg_value('rax’)
idaapi.set_reg_val("rax", 1234)
读取 xmm 寄存器
def read_xmm_reg(name):
rv = idaapi.regval_t()
idaapi.get_reg_val(name,rv)
return (struct.unpack("Q",rv.bytes())[0])
调试内存操作 dbg 是指debug内存(调试内存)
idc.read_dbg_byte(addr)
idc.read_dbg_word(addr)
idc.read_dbg_dword(addr)
idc.read_dbg_qword(addr)
idc.read_dbg_memory(addr,size)
idc.patch_dbg_byte(addr,val)
调试内存读写封装
def patch_dbg_mem(addr,data):
for i in range(len(data)):
idc.patch_dbg_byte(addr+i,data[i])
def read_dbg_mem(addr,size):
dd = []
for i in range(size):
dd.append(idc.read_dbg_byte(addr+i))
return bytes(dd)
本地内存操作(会修改idb数据库)
idc.get_qword(addr)
idc.patch_qword(addr,val)
idc.patch_dword(addr,val)
idc.patch_word(addr,val)
idc.patch_byte(addr,val)
idc.get_bytes(addr,size)
反汇编操作
idc.GetDisasm(addr) # 只能返回一条汇编指令
idc.next_head(addr) # 获取下一条汇编指令的地址
交叉引用分析
for ref in idautils.XrefsTo(ea):
print(hex(ref.frm))
杂项常用接口
idc.add_bpt(addr) # 添加断点
idaapi.get_imagebase() # 获取基地址
idc.create_insn(addr) # 生成汇编指令,相当于快捷键C 常用于固件分析
ida_funcs.add_func(addr) # 生成函数,相当于快捷键p
ida_bytes.create_strlit(addr) # 生成字符串,相当于快捷键A
函数遍历
for func in idautils.Functions():
print("0x%x,%s" % (func,idc.get_func_name(func)))
基本块的遍历
fn = 目标函数地址
f_blocks = idaapi.FlowChart(idaapi.get_func(fn),flags=idaapi.FC_PREDS)
for blocks in f_blocks:
print(hex(blocks.start_ea))
# 基本块的前驱
for pre in blocks.preds():
print(hex(pre.start_ea))
# 基本块的后继
for sucess in blocks.succs():
print(hex(sucess.start_ea))
指令遍历
for ins in idautils.FuncItems(addr):
print(hex(ins))
实战部分
ollvm批量断点设置:
实验材料:ollvm-flat
注意:判断真实块的依据是查找 ollvm 汇集点基本块的交叉引用,不一定准确
断点脚本:
import idc
import idaapi
import struct
import idautils
# ollvm函数地址
fn = 0x401F60
# ollvm基本块汇集地址
ollvm_tail = 0x405D4B
# 拿到函数基本块的迭代器
f_blocks = idaapi.FlowChart(idaapi.get_func(fn),flags=idaapi.FC_PREDS)
# 然后遍历函数基本块
for block in f_blocks:
# 拿到每个基本块的后驱
for sucess in block.succs():
if sucess.start_ea == ollvm_tail:
print(hex(block.start_ea))
idc.add_bpt(block.start_ea)
复制到ida下面,摁回车两次就行
成功打上断点,打上断点的基本块都是真实块
断点管理
全选右键生成文件夹
点击文件夹,进行断点的批量禁用或启用
条件断点脚本编写:
实验材料:dump_test.exe
目标:设置一个条件断点,当 rand 函数返回值为 16949 时停下
找到random函数
设置断点
在断点处右键编辑断点
脚本:
import idc
import idaapi
import struct
import idautils
def bp():
rax = idc.get_reg_value('rax')
return rax == 16949
先在ida中执行脚本
然后编辑断点,增加condition条件
然后运行程序
程序停下来后,就查看rax寄存器,经过16进制转10进制,结果正确
条件断点运用:dump rand 函数每一次执行结果,不让程序停下来
脚本:条件断点函数返回 False,IDA 不会命中该断点,利用这个特性提取运行时数据
def bp():
rax = idc.get_reg_value('rax')
print(rax,end=',')
return False
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com