#!/usr/bin/env python
# 
# 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.
# 
		
#----------------------------------------------------------------------
# guifuzzer.py
#----------------------------------------------------------------------

#Python libraries
import sys
import gobject
import binascii 
import webbrowser # for displaying help on a browser
print "[+] Internal libraries imported."
#Taof libraries
try:
    import fuzzutils
    print "[+] Taof libraries imported."
except:
    print "[Error] Taof could not import fuzzutils library. Make sure you uncompressed all the files in the same folder."
    sys.exit(0)

#Third party libraries
try:
    import gtk.glade
    print "[+] Glade libraries imported."
except:
    print "[Error] Could not import glade library. Refer to http://sourceforge.net/forum/?group_id=176014 for help."
    sys.exit(0)

try:
    import pygtk
    print "[+] PyGTK libraries imported."
except:
    print "[Error] Could not import pygtk library. Refer to http://sourceforge.net/forum/?group_id=176014 for help."
    sys.exit(0)
    
try:
    import gtk
    print "[+] GTK libraries imported."
except:
    print "[Error] Could not import gtk library. Refer to http://sourceforge.net/forum/?group_id=176014 for help."
    sys.exit(0)
    
if fuzzutils.context["os"]=='nt':
    try:
        import debug #PyDbg libraries
        print "[+] PyDbg  imported. Debugging will be available"
        fuzzutils.context["pydbg"]=1
    except:
        print "[+] PyDbg library could not be imported. Install PyDbg if you want debugging monitoring. (Recommended)"
        fuzzutils.context["pydbg"]=0
else:
    print "[+] Debugging will be disabled. (Only supported on Windows like OS)"
    fuzzutils.context["pydbg"]=0

(
    COLUMN_ID,
    COLUMN_TIME
) = range(2)

(
    COLUMN_FROM,
    COLUMN_TO,
	COLUMN_OS,
	COLUMN_FL,
	COLUMN_TL
) = range(5)


VERSION = '0.3'

class taof:

	current_request = 1
	cb_dict = {}
	widget_list = [
			'Settings',
			'localserver',
			'localport',
			'remoteserver',
			'remoteport',
			'radioprotocol',
			'radioprotocol2',
			'OK',
			'usessl',
			'Main',
			'settings',
			'listen', # Start on Dataretrieval
			'stoplisten', # stop listen on Dataretrieval
			'ignore',
			'fuzz', # start fuzzing on fuzzing dialog
			'stopfuzzingbutton', # stop fuzzing on the fuzzing dialog
			'targethost', # target host (fuzzing dialog)
			'targetport', # (fuzzing dialog)
			'targettcp', # (fuzzing dialog)
			'targetudp', # (fuzzing dialog)
			'attachbutton', # (fuzzing dialog)
			'from',
			'to',
			'apply',
			'scrolledwindow4',
			'requesttext',
			'statusbar1',
			'FuzzPoints',
			'asciiview',
			'hexview',
			'txtFrom',
			'txtTo',
			'setfuzz', # set fuzzing points button in main
			'checklen', # set fuzzing points 
			'lenfrom', # set fuzzing points 
			'lento', # set fuzzing points 
			'lenvalue', # set fuzzing points 
			'lenascii', # set fuzzing points 
			'lenlittle', # set fuzzing points
			'lenbig', # set fuzzing points 
			'lenlabel1', # set fuzzing points
			'lenlabel2', # set fuzzing points 
			'lenlabel3', # set fuzzing points 
			'lenlabel4', # set fuzzing points button in main
			'FuzzPoints',
			'scrolledwindow7',
			'add_fuzz',
			'del_fuzz',
			'open',
			'filechooserdialog1', # File chooser for fuzzing files
			'filechooserdialog2', # File chooser for dictionaries
			'cbasis',
			'ok_fuzz',
			'request',
			'aboutdialog1', # about dialog
			'about1', # about menu
			'checkstackheap', # checkbox heap in fuzzingpoints
			'checkstring', # checkbox string on fuzzingpooints
			'checkinteger', # checkbox integer on fuzzingpoints
			'checkdictionary', # checkbox dictionary on fuzzingpoints
			'dataretrievalbutton', # dataretrieval button on main dialog
			'fuzzingbutton', # fuzzing button on main dialog
			'fuzzingdialog', # fuzzing dialog
			'dataretrievaldialog', # dataretrieval dialog
			'dataretrievalok', # hide dataretrieval dialog
			'open1', #menu
			'quit1', #menu
			'help1', #menu
			'listeninglog', # log on dataretrieval
			'fuzzinglog', # log on fuzzingdialog
			'taofsettings_dialog', # taof settings dialog
			'taof_settings_menu', # taof settings option on menu bar
			'menu_timeout', # text field for timeout (taof settings dialog)
			'menu_wait', # text field for waitn (taof settings dialog)
			'menu_wait_reconnection', # text field for wait_reconnection (taof settings dialog)
			'menu_dictionary', # text field for dictionary (taof settings dialog)
			'open_dictionary', # text field for opening a dictionary (taof settings dialog)
			'taof_settings_cancel', # button for cancel (taof settings dialog)
			'taof_settings_ok', # buttong for ok (taof settings dialog)
			'attachprocess', # Attach process dialog
			'okprocess', # OK - process dialog
			'processestree', # Processes tree - process dialog
		
]

	top_window = 'Main'

