Package Peach :: Package Engine :: Module mitm
[hide private]

Source Code for Module Peach.Engine.mitm

  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  # Copyright (c) 2008 Michael Eddington 
 13  # 
 14  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 15  # of this software and associated documentation files (the "Software"), to deal 
 16  # in the Software without restriction, including without limitation the rights  
 17  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 18  # copies of the Software, and to permit persons to whom the Software is  
 19  # furnished to do so, subject to the following conditions: 
 20  # 
 21  # The above copyright notice and this permission notice shall be included in     
 22  # all copies or substantial portions of the Software. 
 23  # 
 24  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 25  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 26  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 27  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 28  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 29  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 30  # SOFTWARE. 
 31  # 
 32   
 33  # Authors: 
 34  #   Michael Eddington (mike@phed.org) 
 35   
 36  # $Id: mitm.py 780 2008-03-23 02:58:49Z meddingt $ 
 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  #from build import BuildPeach 
 82  from Peach.Engine.incoming import * 
 83   
84 -def Debug(level, msg):
85 if level <= 1: 86 print msg
87
88 -def peachPrint(msg):
89 print "peachPrint: ", msg
90 91 92 " [C] -> [PEACH] -> [S]" 93 " Right Left " 94 " Ouput-> <-Input "
95 -class PitmStateEngine:
96
97 - def __init__(self, engine, stateMachine, publisherRight, publisherLeft):
98 self.engine = engine 99 100 # Get and run initial state 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 # listen on tcp socket A 113 114 115 # connect out on tcp socket B 116 117 118 while True: 119 120 # read from A 121 122 # write to B 123 124 # read from B 125 126 # write to A 127 128 pass 129 130 # close both sockets 131 132 mutator.onStateStart(state) 133 134 # EVENT: onEnter 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 # Start with first action and continue along 149 for action in state: 150 if action.elementType != 'action': 151 continue 152 153 self._runAction(action, mutator) 154 155 # EVENT: onExit 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 # EVENT: onExit 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
188 - def _evalEvent(self, code, environment):
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 #print globals() 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
206 - def _runAction(self, action, mutator):
207 208 Debug(1, "StateEngine._runAction: %s" % action.name) 209 210 mutator.onActionStart(action) 211 212 # EVENT: when 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 #print action.parent.parent 224 #for k in action.parent.parent._childrenHash.keys(): 225 # print "Key: ", k 226 227 if not self._evalEvent(action.when, environment): 228 return 229 230 # EVENT: onStart 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 # Determine initial read size 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 # Parse input stream into template 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 # Send data to right side 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 # Determine initial read size 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 # Parse input stream into template 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 # EVENT: onComplete 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
348 -class StateChangeStateException:
349 - def __init__(self, state):
350 self.state = state
351
352 - def __str__(self):
353 return "Exception: StateChangeStateException"
354
355 -class StateError:
356 - def __init__(self, msg):
357 self.msg = msg
358
359 - def __str__(self):
360 return self.msg
361 362 # end 363