engine.py :  » Network » Taof » taof-0.3.2 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Taof 
Taof » taof 0.3.2 » engine.py
# 
# TAOF, the general purpose TCP fuzzer.
# Copyright (C) 2007 Rodrigo Marcos
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
# 

#Python libraries
import time
import socket
import timeoutsocket
import sys
from struct import pack

#Taof libraries
import fuzzutils

#Third party libraries
import gtk

#Fuzzing signatures
overflowstrings = ["A" * 33, "A" * 128, "A" * 240, "A" * 255, "A" * 256, "A" * 257, "A" * 420, "A" * 511, "A" * 512, "A" * 1023, "A" * 1024, "A" * 2047, "A" * 2048, "A" * 4096, "A" * 4097, "A" * 5000, "A" * 10000, "A" * 20000, "A" * 32762, "A" * 32763, "A" * 32764, "A" * 32765, "A" * 32766, "A" * 32767, "A" * 32768, "A" * 65534, "A" * 65535, "A" * 65536]
formatstrings   = ["%s" * 4, "%s" * 8, "%s" * 15, "%s" * 30, "%x" * 1024, "%n" * 1025 , "%s" * 2048, "%s%n%x%d" * 5000, "%s" * 30000, "%s" * 40000, "%.1024d", "%.2048d", "%.4096d", "%.8200d", "%99999999999s", "%99999999999d", "%99999999999x", "%99999999999n", "%99999999999s" * 1000, "%99999999999d" * 1000, "%99999999999x" * 1000, "%99999999999n" * 1000, "%08x" * 100, "%%20s" * 1000,"%%20x" * 1000,"%%20n" * 1000,"%%20d" * 1000, "%#0123456x%08x%x%s%p%n%d%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%#0123456x%%x%%s%%p%%n%%d%%o%%u%%c%%h%%l%%q%%j%%z%%Z%%t%%i%%e%%g%%f%%a%%C%%S%%08x"]
integerstrings  = [-1, 0, 1, 127, 128, 255, 256, 32767, 32768, 65535, 65536, 2097151, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741823, 1073741824, 2147483647, 2147483648, 4294967295]

integerstrings_little_endian = []
for i in integerstrings:
  integerstrings_little_endian.append(pack('<I',i))
integerstrings_big_endian = []
for i in integerstrings:
  integerstrings_big_endian.append(pack('>I',i))




#############################################################################
#
# Fuzzer class 
#
#############################################################################

class fuzzer:
  
  def wait(self, seconds):
    t=time.time()
    
    while 1==1:
      if time.time()>t + seconds:
        break
      else:
        while gtk.events_pending():  # Run pending events
          gtk.main_iteration_do(False)      
        


  def send_as_is(self):
  #This function sends "as_is" requests
    for requestid in range(0, fuzzutils.context["xmllog"].get_number_requests(fuzzutils.context["xmldoc"])):
      myrequest = fuzzutils.context["xmllog"].get_request(fuzzutils.context["xmldoc"],requestid)
      if myrequest.attributes["as_is"].value == "1":
        try:
          current_request = fuzzutils.context["logger"].read_request(requestid+1)
          self.remoteserver.send(current_request)
          self.recv(fuzzutils.context["RECV_BUFFER_SIZE"])
        except:
#          print str(sys.exc_info()[0])
          return "0"
    return "1"          
  


  def fuzz_loop(self, signatures, first_part, last_part, isnumber, checklen, lvalue, middle_part, len_position, lformat):
