Package Peach :: Package Publishers :: Module tcp
[hide private]

Source Code for Module Peach.Publishers.tcp

  1   
  2  ''' 
  3  Default included TCP publishers. 
  4   
  5  @author: Michael Eddington 
  6  @version: $Id: Peach.Publishers.tcp-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
  7  ''' 
  8   
  9  # 
 10  # Copyright (c) 2005-2008 Michael Eddington 
 11  # Copyright (c) 2004-2005 IOActive Inc. 
 12  # 
 13  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 14  # of this software and associated documentation files (the "Software"), to deal 
 15  # in the Software without restriction, including without limitation the rights  
 16  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 17  # copies of the Software, and to permit persons to whom the Software is  
 18  # furnished to do so, subject to the following conditions: 
 19  # 
 20  # The above copyright notice and this permission notice shall be included in     
 21  # all copies or substantial portions of the Software. 
 22  # 
 23  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 24  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 25  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 26  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 27  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 28  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 29  # SOFTWARE. 
 30  # 
 31   
 32  # Authors: 
 33  #   Michael Eddington (mike@phed.org) 
 34   
 35  # $Id: Peach.Publishers.tcp-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
 36   
 37   
 38  import socket, time, sys 
 39  from Peach.publisher import * 
 40  import Peach 
 41   