#----------------------------------------------------------------------

	def __init__(self):
	
		filename = 'fuzzer.glade'
		self.xml = gtk.glade.XML(filename)
		self.init()

#----------------------------------------------------------------------

	def init(self):
		
		
		self.widgets = {}
		for w in self.widget_list:
			self.widgets[w] = self.xml.get_widget(w)
		
		self.create_fuzzer_points_list()
		
		self.create_callbacks()

		self.logdataretrieval = gtk.TextBuffer(None)
		self.widgets['listeninglog'].set_buffer(self.logdataretrieval)

		fuzzutils.context["fuzzinglog"] = gtk.TextBuffer(None)
		self.widgets['fuzzinglog'].set_buffer(fuzzutils.context["fuzzinglog"])
		fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),"Click on 'Start' to begin fuzzing.\n\n")

		statusbar = self.widgets['statusbar1']
		fuzzutils.context["statusbar"] = statusbar.get_context_id("Fuzzer")
		self.push_statusbar("Ready")
		self.set_settings(self)


# TO DO: Fix version function.
#		version = fuzzutils.checkupdates()
#		if version.checkupdate() == '1':
#			self.push_statusbar("A new version of Taof is available. Visit Taof homepage for downloads.")



#----------------------------------------------------------------------

	def create_callbacks(self):

		item = self.widgets['about1']
		item.connect('activate', self.on_about_clicked)

		item = self.widgets['help1']
		item.connect('activate', self.on_help1_clicked)

		item = self.widgets['taof_settings_menu']
		item.connect('activate', self.on_taof_settings_menu_clicked)

		item = self.widgets['settings']
		item.connect('clicked', self.on_settings_clicked)

		item = self.widgets['listen']
		item.connect('clicked', self.on_listen_clicked)

		item = self.widgets['stoplisten']
		item.connect('clicked', self.on_stoplisten_clicked)

		item = self.widgets['fuzz']
		item.connect('clicked', self.on_fuzz_clicked)

		item = self.widgets['stopfuzzingbutton']
		item.connect('clicked', self.on_stopfuzzingbutton_clicked)

		item = self.widgets['dataretrievalbutton']
		item.connect('clicked', self.on_dataretrievalbutton_clicked)

		item = self.widgets['fuzzingbutton']
		item.connect('clicked', self.on_fuzzingbutton_clicked)
		
		item = self.widgets['Main']
		item.connect('hide', self.on_Main_destroy_event)

		item = self.widgets['quit1']
		item.connect('activate', self.on_Main_destroy_event)

		item = self.widgets['Main']
		item.connect('destroy_event', self.on_Main_destroy_event)

		item = self.widgets['OK']
		item.connect('clicked', self.on_OK_clicked)

		item = self.widgets['setfuzz']
		item.connect('clicked', self.on_setfuzz_clicked)

		item = self.widgets['asciiview']
		item.connect('button_release_event', self.on_button_release)
		
		item = self.widgets['FuzzPoints']
		item.connect('delete_event', self.on_fuzzing_points_delete_event)

		item = self.widgets['Settings']
		item.connect('delete_event', self.on_settings_delete_event)

		item = self.widgets['dataretrievaldialog']
		item.connect('delete_event', self.on_dataretrievaldialog_delete_event)

		item = self.widgets['taofsettings_dialog']
		item.connect('delete_event', self.on_taofsettings_dialog_delete_event)

		item = self.widgets['dataretrievalok']
		item.connect('clicked', self.on_dataretrievaldialog_delete_event)

		item = self.widgets['fuzzingdialog']
		item.connect('delete_event', self.on_fuzzingdialog_delete_event)

		item = self.widgets['aboutdialog1']
		item.connect('delete_event', self.on_aboutdialog_delete_event)

		item = self.widgets['FuzzPoints']
		item.connect('show', self.fuzz_points_show)

		item = self.widgets['FuzzPoints']
		item.connect('key_press_event', self.fuzz_points_keypressed)

		item = self.widgets['add_fuzz']
		item.connect('clicked', self.add_fuzzer_point)

		item = self.widgets['del_fuzz']
		item.connect('clicked', self.del_fuzzer_point)
		
		item = self.widgets['open']
		item.connect('clicked', self.open_file)

		item = self.widgets['open1']
		item.connect('activate', self.open_file)
		
		item = self.widgets['cbasis']
		item.connect('clicked', self.as_is_clicked)
		
		item = self.widgets['ok_fuzz']
		item.connect('clicked', self.ok_fuzz_clicked)

		item = self.widgets['checklen']
		item.connect('clicked', self.checklen_clicked)
		
		item = self.widgets['open_dictionary']
		item.connect('clicked', self.open_dictionary_clicked)

		item = self.widgets['taof_settings_ok']
		item.connect('clicked', self.taof_settings_ok_clicked)

		item = self.widgets['taof_settings_cancel']
		item.connect('clicked', self.taof_settings_cancel_clicked)

		item = self.widgets['attachbutton']
		item.connect('clicked', self.taof_attachbutton_clicked)

		item = self.widgets['attachprocess']
		item.connect('delete_event', self.on_attachprocess_delete_event)
		
		item = self.widgets['okprocess']
		item.connect('clicked', self.taof_okprocess_clicked)
		