#TO DO non dictionary attacks:
# Learn the result of a bad request and compare the result to it instead of dumping all the results on the debugging file
# Threading

    for sg in signatures:
      #time.sleep(fuzzutils.context["wait"]) # Wait for each request
      fuzzutils.context["currentsignature"] = fuzzutils.context["currentsignature"] + 1
      if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
        break
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),'*')#Adds a '*' on the fuzzing dialog

      while gtk.events_pending():  # Run pending events
        gtk.main_iteration_do(False)

      if not isnumber:
        sg=sg.strip()  #Removing the new line if this is a dictionay attack, otherwise... there shouldn't be a newline
      try:
        if checklen=='1' and not isnumber:
          injectedlen = lvalue + len(sg)
          if lformat == '1': # ASCII
            injectedlen = str(injectedlen)
          elif lformat == '2': # Little endian
            injectedlen = pack('<l',injectedlen)
          else: # Big endian
            injectedlen = pack('>l',injectedlen)

          if len_position == 0: # PREPEND value
            if isnumber:
              fuzzed_request = first_part + injectedlen + middle_part + str(sg) + last_part
            else:            
              fuzzed_request = first_part + injectedlen + middle_part + sg + last_part
          else:      # POSTPEND value
            if isnumber:
              fuzzed_request = first_part + str(sg) + middle_part + injectedlen + last_part
            else:            
              fuzzed_request = first_part + sg + middle_part + injectedlen + last_part

        else:
          if isnumber:
            fuzzed_request = first_part + str(sg) + last_part
          else:
            fuzzed_request = first_part + sg + last_part

        if fuzzutils.context["debug"]:
          if isnumber:
            debugstring = "\n*************************<REQUEST>***********************\n" 
          else:
            debugstring = "\n*************************<REQUEST>*********************** - " + str(len(sg)) + " characters\n" 
          self.file_object.write(debugstring)
          self.file_object.write(fuzzed_request)
          self.file_object.write("\n*************************<REQUEST/>***********************\n")
        if fuzzutils.context["proto"]=="tcp": # TCP
          self.remoteserver.send(fuzzed_request) # Send...
          results = self.remoteserver.recv(fuzzutils.context["RECV_BUFFER_SIZE"]) # and receive...
        else:            # UDP

          self.remoteserver.sendto(fuzzed_request, (fuzzutils.context["dest_host"], int(fuzzutils.context["dest_port"]))) # Send...
          results, addr = self.remoteserver.recvfrom(fuzzutils.context["RECV_BUFFER_SIZE"]) # and receive...
        
        if results=="": # This usually means that the remote server closed the connection
        #Although we run the risk of sending things twice, otherwise we might skip some vulnerabilities
          res = self.reconnect() # Taof first try to reconnect and repeat the request again
          #Let's handle the reconnection.
          if res=='1': # Success reconnecting
            if fuzzutils.context["proto"]=="tcp": # TCP
              self.remoteserver.send(fuzzed_request) # Send...
              results = self.remoteserver.recv(fuzzutils.context["RECV_BUFFER_SIZE"]) # and receive...
            else:            # UDP
              self.remoteserver.sendto(fuzzed_request, (fuzzutils.context["dest_host"], int(fuzzutils.context["dest_port"]))) # Send...
              results, addr = self.remoteserver.recvfrom(fuzzutils.context["RECV_BUFFER_SIZE"]) # and receive...
            #self.remoteserver.send(fuzzed_request)
            #results = self.remoteserver.recv(fuzzutils.context["RECV_BUFFER_SIZE"])
            if fuzzutils.context["debug"]:
              self.file_object.write("\n+++++++++++++++++++++++++<RESPONSE>+++++++++++++++++++++++++\n")
              self.file_object.write(results)                              
              self.file_object.write("\n+++++++++++++++++++++++++<RESPONSE/>+++++++++++++++++++++++++\n")
          elif res=='-1': # This might be good (connection issue, the service might have died)
            if fuzzutils.context["debug"]:
              if isnumber:
                debugstring = "\n*** Check this out carefully. This request killed the service.\n" 
              else:
                debugstring = "\n*** Check this out carefully. This request killed the service. Request - " + str(len(sg)) + " characters\n" 
              self.file_object.write(debugstring)
              self.file_object.write("\n*************************<BUFFER>***********************\n")
              self.file_object.write(fuzzed_request)
              self.file_object.write("\n*************************<BUFFER/>***********************\n")
              self.file_object.write("\n[*] I have to give up. I can not connect to the server" )
            fuzzutils.context["stopfuzzing"]=2
        else: # everything went ok
          if fuzzutils.context["debug"]:
            self.file_object.write("\n+++++++++++++++++++++++++<RESPONSE>+++++++++++++++++++++++++\n")
            self.file_object.write(results)                              
            self.file_object.write("\n+++++++++++++++++++++++++<RESPONSE/>+++++++++++++++++++++++++\n")                
      except socket.error, msg:
        if fuzzutils.context["debug"]:
          self.file_object.write("\n----------------------------<SOCKET EXCEPTION>-------------------------\n")
          logtemp = "Socket.error: " + str(msg)
          self.file_object.write(logtemp)    
          self.file_object.write("\n----------------------------<SOCKET EXCEPTION/>-------------------------\n")
        res = self.reconnect()
        if res=='-1': # This might be good (connection issue, the service might have died)
          if fuzzutils.context["debug"]:
            if isnumber:
              debugstring = "\n*** Check this out carefully. This request killed the service.\n" 
            else:
              debugstring = "\n*** Check this out carefully. This request killed the service. Request - " + str(len(sg)) + " characters\n" 
            self.file_object.write(debugstring)
            self.file_object.write("\n*************************<BUFFER>***********************\n")
            self.file_object.write(fuzzed_request)
            self.file_object.write("\n*************************<BUFFER/>***********************\n")
            self.file_object.write("\n[*] I have to give up. I can not connect to the server" )
          fuzzutils.context["stopfuzzing"]=2
        
      except:
        if fuzzutils.context["debug"]:
          self.file_object.write("\n----------------------------<EXCEPTION>-------------------------\n")
          self.file_object.write(str(sys.exc_info()[1]) )#+ " - " + sys.exc_info()[1])
          self.file_object.write("\n----------------------------<EXCEPTION/>-------------------------\n")
        res = self.reconnect()
        if res=='-1': # This might be good (connection issue, the service might have died)
          if fuzzutils.context["debug"]:
            if isnumber:
              debugstring = "\n*** Check this out carefully. This request killed the service.\n" 
            else:
              debugstring = "\n*** Check this out carefully. This request killed the service. Request - " + str(len(sg)) + " characters\n" 
            self.file_object.write(debugstring)
            self.file_object.write("\n*************************<BUFFER>***********************\n")
            self.file_object.write(fuzzed_request)
            self.file_object.write("\n*************************<BUFFER/>***********************\n")
            self.file_object.write("\n[*] I have to give up. I can not connect to the server" )
          fuzzutils.context["stopfuzzing"]=2


  def reconnect(self):
