-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathanalyzeryara.py
121 lines (107 loc) · 5.79 KB
/
analyzeryara.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#
# idaDiscover plugin - by Javier Vicente Vallejo - @vallejocc
#
from ida_defines import *
from installation import Installation
import os
class AnalyzerYara():
################################################################################################
def __init__(self, yaraRulesPath, gPrinter):
self.gPrinter = gPrinter
print("Using yara rules: %s" % yaraRulesPath)
self.yaraRulesPath = yaraRulesPath
self.yaraRulesPathDirectory = os.path.dirname(os.path.realpath(self.yaraRulesPath))
try:
self.yaramod = __import__("yara")
except:
print("Error importing yara module. Please execute installation")
curDirectory = os.getcwd()
os.chdir(self.yaraRulesPathDirectory)
try:
self.rule = self.yaramod.compile(self.yaraRulesPath, includes=True, include_callback=Installation._incl_callback)
except:
print("Error compiling yara rules")
os.chdir(curDirectory)
################################################################################################
def Analyze(self, data, callback):
try:
self.rule.match(data=data, callback=callback)
except Exception as e:
print("Error in yara match %s" % e)
################################################################################################
def AnalyzeInline(self, data, callback):
try:
yaraname = IDAAPI_AskStr("", "Please enter a name for the inline yara rule")
yarapattern = IDAAPI_AskStr("", "Please enter a pattern for the inline yara rule")
inlinerule = self.yaramod.compile(source='rule %s {\r\nstrings:\r\n$s = %s\r\ncondition:\r\nall of them\r\n}' % (yaraname, yarapattern))
inlinerule.match(data=data, callback=callback)
except Exception as e:
print("Error in yara match %s" % e)
################################################################################################
def YaraCallback(self, data):
try:
if data['matches'] == True:
#print data['rule']
for e in data['strings']:
if "contentis_base64" not in data['rule']:
cmt = IDAAPI_CommentEx(IDAAPI_ItemHead(self.currentEa+e[0]), 1)
if cmt==None:
cmt=""
if ("%s(%s)" % (data['rule'], e[1])) not in cmt:
IDAAPI_MakeRptCmt(IDAAPI_ItemHead(self.currentEa+e[0]), "%s yara(%s(%s))" % (cmt, data['rule'], e[1]))
self.gPrinter.doPrint("%x - yara(%s(%s))" % (self.currentEa+e[0], data['rule'], e[1]), "yara")
except:
pass
self.yaramod.CALLBACK_CONTINUE
################################################################################################
def YaraMatchesToIdbBySegments(self, binlineyara = False):
self.gPrinter.doPrint("Yara matches:", "yara")
self.gPrinter.doPrint("----------------------------------------------------------", "yara")
for seg_ea in IDAAPI_Segments():
self.currentEa = seg_ea
self.currentEaEnd = IDAAPI_SegEnd(seg_ea)
for i in range(0, 0x1000):
flags = IDAAPI_GetFlags(self.currentEaEnd-1)
if flags == 0 or flags == 512: #FF_UNK / FF_TAIL
self.currentEaEnd = self.currentEaEnd - 1
segmentContent = IDAAPI_GetManyBytes(self.currentEa, self.currentEaEnd - self.currentEa)
if not segmentContent:
print("Unable to get segment content %x" % self.currentEa)
else:
print("Yara analysis on segment %x - %x" % (self.currentEa, self.currentEaEnd))
if segmentContent:
if not binlineyara: self.Analyze(segmentContent, self.YaraCallback)
else: self.AnalyzeInline(segmentContent, self.YaraCallback)
self.gPrinter.doPrint("----------------------------------------------------------", "yara")
self.gPrinter.doPrint("", "yara")
self.gPrinter.doPrint("", "yara")
################################################################################################
def YaraMatchesToIdb(self, binlineyara = False):
self.gPrinter.doPrint("Yara matches:", "yara")
self.gPrinter.doPrint("----------------------------------------------------------", "yara")
bfirst = True
fullImage = ""
for seg_ea in IDAAPI_Segments():
if bfirst: self.currentEa = seg_ea
else: fullImage += ("\x00"*(seg_ea - self.currentEaEnd))
bfirst = False
self.currentEaEnd = IDAAPI_SegEnd(seg_ea)
removedBytes = 0
for i in range(0, 0x1000):
flags = IDAAPI_GetFlags(self.currentEaEnd - 1)
if flags == 0 or flags == 512: #FF_UNK / FF_TAIL
self.currentEaEnd = self.currentEaEnd - 1
removedBytes += 1
segmentContent = IDAAPI_GetManyBytes(seg_ea, self.currentEaEnd - seg_ea)
if not segmentContent:
print("Unable to get segment content %x" % seg_ea)
fullImage += "\x00"*(self.currentEaEnd - seg_ea + removedBytes)
else:
print("Yara analysis on segment %x - %x" % (seg_ea, self.currentEaEnd))
fullImage += (segmentContent + "\x00"*removedBytes)
self.currentEaEnd += removedBytes
if not binlineyara: self.Analyze(fullImage, self.YaraCallback)
else: self.AnalyzeInline(fullImage, self.YaraCallback)
self.gPrinter.doPrint("----------------------------------------------------------", "yara")
self.gPrinter.doPrint("", "yara")
self.gPrinter.doPrint("", "yara")