#----------------------------------------------------------------------

	def create_fuzzer_points_list(self):

		model = gtk.ListStore(gobject.TYPE_UINT,gobject.TYPE_UINT,gobject.TYPE_UINT,gobject.TYPE_UINT,gobject.TYPE_UINT)
			
		treeview =  gtk.TreeView(model)
		treeview.id = "FuzzPointsList"
		treeview.set_rules_hint(True)
		treeview.set_search_column(COLUMN_TIME)

		sw = self.widgets['scrolledwindow7']
		sw.add(treeview)

		
				# columns
		column = gtk.TreeViewColumn('From', gtk.CellRendererText(),
		                            text=COLUMN_FROM)
		treeview.append_column(column)
		
		column = gtk.TreeViewColumn('To', gtk.CellRendererText(),
		                            text=COLUMN_TO)
		treeview.append_column(column)

		column = gtk.TreeViewColumn('Value (length)', gtk.CellRendererText(),
		                            text=COLUMN_OS)
		treeview.append_column(column)

		column = gtk.TreeViewColumn('From (length)', gtk.CellRendererText(),
		                            text=COLUMN_FL)
		treeview.append_column(column)

		column = gtk.TreeViewColumn('To (length)', gtk.CellRendererText(),
		                            text=COLUMN_TL)
		treeview.append_column(column)

		
		treeview.show()
		
#----------------------------------------------------------------------

	def create_tree_view(self): # Creates a list with the saved requests after stopping listener
	
		data=[]
		pair=[1,'']
		data1 = fuzzutils.context["xmllog"].get_requests(fuzzutils.context["xmldoc"])
		for request in range(0, len(data1)):
			pair[0] = int(data1[request].attributes["ID"].value)
			pair[1] = str(data1[request].attributes["time"].value)
			data.append(pair[:])

		model = gtk.ListStore(gobject.TYPE_UINT,gobject.TYPE_STRING)
			
		for item in data:
			iter = model.append()
			model.set(iter, 0, item[0],	1, str(item[1]))	

		treeview =  gtk.TreeView(model)
		treeview.set_rules_hint(True)
		treeview.set_search_column(COLUMN_TIME)

		sw = self.widgets['scrolledwindow4']
		child = sw.get_child() 
		if child != None:
			sw.remove(child)
					
		sw.add(treeview)

		treeview.connect('row_activated', self.on_setfuzz_clicked)

		selection = treeview.get_selection()
		selection.set_mode(gtk.SELECTION_BROWSE)

		selection.connect('changed', self.selection_changed_cb)
#		selection.connect('clicked', self.selection_clicked)

	

		column = gtk.TreeViewColumn('Request ID', gtk.CellRendererText(),
		                            text=COLUMN_ID)
		column.set_sort_column_id(COLUMN_ID)
		treeview.append_column(column)
		

		# columns
		column = gtk.TreeViewColumn('Time', gtk.CellRendererText(),
		                            text=COLUMN_TIME)
		column.set_sort_column_id(COLUMN_TIME)
		treeview.append_column(column)
		treeview.show()
		self.enablefuzzing()
		#by default, the first one is selected
		try:
			firstone = model.get_iter(0)
			selection.select_iter(firstone)
		except:
			pass

			
#----------------------------------------------------------------------		
		
	def push_statusbar(self, message):
		self.widgets['statusbar1'].push(fuzzutils.context["statusbar"], message)

#----------------------------------------------------------------------

	def pop_statusbar(self):
		self.widgets['statusbar1'].pop(fuzzutils.context["statusbar"])

#----------------------------------------------------------------------

	def load_request_list(self):
		pass

#----------------------------------------------------------------------

	def alert(self, type, text):
		message = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, gtk.BUTTONS_OK, text)
		resp = message.run()
		if resp == gtk.RESPONSE_OK:
			message.destroy()

#----------------------------------------------------------------------

	def load_request(self, request_id): # loads request for fuzzing points
		mytextview = self.widgets['requesttext']
		mytextview.set_editable(0)
		mytextview.set_wrap_mode(2)
		mybuffer = mytextview.get_buffer()
		filename = str(request_id) + "req"
		try:
			str_request = fuzzutils.context["logger"].read_request(request_id)
		except:
			return False

		if str_request:
				mybuffer.set_text("%r"%str_request)
				result=""
				myhexview = self.widgets['hexview']
				myhexview.set_editable(0)
				myhexbuffer = myhexview.get_buffer()
				asciiresult=""
				
				for c in str_request[:]:
					result+= binascii.hexlify(c) + ' '

				myhexbuffer.set_text(result)
		
				asciiresult=""
				myasciiview = self.widgets['asciiview']
				myasciiview.set_editable(0)
				myasciibuffer = myasciiview.get_buffer()
				asciiresult=""
				for c in str_request[:]:
					#print ord(c)
					if ord(c) in range(32,127) + [10,13]: # ascii printable characters 
						asciiresult += c
					else:
						asciiresult += "."
					myasciibuffer.set_text(asciiresult)
				#print asciiresult