#This function reconnects to the remote server. If not possible the first time it tries again.
#Returns '1' on success and '-1' if reconnection was not possible
    try:
      if fuzzutils.context["proto"]=="tcp": # TCP
        self.remoteserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      else:        #UDP
        self.remoteserver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        result = self.send_as_is()
        return '1'
    except:
      pass
    
    connected = 0
    for i in range(0,2):
      try:  
        self.remoteserver.connect((fuzzutils.context["dest_host"], int(fuzzutils.context["dest_port"])))
        connected=1

      except socket.error, desc:
        #print desc
        if desc[0]==106:
          connected=1  # Already connected
        else:
          logtemp = "\n[*] It was not possible to connect to " + fuzzutils.context["dest_host"] + ":" + fuzzutils.context["dest_port"] + ". It might be down. Retrying now..."
          fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
          #time.sleep(fuzzutils.context["wait_reconnection"]) # Let's wait a little bit
      except:
        #print str(sys.exc_info()[1])
        logtemp = "\n[*] It was not possible to connect to " + fuzzutils.context["dest_host"] + ":" + fuzzutils.context["dest_port"] + ". It might be down. Retrying now..."
        fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
        self.wait(fuzzutils.context["wait_reconnection"]) # Let's wait a little bit
      if connected==1:
        break

    if connected==0: # Ooops, we could not connect to the server. The service might have died
      logtemp = "\n[*] I could not connect to the server. I might have killed the service (which is good!)."
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
      return '-1'

    result = self.send_as_is()
  #  if fuzzutils.context["debug"]:
  #    logtemp = "Authentication result:" + result + "\n"
  #    self.file_object.write(logtemp)
    return '1'
        
  def run(self):
  # This is the main loop for fuzzing
      
    if fuzzutils.context["debug"]:
      self.file_object = open("debugging" , "w")      
      logtemp = "Starting fuzzing session against " + fuzzutils.context["dest_host"] + ":" + fuzzutils.context["dest_port"]  + " - " + time.strftime("%H:%M:%S")##########################
      self.file_object.write(logtemp)

    fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
    fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"Check 'debugging' file for further information" + '\n\n')
    #initialization

    res = self.reconnect() # it establishes the connection to the server

    if res!='1':
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"\nCould not connect to the server.\n")      
      if fuzzutils.context["debug"]:
        self.file_object.write("Could not connect to the server.\n")
      return "1"
    #loops though all the requests          
    for requestid in range(0, fuzzutils.context["xmllog"].get_number_requests(fuzzutils.context["xmldoc"])):

      if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
        break
      current_request = fuzzutils.context["logger"].read_request(requestid+1) # we read the original request
      logtemp = "Fuzzing request: " + str(requestid)
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
      logtemp = "  Number of fuzzing points: " + str(fuzzutils.context["xmllog"].get_number_fuzz(fuzzutils.context["xmldoc"], requestid))
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')

      if fuzzutils.context["debug"]:
        logtemp = "Fuzzing request: " + str(requestid) + "\n"
        self.file_object.write(logtemp)
        logtemp = "  Number of fuzzing points: " + str(fuzzutils.context["xmllog"].get_number_fuzz(fuzzutils.context["xmldoc"],requestid)) + "\n"
        self.file_object.write(logtemp)
      
      #It goes through each of the fuzzing points on the current request
      for fuzzid in range (0, fuzzutils.context["xmllog"].get_number_fuzz(fuzzutils.context["xmldoc"], requestid)):
        if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
          break
        fuzzutils.context["currentsignature"] = 0
        ffrom, fto = fuzzutils.context["xmllog"].get_from_to(fuzzutils.context["xmldoc"], requestid, fuzzid)
        #it gest the boundaries of the fuzzing point

        checklen, lfrom, lto, lvalue, lformat = fuzzutils.context["xmllog"].get_len(fuzzutils.context["xmldoc"], requestid, fuzzid)
        #It gets all the necessary parameters for variable lenght calculations

        print "Testing fuzzing point ", fuzzid, ": (", ffrom, " - ", fto, ")"
        if fuzzutils.context["debug"]:
          logtemp = "Testing fuzzing point " + str(fuzzid) + ": (" + ffrom + " - " + fto + ")"
          self.file_object.write(logtemp)

        ffrom = int(ffrom)
        fto = int(fto)
        

        if checklen=='1': # This means that we need to include a variable lenght with the request
          lfrom = int(lfrom)
          lto = int(lto)
          lvalue = int(lvalue)
          
          #in order to inject the length in the correct place, we calculate the location:
          if lto<=ffrom:
            # the lenght value is located BEFORE the injection point
            first_part = current_request[:lfrom]
            middle_part = current_request[lto:ffrom]
            last_part = current_request[fto:]
            len_position = 0

          else: # We trust the value entry (we shouldn't!). To do, check that "lfrom>=to"
            # the lenght value is located AFTER the injection point
            first_part = current_request[:ffrom]
            middle_part = current_request[fto:lfrom]
            last_part = current_request[lto:]
            len_position = 1

        else: # No lenght has to be included
          first_part = current_request[:ffrom]
          last_part = current_request[fto:]
          middle_part = ''
          len_position = -1        
  
        #fuzzing buffer overflows
        if fuzzutils.context["xmllog"].fuzz_bo(fuzzutils.context["xmldoc"], requestid, fuzzid)=='1':
          logtemp = "\n + Buffer overflows"
          fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')

          self.fuzz_loop(overflowstrings, first_part, last_part, 0, checklen, lvalue, middle_part, len_position, lformat)
        if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
          break
      
        #fuzzing format strings                 
        if fuzzutils.context["xmllog"].fuzz_fs(fuzzutils.context["xmldoc"], requestid, fuzzid)=='1':
          logtemp = "\n + Format Strings"
          fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
          
          self.fuzz_loop(formatstrings, first_part, last_part, 0, checklen, lvalue, middle_part, len_position, lformat)
        
        if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
          break
  
        #fuzzing integer strings
        if fuzzutils.context["xmllog"].fuzz_int(fuzzutils.context["xmldoc"], requestid, fuzzid)=='1':
          logtemp = "\n + Integer Overflows"
          fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
           
          #Numbers in Ascii
          self.fuzz_loop(integerstrings, first_part, last_part, 1, checklen, lvalue, middle_part, len_position, lformat)
          if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
            break
          #Numbers in little Endian
          self.fuzz_loop(integerstrings_little_endian, first_part, last_part, 0, checklen, lvalue, middle_part, len_position, lformat)
          if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
            break
          #Numbers in big Endian
          self.fuzz_loop(integerstrings_big_endian, first_part, last_part, 0, checklen, lvalue, middle_part, len_position, lformat)

        if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
          break

        if fuzzutils.context["xmllog"].fuzz_dict(fuzzutils.context["xmldoc"], requestid, fuzzid)=='1' and fuzzutils.context["dictionary"]!='':
          logtemp = "\n + Dictionary Attack"
          dictionary_file = open(fuzzutils.context["dictionary"])
          fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),logtemp + '\n')
          self.fuzz_loop(dictionary_file, first_part, last_part, 0, checklen, lvalue, middle_part, len_position, lformat)
          dictionary_file.close()
        
        if fuzzutils.context["stopfuzzing"]!=0: # The user decided to stop fuzzing
          break
  

    if fuzzutils.context["debug"]:
      self.file_object.close()
    if fuzzutils.context["stopfuzzing"]==1: # The user decided to stop fuzzing
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"\n[*] Fuzzing session finished by user.\n")
      fuzzutils.context["stopfuzzing"]=0
    elif fuzzutils.context["stopfuzzing"]==2:
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"\n[*] Fuzzing session because remote server is not responding.\n")
      fuzzutils.context["stopfuzzing"]=0
    else:
      fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"\n[*] Fuzzing session finished.\n")

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.