IDApython基础
三个基础模块:idc、idautils和idaapi;
其中ida是一个封装了IDC的兼容模块,idautils是IDA的高就实用功能模块,idaapi方便我们访问一下更加底层的数据。
总的来看,可以通过IDApython完成 地址、指令、函数、段、交叉引用 相关的操作。
idc
注:以IDApython文档为准,以下所有示例地址为ea
;返回的集合形式都是迭代器。
获取当前光标所在的指令地址;
获取指定地址的汇编指令;
获取当前地址的汇编指令的操作符。
获取指定地址处的指令中的第n个操作数(0计起);该函数的底层依赖get_operand_value(ea, n)
(获取第n个操作数的值)
获取指定指令操作数类型;
共有八种操作数类型(0-7):无操作数、寄存器、直接寻址的内存、基址和变址、寄存器偏移、常数、far寻址、near寻址。
获取指定地址所在的段(segment)名称;
指定段的起始地址;
指定段的结束地址;
指定地址所在段的下一个段的起始地址。
通过地址获取函数名称;ea可以是该函数范围的任意地址
获取下一条指令
获取前一条指令
idautils
获取当前程序所有段;
Functions(start=None, end=None)
获取指定地址区间的所有函数列表,默认返回所有识别出的函数地址列表。
获取指定地址所在函数的所有指令地址的集合。
获取ea地址处引用其他地址(call 或者 jmp方法)列表。
flow
(Boolen 0/1, Flase/True) ——是否跟进代码执行流,这在有条件跳转或者call时有区别。
有条件跳转或者call将产生两个引用(一个跳转指令的目的地址,另一个该指令的下一地址)。
获取引用了地址ea的地址列表,就是IDA的交叉引用快捷键X
功能
用IDApython解决计算AFL记录路径的hash算法碰撞问题
获取block及block id
def find_afl_block():
afl_funcs = []
blocks = dict()
# find all __afl_maybe_log_xx functions
for seg_ea in Segments():
for function_ea in Functions(seg_ea, SegEnd(seg_ea)):
if(GetFunctionName(function_ea)).startswith("__afl_maybe_log"):
afl_funcs.append(function_ea)
for afl_maybe_log_addr in afl_funcs:
refs = CodeRefsTo(afl_maybe_log_addr, 0) # where calls afl_maybe_log
for call_addr in refs:
# get block's id
id_addr = PrevHead(call_addr)
block_id = idc.get_operand_value(id_addr, 1)
blocks[call_addr] = block_id # (block_addr : block_id)
print("afl_funcs: {}; afl_blocks: {}".format(len(afl_funcs), len(blocks)))
return blocks
获取edges
def is_afl(addr):
asm = GetDisasm(addr)
return ("__afl_maybe_log" in asm)
def end_blocks(start):
# from this block; there has how many edges
ends = []
while isCode(GetFlags(start)):
head = NextHead(start)
if is_afl(head):
ends.append(head)
break
else:
# iterate to find afl
call = False
refs = CodeRefsFrom(head, 0)
asm = GetDisasm(head)
if asm.startswith('call') or asm.startswith('jmp'):
call = True
for r in refs:
try:
r_block = end_blocks(r)
except:
r_block = []
r_asm = GetDisasm(r)
if len(r_block):
ends += r_block
if call: # in call or jmp we found, jut out
return ends
start = head
return list(set(ends))
def find_afl_edges(afl_blocks):
edges = []
for block in afl_blocks: # block dict
# addr, afl_blocks[addr]
# search forwards to find an edge to another afl_block
# print(block)
ends = end_blocks(block)
edges.append((block, ends))
return edges
计算hash collision概率
def calc_collision(edges, blocks, hashs):
collision_cnt = 0
edge_cnt = 0
for edge in edges:
edge_cnt += len(edge[1])
prev = blocks[edge[0]]
for loc in edge[1]:
hans = calc_hash(prev, blocks[loc])
if hashs[hans] == 1:
collision_cnt += 1
else:
hashs[hans] = 1
print("edge_cnt: {}".format(edge_cnt))
rate = (collision_cnt * 1.0000)/(1 << 16)