#----------------------------------------------------------------------

	def selection_changed_cb(self, selection, *args): # This def refreshes the request display when changing the request.
		model, iter = selection.get_selected()
		if not iter:
			return False
		
		name = model.get_value(iter, COLUMN_ID)
		self.current_request = name
		myrequest = fuzzutils.context["xmllog"].get_request(fuzzutils.context["xmldoc"], self.current_request-1)
		self.widgets['cbasis'].set_active(int(myrequest.attributes["as_is"].value))
		

		# to do: only display if window=visible, otherwise, skip this line
		self.load_request(name)
#		self.fuzz_points_show()

		

#----------------------------------------------------------------------
	def on_settings_delete_event(self, *args):
		if self.widgets['localserver'].get_text() != "":
			fuzzutils.context["local_host"] = self.widgets['localserver'].get_text() 
		if self.widgets['localport'].get_text() != "":
			fuzzutils.context["local_port"] = self.widgets['localport'].get_text()
		if self.widgets['remoteserver'].get_text() != "":
			fuzzutils.context["dest_host"] = self.widgets['remoteserver'].get_text()
		if self.widgets['remoteport'].get_text() != "":
			fuzzutils.context["dest_port"] = self.widgets['remoteport'].get_text()

		tcpproto = self.widgets['radioprotocol']  # tcp protocol
		udpproto = self.widgets['radioprotocol2'] # udp protocol

		if tcpproto.get_active(): # TCP
					fuzzutils.context["proto"]="tcp"
		else:						#UDP
					fuzzutils.context["proto"]="udp"

		if fuzzutils.context.has_key("dest_host") and fuzzutils.context.has_key("dest_port") and fuzzutils.context.has_key("local_port") and fuzzutils.context.has_key("local_host"):
			self.widgets['listen'].set_sensitive(True)
			string = " WARNING: Due to a limitation on the network library, 'port forwarding' can only happen once during execution, so please make sure that you set up everythink ok. \n\n"
			string = string + "[*] Listening service:\n\t - Local: " + fuzzutils.context["local_host"] + ":" + fuzzutils.context["local_port"] + "\n\t - Remote: " + fuzzutils.context["dest_host"] + ":" + fuzzutils.context["dest_port"] + "\n\t - Protocol: " +  fuzzutils.context["proto"] + "\n\n"
			string = string + "Please clik on 'Start' when ready.\n\n"
			self.logdataretrieval.insert(self.logdataretrieval.get_end_iter(),string)

		self.widgets['Settings'].hide()
		
		return 1

#----------------------------------------------------------------------

	def on_about_clicked(self, *args):
		self.widgets['aboutdialog1'].show()

#----------------------------------------------------------------------

	def on_help1_clicked(self, *args):
		#print fuzzutils.context["TAOF_HELP_PATH"]
		webbrowser.open(fuzzutils.context["TAOF_HELP_PATH"])
	
#----------------------------------------------------------------------

	def on_taof_settings_menu_clicked(self, *args):
			self.widgets['taofsettings_dialog'].show()	

#----------------------------------------------------------------------

	def on_settings_clicked(self, *args):
			self.widgets['Settings'].show()

#----------------------------------------------------------------------

	def on_dataretrievalbutton_clicked(self, *args):
			self.widgets['dataretrievaldialog'].show()

		
#----------------------------------------------------------------------

	def on_fuzzingbutton_clicked(self, *args):
			self.widgets['targethost'].set_text(fuzzutils.context["dest_host"])
			self.widgets['targetport'].set_text(fuzzutils.context["dest_port"])
			if fuzzutils.context["proto"]=="tcp":
				self.widgets['targettcp'].set_active(1)
			else:
				self.widgets['targetudp'].set_active(1)
			if fuzzutils.context["pydbg"]==0:
				self.widgets["attachbutton"].set_sensitive(False)
			self.widgets['fuzzingdialog'].show()

#----------------------------------------------------------------------

	def on_taofsettings_dialog_delete_event(self, *args):
		self.widgets['taofsettings_dialog'].hide()
		return 1

#----------------------------------------------------------------------

	def on_aboutdialog_delete_event(self, *args):
		self.widgets['aboutdialog1'].hide()
		return 1
		
#----------------------------------------------------------------------

	def on_fuzzingdialog_delete_event(self, *args):
		self.widgets['fuzzingdialog'].hide()
		return 1


#----------------------------------------------------------------------

	def on_attachprocess_delete_event(self, *args):
		self.widgets['attachprocess'].hide()
		return 1


