IDA 特征码生成和搜索脚本

发布时间 2023-04-12 19:27:01作者: 好鱼233

最近比较忙,就少写两句,直接附上源代码,其中的细节点就不再赘述,如有疑问,请留言。


一共就是实现了两个函数,一个用于搜索特征码 (SearchPattern),一个用于生成特征码 (GenerateFunctionSignature)

函数的参数和返回值:

1.SearchPattern 接收一个必要参数 hexStr(即要搜索的特征码),一个可选参数 num(最多返回多少个匹配的结果),返回一个存放所有符合条件的地址的 list

2.GenerateFunctionSignature 接收一个必要参数 addr(即要生成特征码的地址的起始位置),返回唯一的特征码字符串,例如输入地址:0x12345678,返回字符串 48 8B F2 4C 8B F1 E8 ?? ?? ?? ??

 

··· 以下是 SearchPattern 的实现:

 1 import ida_bytes
 2 import ida_ida
 3 
 4 def SearchPattern(hexStr, num = 0):
 5     '''
 6     hexStr: 输入的特征码字符串,例:41 80 BE ?? ?? ?? ?? 0F 84 ?? ?? 
 7     num:    搜索到多少个结果时返回,为 0 时搜索全部匹配的地址
 8     '''
 9     
10     # 生成掩码
11     bMask = hexStr.replace('00', '01')
12     bMask = bMask.replace('??', '00')
13     bMask = bytes.fromhex(bMask)
14     # print(bMask)
15     
16     # 生成模式码
17     bPattern = hexStr.replace('??', '00')
18     bPattern = bytes.fromhex(bPattern)
19     # print(bPattern)
20 
21 
22     results = []
23     ea = ida_ida.inf_get_min_ea()
24     
25     while True:
26         ea = ida_bytes.bin_search(
27             ea + 1, 
28             ida_ida.inf_get_max_ea(), 
29             bPattern, 
30             bMask, 
31             1, 
32             ida_bytes.BIN_SEARCH_FORWARD| ida_bytes.BIN_SEARCH_NOBREAK| ida_bytes.BIN_SEARCH_NOSHOW)
33         if ea == ida_idaapi.BADADDR:
34             break
35         else:
36             # 这里可以稍作修改,让返回值变为当前函数的首地址
37             results.append(hex(ea))
38             if num != 0 and len(results) >= num:
39                 break
40     # print("find {} result".format(len(results)))
41     
42     return results
43 
44 
45 ## 测试
46 print(SearchPattern("48 8B C4 48 89 50 ??", 3))

 

 

··· 以下是 GenerateFunctionSignature 的实现:

 1 import ida_bytes, ida_ua
 2 
 3 def GenerateFunctionSignature(funcBase):
 4     # 初始化要用到的变量
 5     instruction = ida_ua.insn_t()
 6     offset = 0
 7     signature = ""
 8     
 9     # 最多分析 100 条指令
10     for count in range(1, 101):
11         ida_ua.decode_insn(instruction, funcBase + offset)
12         offset += instruction.size
13         patternTemp = [0 for i in range(0, instruction.size)]
14         
15         
16         # 遍历当前指令的全部操作数,并将部分操作数的机器码置为 ??
17         for op in instruction.ops:
18             if op.type == o_void:
19                 continue
20             #  模糊位 ?? 的匹配条件:
21             # and op.type != ida_ua.o_phrase and op.type != ida_ua.o_displ
22             elif (op.type != ida_ua.o_reg):
23                 for index in range(op.offb, instruction.size):
24                     patternTemp[index] = "??"
25 
26 
27         # 读入除模糊位之外的机器码
28         for index in range(0, instruction.size):
29             if patternTemp[index] == "??":
30                 pass
31             else:
32                 byteStr = format(ida_bytes.get_byte(instruction.ea + index), '02X')
33                 patternTemp[index] = byteStr
34             signature = signature + ' ' + patternTemp[index]
35 
36         
37         # 每分析 3 条指令,判断一次当前的 signature 是否唯一
38         if count%3 == 0:
39             if len(SearchPattern(signature, 2)) == 1:
40                 print('unique signature')
41                 return signature
42             else:
43                 # print('not unique signature')
44                 continue
45             
46     return None
47     
48 
49 ## 测试
50 print("pattern = ", GenerateFunctionSignature(0x320E21F))