1
2 """
3 A byte and mask based decision engine for creating byte
4 sequences (and potential comparison masks) for general purpose
5 signature matching.
6
7 Currently used by vivisect function entry sig db and others.
8 """
9
11 """
12 A byte based decision tree which uses all the RAMs but is
13 really fast....
14
15 Signatures consist of a byte sequence and an optional mask
16 sequence. If present each mask byte is used to logical and
17 the byte being compared before comparison. This allows the
18 creation of signatures which have parts of the sig generalized.
19
20 FIXME allow sigs to have a reliability rating
21 FIXME allow sig nodes to store depth and truncate the tree early (and then mask the rest)
22 """
23
25 self.basenode = (0, [], [None] * 256)
26 self.sigs = {}
27
29
30 todo = [(node, siginfo),]
31
32
33 while len(todo):
34
35 node, siginfo = todo.pop()
36 depth, sigs, choices = node
37 bytes, masks, o = siginfo
38 siglen = len(sigs)
39
40 sigs.append(siginfo)
41 if siglen == 0:
42 pass
43
44
45 elif siglen == 1:
46
47
48 for s in sigs:
49 chval = s[0][depth]
50 nnode = self._getNode(depth, choices, chval)
51 todo.append((nnode, s))
52
53 else:
54 chval = bytes[depth]
55 nnode = self._getNode(depth, choices, chval)
56 todo.append((nnode, siginfo))
57
58 - def _getNode(self, depth, choices, choice):
59
60 nnode = choices[choice]
61 if nnode == None:
62 nnode = (depth+1, [], [None] * 256)
63 choices[choice] = nnode
64 return nnode
65
67 """
68 Add a signature to the search tree. If masks goes unspecified, it will be
69 assumed to be all ones (\\xff * len(bytes)).
70
71 Additionally, you may specify "val" as the object to get back with
72 getSignature().
73 """
74
75 if masks == None:
76 masks = "\xff" * len(bytes)
77
78 if val == None:
79 val = True
80
81
82 bytekey = bytes + masks
83 if self.sigs.get(bytekey) != None:
84 return
85
86 self.sigs[bytekey] = True
87
88 byteord = [ord(c) for c in bytes]
89 maskord = [ord(c) for c in masks]
90
91 siginfo = (byteord, maskord, val)
92 self._addChoice(siginfo, self.basenode)
93
96
98
99 node = self.basenode
100 while True:
101 depth, sigs, choices = node
102
103
104 if len(sigs) == 1:
105 sbytes, smasks, sobj = sigs[0]
106 for i in xrange(depth, len(sbytes)):
107 realoff = offset + i
108 masked = ord(bytes[realoff]) & smasks[i]
109 if masked != sbytes[i]:
110 return None
111 return sobj
112
113
114 node = None
115 for sig in sigs:
116 sbytes, smasks, sobj = sig
117 masked = ord(bytes[offset+depth]) & smasks[depth]
118 if sbytes[depth] == masked:
119
120 node = choices[masked]
121 break
122
123
124 if node == None:
125 return None
126