#----------------------------------------------------------------------
	def on_dataretrievaldialog_delete_event(self, *args):

		if self.widgets['stoplisten'].get_property('sensitive'):
			self.on_stoplisten_clicked()
		else:
			self.widgets['dataretrievaldialog'].hide()
		return 1

#----------------------------------------------------------------------


	def on_listen_clicked(self, *args):
		
		if not fuzzutils.context.has_key("dest_host") or not fuzzutils.context.has_key("dest_port") or not fuzzutils.context.has_key("local_port") or not fuzzutils.context.has_key("local_host"):
			#print 
			self.alert(gtk.MESSAGE_ERROR, "Please set forwarding information.")
		else:
			try:
				fuzzutils.context["REQUEST_COUNTER"]=0

				if fuzzutils.context["proto"]=="tcp": # TCP
					fuzzutils.reactor.listenTCP(int(fuzzutils.context["local_port"]), fuzzutils.portforward.ProxyFactory(fuzzutils.context["dest_host"], int(fuzzutils.context["dest_port"])))
				else:						#UDP
					fuzzutils.reactor.listenUDP(int(fuzzutils.context["local_port"]), fuzzutils.UDPServer())
				self.push_statusbar("Forwarding conections...")				
				if fuzzutils.context.has_key("logger"):
					del fuzzutils.context["logger"]
				if fuzzutils.context.has_key("xmllog"):
					del fuzzutils.context["xmllog"]
				if fuzzutils.context.has_key("xmldoc"):
					del fuzzutils.context["xmldoc"]
		
				fuzzutils.context["logger"] = fuzzutils.Log()
				fuzzutils.context["xmllog"] = fuzzutils.xmlfuzz()
				fuzzutils.context["xmldoc"], fuzzutils.context["xmlconv"] = fuzzutils.context["xmllog"].create_document(fuzzutils.context["local_host"], fuzzutils.context["local_port"], fuzzutils.context["dest_host"], str(fuzzutils.context["dest_port"]), fuzzutils.context["proto"])
	
				self.widgets['listen'].set_sensitive(False)
				self.widgets['settings'].set_sensitive(False)
				self.widgets['stoplisten'].set_sensitive(True)
				self.widgets['dataretrievalok'].set_sensitive(False)
				self.widgets['open'].set_sensitive(False)
			
				self.logdataretrieval.insert(self.logdataretrieval.get_end_iter(),"[*] Forwarding traffic...\n")
				self.logdataretrieval.insert(self.logdataretrieval.get_end_iter(),"\t - Logging requests under '" + fuzzutils.context["logger"].folder + "' folder \n\nClick 'Stop' when finished. \n ")
				fuzzutils.context["reactor"]=1				
				fuzzutils.reactor.run()

			except:
				self.alert(gtk.MESSAGE_ERROR, "Error setting listener: " + str(sys.exc_info()[0]) + " - " + str(sys.exc_info()[1]))
				self.widgets['listen'].set_sensitive(True)
				self.widgets['settings'].set_sensitive(True)
				self.widgets['stoplisten'].set_sensitive(False)
				self.widgets['dataretrievalok'].set_sensitive(True)
				self.widgets['open'].set_sensitive(True)
				fuzzutils.context["reactor"]=0			
#----------------------------------------------------------------------
	def on_stoplisten_clicked(self, *args):
		try:
			if fuzzutils.context.has_key("reactor") and fuzzutils.context["reactor"]:
				self.push_statusbar("Stop forwarding...")
				fuzzutils.reactor.stop()
				fuzzutils.context["reactor"]=0
				self.create_tree_view()
				fuzzutils.context["xmllog"].write_to_file(fuzzutils.context["xmldoc"])
				self.push_statusbar("Ready")
				#del fuzzutils.context["logger"] # we stop logging
				#self.widgets['listen'].set_sensitive(True)
				#self.widgets['settings'].set_sensitive(True)
				self.widgets['stoplisten'].set_sensitive(False)
				self.widgets['dataretrievalok'].set_sensitive(True)
				self.widgets['open'].set_sensitive(True)
				self.logdataretrieval.insert(self.logdataretrieval.get_end_iter(),"[*] Forwarding service was stopped by the user.\n\n")

			self.widgets['dataretrievaldialog'].hide()			
		except:
			self.alert(gtk.MESSAGE_ERROR, "Error: " + str(sys.exc_info()[0]) + " - " + str(sys.exc_info()[1]))

