1
2 '''
3 Peach-in-The-Middle Fuzzing
4
5 This module is the core of th PiTM support in Peach
6
7 @author: Michael Eddington
8 @version: $Id: mitm.py 780 2008-03-23 02:58:49Z meddingt $
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 DESIGN
41
42 Goal: Make it easy to fuzz protocols that have complex state transitions. And example would be RDP (remote desktop protocol).
43
44 FEATURES
45
46 OPERATION
47
48 1. Cause client to perform usecase
49 a. Watch sequence of packets
50 b. Build minimal StateMachine based on packet sequence
51
52 -> Have collection of possible Templates. Attempt to fit each template
53 to locate best fit.
54
55 2. Rest client & server
56
57 3. Loop the following:
58 a. [C] Start usecase
59 b. [P] Mutate usecase
60 c. [A] Monitor server for fault
61 d. Reset state
62
63 4. Move to next use case and GOTO #1
64
65 NEED
66
67 - Client control
68 - Server monitor (have)
69 - MiTM part
70
71 '''
72
73 import sys, re, types
74 import traceback
75
76 import Ft.Xml.Domlette
77 from Ft.Xml.Domlette import Print, PrettyPrint
78
79 from Peach.Engine.dom import *
80 from Peach.Engine.parser import *
81
82 from Peach.Engine.incoming import *
83
85 if level <= 1:
86 print msg
87
89 print "peachPrint: ", msg
90
91
92 " [C] -> [PEACH] -> [S]"
93 " Right Left "
94 " Ouput-> <-Input "
96
97 - def __init__(self, engine, stateMachine, publisherRight, publisherLeft):
98 self.engine = engine
99
100
101 self.stateMachine = stateMachine
102 self.publisherRight = publisherRight
103 self.publisherLeft = publisherLeft
104 self.f = peachPrint
105
106 - def run(self, mutator):
107 '''
108 Returns true if all test cases have been performed.
109 '''
110 Debug(1, "StateEngine.run: %s" % self.stateMachine.name)
111
112
113
114
115
116
117
118 while True:
119
120
121
122
123
124
125
126
127
128 pass
129
130
131
132 mutator.onStateStart(state)
133
134
135 if state.onEnter != None:
136 environment = {
137 'peach' : self.engine.peach,
138 'state' : state,
139 'stateMachine' : state.parent,
140 'peachPrint' : self.f,
141 'mutator' : mutator
142 }
143
144 self._evalEvent(state.onEnter, environment)
145
146 try:
147
148
149 for action in state:
150 if action.elementType != 'action':
151 continue
152
153 self._runAction(action, mutator)
154
155
156 if state.onExit != None:
157 environment = {
158 'peach' : self.engine.peach,
159 'state' : state,
160 'stateMachine' : state.parent,
161 'peachPrint' : self.f,
162 'mutator' : mutator
163 }
164
165 self._evalEvent(state.onExit, environment)
166
167 mutator.onStateComplete(state)
168
169 except StateChangeStateException, e:
170
171
172 if state.onExit != None:
173 environment = {
174 'peach' : self.engine.peach,
175 'state' : state,
176 'stateMachine' : state.parent,
177 'peachPrint' : self.f,
178 'mutator' : mutator
179 }
180
181 self._evalEvent(state.onExit, environment)
182
183 mutator.onStateComplete(state)
184
185 self._runState(e.state, mutator)
186
187
189 '''
190 Eval python code returning result.
191
192 code - String
193 environment - Dictionary, keys are variables to place in local scope
194 '''
195
196
197 scope = { '__builtins__' : globals()['__builtins__'] }
198 for k in environment.keys():
199 scope[k] = environment[k]
200
201 ret = eval(code, scope, scope)
202
203 return ret
204
205
207
208 Debug(1, "StateEngine._runAction: %s" % action.name)
209
210 mutator.onActionStart(action)
211
212
213 if action.when != None:
214 environment = {
215 'peach' : self.engine.peach,
216 'action' : action,
217 'state' : action.parent,
218 'stateMachine' : action.parent.parent,
219 'mutator' : mutator,
220 'peachPrint' : self.f
221 }
222
223
224
225
226
227 if not self._evalEvent(action.when, environment):
228 return
229
230
231 if action.onStart != None:
232 environment = {
233 'peach' : self.engine.peach,
234 'action' : action,
235 'state' : action.parent,
236 'stateMachine' : action.parent.parent,
237 'mutator' : mutator,
238 'peachPrint' : self.f
239 }
240
241 self._evalEvent(action.onStart, environment)
242
243 if action.type == 'input':
244 """
245 Get input from left side
246
247 1. Receive data from the left side
248 2. Parse into template
249 3. Pass back to right side
250 """
251
252 action.value = None
253
254
255 cracker = DataCracker(self.engine.peach)
256 size = cracker.getInitialReadSize(action.template)
257 Debug(1, "StateEngine._runAction(input): Found initial read size of %s" % size)
258
259 data = ""
260 dom = None
261
262
263 while True:
264 try:
265 print ">>STATE IS CALLING RECEIVE FOR %d BYTES" % size
266 data += self.publisherLeft.receive(size)
267 Debug(2, "======================================")
268 cracker = DataCracker(self.engine.peach)
269 dom = cracker.crackDataForTemplate(action.template, data)
270 break
271
272 except NeedMoreData, e:
273 size = e.amount
274 Debug(2, "Going back for: %d" % size)
275 Debug(2, "Currently Have:")
276 Debug(2, "><><><><><><><><><><><><><><><><><><")
277 Debug(2, data)
278 Debug(2, "><><><><><><><><><><><><><><><><><><")
279
280 printDom(dom, 0)
281
282 action.value = dom
283
284
285 self.publisherRight.send(action.value)
286
287 elif action.type == 'output':
288 """
289 Get ouput from right side
290
291 1. Receive data from the right side
292 2. Parse into template
293 3. Pass back to left side
294 """
295
296 action.value = None
297
298
299 cracker = DataCracker(self.engine.peach)
300 size = cracker.getInitialReadSize(action.template)
301 Debug(1, "StateEngine._runAction(input): Found initial read size of %s" % size)
302
303 data = ""
304 dom = None
305
306
307 while True:
308 try:
309 print ">>STATE IS CALLING RECEIVE FOR %d BYTES" % size
310 data += self.publisherRight.receive(size)
311 Debug(2, "======================================")
312 cracker = DataCracker(self.engine.peach)
313 dom = cracker.crackDataForTemplate(action.template, data)
314 break
315
316 except NeedMoreData, e:
317 size = e.amount
318 Debug(2, "Going back for: %d" % size)
319 Debug(2, "Currently Have:")
320 Debug(2, "><><><><><><><><><><><><><><><><><><")
321 Debug(2, data)
322 Debug(2, "><><><><><><><><><><><><><><><><><><")
323
324 printDom(dom, 0)
325
326 action.value = dom
327 action.value = mutator.getActionValue(action)
328
329 self.publisherLeft.send(action.value)
330
331 else:
332 raise Exception("StateEngine._runAction(): Unknown action.type of [%s]" % str(action.type))
333
334
335 if action.onComplete != None:
336 environment = {
337 'peach' : self.engine.peach,
338 'action' : action,
339 'state' : action.parent,
340 'mutator' : mutator,
341 'stateMachine' : action.parent.parent
342 }
343
344 self._evalEvent(action.onComplete, environment)
345
346 mutator.onActionComplete(action)
347
351
353 return "Exception: StateChangeStateException"
354
361
362
363