42 -def Debug(msg):
43 if Peach.Engine.engine.Engine.debug: 44 print msg
45
46 -class Tcp(Publisher):
47 ''' 48 A simple TCP client publisher. 49 ''' 50 51
52 - def __init__(self, host, port, timeout = 0.25):
53 ''' 54 @type host: string 55 @param host: Remote host 56 @type port: number 57 @param port: Remote port 58 @type timeout: number 59 @param timeout: How long to wait for reponse 60 ''' 61 self._host = host 62 63 try: 64 self._port = int(port) 65 except: 66 raise PeachException("The Tcp publisher parameter for port was not a valid number.") 67 68 try: 69 self._timeout = float(timeout) 70 except: 71 raise PeachException("The Tcp publisher parameter for timeout was not a valid number.") 72 73 self._socket = None
74
75 - def start(self):
76 pass
77
78 - def stop(self):
79 self.close()
80
81 - def connect(self):
82 ''' 83 Create connection. 84 ''' 85 self.close() 86 87 # Try connection three times befor 88 # exiting fuzzer run 89 for i in range(3): 90 try: 91 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 92 self._socket.connect((self._host,self._port)) 93 exception = None 94 break 95 96 except: 97 self._socket = None 98 exception = sys.exc_info() 99 100 # Wait half sec and try again 101 time.sleep(0.5) 102 103 if self._socket == None: 104 value = "" 105 try: 106 value = str(exception[1]) 107 except: 108 pass 109 110 raise PeachException("TCP onnection attempt failed: %s" % value) 111 112 self.buff = "" 113 self.pos = 0
114
115 - def close(self):
116 ''' 117 Close connection if open. 118 ''' 119 try: 120 if self._socket != None: 121 self._socket.close() 122 finally: 123 self._socket = None 124 125 self.buff = "" 126 self.pos = 0
127
128 - def send(self, data):
129 ''' 130 Send data via sendall. 131 132 @type data: string 133 @param data: Data to send 134 ''' 135 136 try: 137 self._socket.sendall(data) 138 except: 139 raise PublisherSoftException("sendall failed: " + str(sys.exc_info()[1]))
140
141 - def _receiveBySize(self, size):
142 ''' 143 This is now a buffered receiver. 144 145 @rtype: string 146 @return: received data. 147 ''' 148 149 # Do we already a have it? 150 if size+self.pos < len(self.buff): 151 ret = self.buff[self.pos:self.pos+size] 152 self.pos += size 153 return ret 154 155 # Only ask for the diff of what we don't already have 156 diffSize = (self.pos+size) - len(self.buff) 157 158 try: 159 self._socket.settimeout(self._timeout) 160 ret = self._socket.recv(diffSize) 161 162 Debug("udp.Udp.receive we got:") 163 Debug(repr(ret)) 164 165 if not ret: 166 # Socket was closed 167 raise PublisherSoftException("Socket is closed") 168 169 self.buff += ret 170 171 except socket.error, e: 172 if str(e).find('The socket operation could not complete without blocking') == -1: 173 raise Timeout("Timed out waiting for data [%d:%d:%d:%d]" % (len(self.buff), (size+self.pos), size, diffSize)) 174 175 else: 176 raise PublisherSoftException("recv failed: " + str(sys.exc_info()[1])) 177 178 finally: 179 self._socket.settimeout(None) 180 181 ret = self.buff[self.pos:] 182 self.pos = len(self.buff) 183 return ret
184
185 - def _receiveByAvailable(self):
186 ''' 187 Receive as much as possible prior to timeout. 188 189 @rtype: string 190 @return: received data. 191 ''' 192 self._socket.settimeout(self._timeout) 193 194 try: 195 ret = self._socket.recv(4096) 196 197 Debug("udp.Udp.receive we got:") 198 Debug(repr(ret)) 199 200 if not ret: 201 raise PublisherSoftException("Socket is closed") 202 203 self.buff += ret 204 205 except socket.error, e: 206 if str(e).find('The socket operation could not complete without blocking') == -1: 207 pass 208 209 else: 210 raise PublisherSoftException("recv failed: " + str(sys.exc_info()[1])) 211 212 self._socket.settimeout(None) 213 214 ret = self.buff[self.pos:] 215 self.pos = len(self.buff) 216 return ret
217
218 - def receive(self, size = None):
219 220 if size == None: 221 return self._receiveByAvailable() 222 else: 223 return self._receiveBySize(size)
224
225 -class TcpListener(Tcp):
226 ''' 227 A TCP Listener publisher. This publisher 228 supports the following state actions: 229 230 * start - Start listening 231 * stop - Stop listeningn nCMuBd7z3 232 * accept - Accept a client connection 233 * close - Close a client connection 234 ''' 235
236 - def __init__(self, host, port, timeout = 0.25):
237 Tcp.__init__(self, host, port, timeout) 238 239 self._listen = None 240 self._clientAddr = None
241
242 - def start(self):
243 self.stop() 244 245 if self._listen == None: 246 # Try connection three times befor 247 # exiting fuzzer run 248 for i in range(3): 249 try: 250 self._listen = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 251 self._listen.bind((self._host,self._port)) 252 self._listen.listen(1) 253 exception = None 254 break 255 256 except: 257 self._listen = None 258 exception = sys.exc_info() 259 260 time.sleep(0.5) 261 262 if self._listen == None: 263 value = "" 264 try: 265 value = str(exception[1]) 266 except: 267 pass 268 269 raise PeachException("TCP bind attempt failed: %s" % value) 270 271 self.buff = "" 272 self.pos = 0
273
274 - def stop(self):
275 try: 276 if self._socket != None: 277 self._socket.close() 278 except: 279 pass 280 281 finally: 282 self._socket = None
283 284 # Avoid TIME_WAIT state by not closing our listener 285 286 #try: 287 # if self._listen != None: 288 # self._listen.close() 289 #except: 290 # pass 291 # 292 #finally: 293 # self._listen = None 294
295 - def accept(self):
296 self.buff = "" 297 self.pos = 0 298 299 conn, addr = self._listen.accept() 300 self._socket = conn 301 self._clientAddr = addr
302
303 - def close(self):
304 try: 305 if self._socket != None: 306 self._socket.close() 307 except: 308 pass 309 finally: 310 self._socket = None
311
312 - def connect(self):
313 raise PeachException("Action 'connect' not supported")
314 315 try: 316 import win32gui, win32con, win32process 317 import sys,time, os, signal 318
319 - class TcpListenerLaunchGui(TcpListener):
320 ''' 321 Does TcpListener goodness and also can laun a program. After 322 some defined amount of time we will try and close the 323 GUI application by sending WM_CLOSE than kill it. 324 ''' 325
326 - def __init__(self, host, port, windowname, timeout = 0.25):
327 TcpListener.__init__(self, host, port, timeout) 328 self._windowName = windowname
329
330 - def stop(self):
331 self.closeApp(self._windowName) 332 TcpListener.stop(self)
333
334 - def call(self, method, args):
335 ''' 336 Launch program to consume file 337 338 @type method: string 339 @param method: Command to execute 340 @type args: array of objects 341 @param args: Arguments to pass 342 ''' 343 344 realArgs = [method, "/c", method] 345 for a in args: 346 realArgs.append(a) 347 348 #print "Spawning %s" % method 349 os.spawnv(os.P_NOWAIT, os.path.join( os.getenv('SystemRoot'), 'system32','cmd.exe'), realArgs)
350 351
352 - def enumCallback(hwnd, windowName):
353 ''' 354 Will get called by win32gui.EnumWindows, once for each 355 top level application window. 356 ''' 357 358 try: 359 360 # Get window title 361 title = win32gui.GetWindowText(hwnd) 362 363 # Is this our guy? 364 if title.find(windowName) == -1: 365 return 366 367 (threadId, processId) = win32process.GetWindowThreadProcessId(hwnd) 368 369 # Send WM_CLOSE message 370 try: 371 win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) 372 win32gui.PostQuitMessage(hwnd) 373 except: 374 pass 375 376 # Give it upto 5 sec 377 for i in range(100): 378 if win32process.GetExitCodeProcess(processId) != win32con.STILL_ACTIVE: 379 # Process exited already 380 return 381 382 time.sleep(0.25) 383 384 try: 385 # Kill application 386 win32process.TerminateProcess(processId, 0) 387 except: 388 pass 389 except: 390 pass
391 392 enumCallback = staticmethod(enumCallback) 393
394 - def closeApp(self, title):
395 ''' 396 Close Application by window title 397 ''' 398 #print "CloseApp: %s" % title 399 win32gui.EnumWindows(TcpListenerLaunchGui.enumCallback, title)
400 401 except: 402 pass 403 404 # end 405