#----------------------------------------------------------------------

	def on_fuzz_clicked(self, *args):
		#try:
			if not fuzzutils.context.has_key("xmllog"):
				self.alert(gtk.MESSAGE_ERROR, "It's not possible to run a fuzzing session without previously retrieve information.")
			else:
				self.push_statusbar("Fuzzing...")
				fuzzutils.context["xmllog"].write_to_file(fuzzutils.context["xmldoc"])
				fuzzengine = fuzzutils.fuzzer()
				self.widgets['stopfuzzingbutton'].set_sensitive(True)				
				self.widgets['fuzz'].set_sensitive(False)

				# We retrieve target details
				fuzzutils.context["dest_host"] = self.widgets['targethost'].get_text()
				fuzzutils.context["dest_port"] = self.widgets['targetport'].get_text()
				if self.widgets['targettcp'].get_active():

					fuzzutils.context["proto"]="tcp"
				else:
					fuzzutils.context["proto"]="udp"

				fuzzengine.run()
				self.widgets['stopfuzzingbutton'].set_sensitive(False)				
				self.widgets['fuzz'].set_sensitive(True)								
				self.push_statusbar("Fuzz finished.")
		#except:
		#	self.alert(gtk.MESSAGE_ERROR, "Error: " + str(sys.exc_info()[0]) + " - " + str(sys.exc_info()[1]))

#----------------------------------------------------------------------

	def on_stopfuzzingbutton_clicked(self, *args):
		fuzzutils.context['stopfuzzing']=1
		
#	def on_apply_clicked(self, *args):
#		pass


#----------------------------------------------------------------------
	def on_button_release(self, *args):

		mytextview = self.widgets['asciiview']
#		mytextview.set_editable(0)
		mybuffer = mytextview.get_buffer()
		data = mybuffer.get_selection_bounds()
		if data:
			if not self.widgets['checklen'].get_active(): # we are setting main boundaries
				tFrom = self.widgets['txtFrom']
				tTo = self.widgets['txtTo']
				tFrom.set_text(str(data[0].get_offset()))
				tTo.set_text(str(data[1].get_offset()))
				self.widgets['checklen'].set_sensitive(True)
			else:	# We are setting boundaries for the length value
				tFrom = self.widgets['lenfrom']
				tTo = self.widgets['lento']
				tFrom.set_text(str(data[0].get_offset()))
				tTo.set_text(str(data[1].get_offset()))	
			
#----------------------------------------------------------------------

	def on_Main_destroy_event(self, *args):
		gtk.main_quit()
		sys.exit(-1)

#----------------------------------------------------------------------

	def ok_fuzz_clicked(self, *args):
		self.widgets['FuzzPoints'].hide()

#----------------------------------------------------------------------

	def on_OK_clicked(self, *args):
		self.on_settings_delete_event()

#----------------------------------------------------------------------

	def on_setfuzz_clicked(self, *args):
		self.widgets['FuzzPoints'].show()

#----------------------------------------------------------------------

	def fuzz_points_show(self, *args):
		sw = self.widgets['scrolledwindow7']
		mylist = sw.get_children()
		model = mylist[0].get_model()

		for a in range(0,len(model)):
			del model[0]

		fuzzing_points = fuzzutils.context["xmllog"].get_fuzzs(fuzzutils.context["xmldoc"], self.current_request-1)
		for fuzz in range(0, len(fuzzing_points)):
			iter = model.append()
			
			model.set(iter, 0, int(fuzzing_points[fuzz].attributes["from"].value), 1, int(fuzzing_points[fuzz].attributes["to"].value), 2, int(fuzzing_points[fuzz].attributes["lvalue"].value), 3, int(fuzzing_points[fuzz].attributes["lfrom"].value), 4, int(fuzzing_points[fuzz].attributes["lto"].value))
	
#----------------------------------------------------------------------		
	def fuzz_points_keypressed(self, widget, event):
		if event.keyval== gtk.keysyms.Escape:
			self.widgets['FuzzPoints'].hide()

#----------------------------------------------------------------------			
	def add_fuzzer_point(self, *args):


#TO DO:
#	- Control length
#	- Check the value of checklen
#	- Retrieve boundaries
#	- Retrieve value
	
#	- check dictionary attack

		sw = self.widgets['scrolledwindow7']
		mylist = sw.get_children()
		model = mylist[0].get_model()		

		iter = model.append()

		nto = self.widgets['txtTo']
		nfrom = self.widgets['txtFrom']		

		lto = self.widgets['lento']
		lfrom = self.widgets['lenfrom']
		lvalue = self.widgets['lenvalue']
		lascii = self.widgets['lenascii']
		llittle = self.widgets['lenlittle']
		lbig = self.widgets['lenbig']

		if lascii.get_active():
			lformat = 1 # Ascii
		elif llittle.get_active():
			lformat = 2 # Little endian
		else:
			lformat = 3 # Big endian

		checkstackheap = int(self.widgets['checkstackheap'].get_active())
		checkstring = int(self.widgets['checkstring'].get_active())
		checkinteger = int(self.widgets['checkinteger'].get_active())
		checkdictionary = int(self.widgets['checkdictionary'].get_active())

		myrequest = fuzzutils.context["xmllog"].get_request(fuzzutils.context["xmldoc"], self.current_request-1)

		if self.widgets['checklen'].get_active(): 
#TO DO: basic tests (all fields completed and with correct values)
# Also, check that the length value is not within the fuzzed value
			model.set(iter, 0,int(nfrom.get_text()), 1, int(nto.get_text()), 2, int(lvalue.get_text()), 3, int(lfrom.get_text()), 4, int(lto.get_text()),)
			fuzzutils.context["xmllog"].add_fuzz(fuzzutils.context["xmldoc"], myrequest, nfrom.get_text(), nto.get_text(), checkstackheap, checkstring, checkinteger, checkdictionary, '1', lfrom.get_text(), lto.get_text(), lvalue.get_text(), lformat)
		else:
			model.set(iter, 0,int(nfrom.get_text()), 1, int(nto.get_text()))	
			fuzzutils.context["xmllog"].add_fuzz(fuzzutils.context["xmldoc"], myrequest, nfrom.get_text(), nto.get_text(), checkstackheap, checkstring, checkinteger, checkdictionary, '0', '0', '0', '0', '0')

		fuzzutils.context["xmllog"].write_to_file(fuzzutils.context["xmldoc"])

		nto.set_text('')
		nfrom.set_text('')
		self.widgets['checklen'].set_active(False) # Disable again checklen (and will trigger the Checklen_clicked() )
		self.widgets['checklen'].set_sensitive(False) # Disable again checklen
		

#----------------------------------------------------------------------

	def del_fuzzer_point(self, *args):

		sw = self.widgets['scrolledwindow7']
		mylist = sw.get_children()
		
		selection = mylist[0].get_selection()
		selection.set_mode(gtk.SELECTION_BROWSE)

		model, iter = selection.get_selected()
		if not iter:
			return False
		path = model.get_path(iter)
		selected_row= path[0]
		model.remove(iter)

		myrequest = fuzzutils.context["xmllog"].get_request(fuzzutils.context["xmldoc"], self.current_request-1)
		fuzzutils.context["xmllog"].del_fuzz(fuzzutils.context["xmldoc"], myrequest, selected_row)
		fuzzutils.context["xmllog"].write_to_file(fuzzutils.context["xmldoc"])

		
#----------------------------------------------------------------------

	def on_fuzzing_points_delete_event(self, *args):
		self.widgets['FuzzPoints'].hide()
		return 1

#----------------------------------------------------------------------	
	
	def open_file(self, *args):

		filter = gtk.FileFilter()
		filter.set_name('Fuzzing files')
		filter.add_pattern('fuzz.xml')
		self.widgets['filechooserdialog1'].add_filter(filter)

		response = self.widgets['filechooserdialog1'].run()
		self.widgets['filechooserdialog1'].hide()		

		if response == gtk.RESPONSE_OK:
			fuzzutils.context["logger"] = fuzzutils.Log(self.widgets['filechooserdialog1'].get_current_folder())
			fuzzutils.context["xmllog"] = fuzzutils.xmlfuzz()
			fuzzutils.context["xmldoc"], fuzzutils.context["xmlconv"] = fuzzutils.context["xmllog"].get_document(self.widgets['filechooserdialog1'].get_filename())

			fuzzutils.context["local_host"], fuzzutils.context["local_port"], fuzzutils.context["dest_host"], fuzzutils.context["dest_port"], fuzzutils.context["proto"] = fuzzutils.context["xmllog"].get_network_info(fuzzutils.context["xmldoc"])

			self.widgets['localserver'].set_text(fuzzutils.context["local_host"])
			self.widgets['localport'].set_text(fuzzutils.context["local_port"])
			self.widgets['remoteserver'].set_text(fuzzutils.context["dest_host"])
			self.widgets['remoteport'].set_text(fuzzutils.context["dest_port"])
	
			if fuzzutils.context["proto"]=="tcp":
				self.widgets['radioprotocol'].set_active(1)
			else:
				self.widgets['radioprotocol2'].set_active(1)
				
			try:
				self.create_tree_view()
			except:
				self.alert(gtk.MESSAGE_ERROR, "Error retrieving information from file")
				return '-1'				
			self.enablefuzzing()
			self.on_dataretrievaldialog_delete_event()


#----------------------------------------------------------------------	
	
	def open_dictionary_clicked(self, *args):

		response = self.widgets['filechooserdialog2'].run()
		self.widgets['filechooserdialog2'].hide()		

		if response == gtk.RESPONSE_OK:
			fuzzutils.context["dictionary"] = self.widgets['filechooserdialog2'].get_filename()
			self.widgets['menu_dictionary'].set_text(fuzzutils.context["dictionary"])


		
#----------------------------------------------------------------------

	def as_is_clicked(self, *args):
		myrequest = fuzzutils.context["xmllog"].get_request(fuzzutils.context["xmldoc"], self.current_request-1)
		if self.widgets['cbasis'].get_active():
			fuzzutils.context["xmllog"].add_as_is(fuzzutils.context["xmldoc"], myrequest)
		else:
			fuzzutils.context["xmllog"].del_as_is(fuzzutils.context["xmldoc"], myrequest)
		#fuzzutils.context["xmllog"].write_to_screen(fuzzutils.context["xmldoc"])	
			
	
#----------------------------------------------------------------------

	def enablefuzzing(self, *args):
		self.widgets['fuzzingbutton'].set_sensitive(True)
		self.widgets['setfuzz'].set_sensitive(True)
		self.widgets['cbasis'].set_sensitive(True)

#----------------------------------------------------------------------

	def checklen_clicked(self, *args):
		tostate = self.widgets['checklen'].get_active()
		self.widgets['lenfrom'].set_sensitive(tostate)
		self.widgets['lento'].set_sensitive(tostate)
		self.widgets['lenvalue'].set_sensitive(tostate)
		self.widgets['lenascii'].set_sensitive(tostate)
		self.widgets['lenlittle'].set_sensitive(tostate)
		self.widgets['lenbig'].set_sensitive(tostate)
		self.widgets['lenlabel1'].set_sensitive(tostate)
		self.widgets['lenlabel2'].set_sensitive(tostate)
		self.widgets['lenlabel3'].set_sensitive(tostate)
		self.widgets['lenlabel4'].set_sensitive(tostate)

#----------------------------------------------------------------------

	def set_settings(self, *args):
		self.widgets['menu_timeout'].set_text(str(fuzzutils.context["timeout"]))
		self.widgets['menu_wait'].set_text(str(fuzzutils.context["wait"]))
		self.widgets['menu_wait_reconnection'].set_text(str(fuzzutils.context["wait_reconnection"]))
		self.widgets['menu_dictionary'].set_text(fuzzutils.context["dictionary"])

		fuzzutils.timeoutsocket.setDefaultSocketTimeout(fuzzutils.context["timeout"])

#----------------------------------------------------------------------

	def taof_settings_ok_clicked(self, *args):

		fuzzutils.context["timeout"] = float(self.widgets['menu_timeout'].get_text())
		fuzzutils.context["wait"] = float(self.widgets['menu_wait'].get_text())
		fuzzutils.context["wait_reconnection"] = float(self.widgets['menu_wait_reconnection'].get_text())
		fuzzutils.context["dictionary"] = self.widgets['menu_dictionary'].get_text()

		taof_settings = fuzzutils.xmlsettings()
		taof_settings.create_document(str(fuzzutils.context["timeout"]), str(fuzzutils.context["wait"]), str(fuzzutils.context["wait_reconnection"]), fuzzutils.context["dictionary"])

		self.widgets['taofsettings_dialog'].hide()

		fuzzutils.timeoutsocket.setDefaultSocketTimeout(fuzzutils.context["timeout"])
#----------------------------------------------------------------------

	def taof_settings_cancel_clicked(self, *args):
		self.set_settings()
		self.widgets['taofsettings_dialog'].hide()


#----------------------------------------------------------------------
# Build list of processes
	def taof_attachbutton_clicked(self, *args):
		
		fuzzutils.context["dbg"] = debug.pydbg()
		
		model = gtk.ListStore(gobject.TYPE_UINT,gobject.TYPE_STRING)
					
		for (pid, name) in fuzzutils.context["dbg"].enumerate_processes():
			#print str(pid) + " - " + name
			iter = model.append()
			model.set(iter, 0, pid,	1, name)	

		mytree = self.widgets['processestree']
		mytree.set_model(model)
		if len(mytree.get_columns())==0:
			# columns
			column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=COLUMN_FROM)
			column.set_sort_column_id(0)
			mytree.append_column(column)
			
			column = gtk.TreeViewColumn('Process', gtk.CellRendererText(), text=COLUMN_TO)
			column.set_sort_column_id(1)
			mytree.append_column(column)
		
		self.widgets['attachprocess'].show()


#----------------------------------------------------------------------
# Attach process
	def handler_debug_event(self, *args):
		while gtk.events_pending():	# Run pending events
			gtk.main_iteration_do(False)		

#----------------------------------------------------------------------
# Attach process
	def taof_okprocess_clicked(self, *args):
		
		myselection = self.widgets['processestree'].get_selection()
		model, iter = myselection.get_selected()
		if not iter:
			print "No selected item"
		else:		
			pid = model.get_value(iter, 0)
			name = model.get_value(iter, 1)
		
		self.widgets['attachprocess'].hide()
		
		#fuzzutils.context["dbg"].set_callback(debug.EXCEPTION_BREAKPOINT, debug.handler_breakpoint)
		fuzzutils.context["dbg"].set_callback(debug.EXCEPTION_ACCESS_VIOLATION, debug.handler_accessviolation)
		fuzzutils.context["dbg"].set_callback(debug.CREATE_THREAD_DEBUG_EVENT, debug.handler_new_thread)
		fuzzutils.context["dbg"].set_callback(debug.USER_CALLBACK_DEBUG_EVENT,self.handler_debug_event)
		
		
		fuzzutils.context["dbg"].attach(pid)
		fuzzutils.context["fuzzinglog"].insert(fuzzutils.context["fuzzinglog"].get_end_iter(),' [DBG] Process ' + name + ' attached. \n')
		fuzzutils.context["dbg"].run()
		
		return 1

def main(argv):
		w = taof()
		w.widgets['Main'].show()
		gtk.main()

#----------------------------------------------------------------------

if __name__ == '__main__':
		main(sys.argv)
