[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r11302: added more documentation, bugfixes, process detection (in topf/trunk: doc examples lib/fuzz lib/fuzz-struct)



Author: benedikt
Date: 2007-08-29 15:19:35 -0400 (Wed, 29 Aug 2007)
New Revision: 11302

Added:
   topf/trunk/examples/tutorial-example.rb
Modified:
   topf/trunk/doc/tutorial.tex
   topf/trunk/lib/fuzz-struct/fuzz-struct.rb
   topf/trunk/lib/fuzz/connection.rb
   topf/trunk/lib/fuzz/observer.rb
Log:
added more documentation, bugfixes, process detection

Modified: topf/trunk/doc/tutorial.tex
===================================================================
--- topf/trunk/doc/tutorial.tex	2007-08-29 19:02:43 UTC (rev 11301)
+++ topf/trunk/doc/tutorial.tex	2007-08-29 19:19:35 UTC (rev 11302)
@@ -14,85 +14,103 @@
 \section{Introduction}
 \label{working}
 T.O.P.F is a fuzzing Framework written in Ruby and developed to test the
-Tor protocol-suite.  It uses a block-based approch like the famous SPIKE
-fuzzer written by Dave-Aitel.  Block-based means that data is divided into
-so-called blocks that are then processed in a predefined fashion. Compared
+Tor protocol-suite. It uses a block-based approch like the famous SPIKE
+fuzzer written by Dave-Aitel. Block-based means that data is divided into
+so-called blocks who are then processed in a predefined fashion. Compared
 to the random byte-flipping that many other fuzzers do, this allows a more
 focused approach on specific vulnerbilities like buffer, format-string
-or integer overflows.  If fuzzing and/or ruby sound strange to you,
-you should read into the links listed in Appendix \ref{links}.
+or integer overflows. If fuzzing and/or ruby sound strange to you,
+you should read the links listed in Appendix \ref{links}.
 
 \section{Working with T.O.P.F}
 To use T.O.P.F a few basic steps described in this section are necessary.
 \subsection{Setting up a working Environment}
+\label{config}
 T.O.P.F needs Ruby and the Ruby-SSL library which is on some systems supplied 
-as standart-library and not on others. On Debian you need to run
-"apt-get install ruby libruby-openssl" beside the normal Ruby library.
+as standart-library and not on others. 
+On Debian you need to run "apt-get install ruby libruby-openssl" to get it running.
+On Fedora "yum install ruby" should to the trick :)
 
+
 \subsubsection{Checking out the current T.O.P.F trunk}
-Checking out T.O.P.F is as simple as starting a
+Next you need the T.O.P.F source which you are able to get from the
+Tor Subversion on https://tor-svn.freehaven.net/svn/. The Sources are 
+on https://tor-svn.freehaven.net/svn/topf/trunk so
 \begin{verbatim}
 svn co https://tor-svn.freehaven.net/svn/topf/trunk topf
 \end{verbatim}
-on your command-shell of choice.
+should copy them to the directory topf.
 
 \subsection{Running the fuzz tests}
+To run the tests you first need to setup a config-file which must
+be in the YAML file-format (see: \ref{yaml}).
+The config-file contains information for the Framework on which
+Port each Service is running, if the Framework should output debug-message,
+where corefiles are being created and where it can find the tor-binary.
+
 \subsubsection{Adjusting the config File}
-To let the Framework work properly the right setup of the
-config-file is nessesary. Just alter the given options
-to your environment.
+To give you a better insight on how the config-file must look, next
+you see an example config.
 
 \begin{verbatim}
-DIRPORT: "2324"
-CONTROLPORT: "2323"
-HOST: "127.0.0.1"
-KEYFILE: "stuff/fuzz-private.pem"
-DEBUG: false
-COREDIR: "/home/your_user/topf/core"
-BINDIR: "/home/your_user/topf/binary"
-CONFDIR: "/home/your_user/topf/config"
+DIRPORT: "2324"                         # where is the dirport ?
+CONTROLPORT: "2323"                     # where is the control-port ?
+HOST: "127.0.0.1"                       # on which ip is tor running
+KEYFILE: "stuff/fuzz-private.pem"       # this is to sign dir-descriptors
+                                        # (password is fuzz)
+DEBUG: false                            # should the framework output
+                                        #  debug-messages?
+COREDIR: "/home/your_user/topf/core"    # where are corefiles created ? see next
+                                        # sections on howto setup a path for 
+                                        # corefiles
+BINDIR: "/home/your_user/topf/binary"   # path to the tor binary
+CONFDIR: "/home/your_user/topf/config"  # patch to the directory containing the
+                                        # tor-config-file
 \end{verbatim}
 
 \subsubsection{Setting the u-limit}
-To let your system create core-dumps you normaly have
-to adjust your ulimit. You can do this on the
-shell with the command: "ulimit -c unlimited"
+Now we need to tell the system that it should create core-files
+when tor gets killed by the framework. This can be done through the
+command: "ulimit -c unlimited"
+
 \subsubsection{Setting a core-pattern}
-T.O.P.F checks if a process has been crashed by diffing the
-coredump-directory that was setup in the config-file.
-To let your system create core-files in this directory you
-have to supply a core-pattern. If you work with Linux you
-can set the core-pattern with echoing a path+filepattern
-into the file in proc named core\_pattern.
-When using Fedora this can be done with the following command
- executed as root:
- \begin{verbatim}
+To tell the System where to create core-files, on Linux, one can
+alter the proc-file "/proc/sys/kernel/core\_pattern" to point
+to the core-directory in the T.O.P.F root-directory.
+You can do this manually when running the following command as root:
+\begin{verbatim}
  echo "/home/youruser/path_to_topf/core/core" > /proc/sys/kernel/core_pattern
  \end{verbatim}
+or you can run the bash-script "set\_core\_pattern" in the utils directory as root.
 
+\subsection{Running the Tests}
+Now after completing all of the steps from \ref{config} we are finally able to
+run the standart-tests supplied with T.O.P.F.
 \subsubsection{Running the Dir-Port tests}
-To run the tests against the Dir-Port make sure you have setup
-the right host and dir-port in the configuration file.
-If everything is setup right you can just execute the dir-fuzzing
-with the command "ruby tor-dir-fuzz.rb".
-If something goes wrong a corefile should be dumped and the
-test-script should give you a backtrace and register information
-out of that corefile. Also it should print out the data that triggered
-the bug.
+To run the Dir-Port tests simply execute "ruby tor-dir-fuzz.rb"
+which looks first if tor is allready running on the system and if not 
+tries to execute it using the information in the config-file on where
+the binary and the config-file are.
+If the test succeeds and tor crashes a corefile should be dumped and the
+Script should print a backtrace and register informations on the standart output.
+Also it should print out the data that triggered the crash.
+
 \subsubsection{Running the Control-Port tests}
 Running tests against the Control-Port should be the same as running
 the tests against the Dir-Port. If you're sure you did all config options
-right you can execute "ruby tor-control-fuzz.rb" and the rest is done
+right you execute "ruby tor-control-fuzz.rb" and the rest is done
 automatically.
+
 \subsection{Writing tests for TOR}
-To give you a more tor-specific example of how such a test might look i give you
-an example out of control.rb that helds the structures to fuzz the Tor
-control-port. From the control-spec we take the "SIGNAL" keyword and check out
-the syntax of the command: \begin{varbatim}"SIGNAL" SP Signal CRLF\end{verbatim}
-If we now want to check if the parsing of the given signal has a bug we also
-want to set the initial "SIGNAL" keyword and the appended crlf field to non-fuzzable.
-Implementing this as a FuzzStruct could look like this:\\
+Next it is shown how you can alter the Framework to write your own test-cases
+our implement future tor-protocols.
+To do this a bit tor-related we will write a test against the Control-Port
+ keyword "SIGNAL" (see \ref{control-spec} ).\\
+We start including topf and build a fuzz-struct containing the blocks that are describing the
+right Syntax to config SIGNAL.
 \begin{verbatim}
+require "lib/topf"
+
 class SignalItem < FuzzStruct
     text :item, 6, :fuzzable => false
     text :signal, 13
@@ -103,52 +121,84 @@
 end
 \end{verbatim}
 The signal-field is chosen to be 13 bytes long as the longest signal-string
-("CLEARDNSCACHE") is 13 bytes long.\\
-Now we want to test the signal "RELOAD" so we create a SignalItem object and set
-signal to "RELOAD".
+("CLEARDNSCACHE") is 13 bytes long. Also the field item and crlf is set
+non-fuzzable so the fuzzing-algorithm doesnt alter these.\\
+Next we create a SignalItem object and set signal to "RELOAD" as a start.
 \begin{verbatim}
 si = SignalItem.new
 si.signal = "RELOAD"
 \end{verbatim}
-Next we want to apply two tests for the signal-field, a very long string and
-a format-string.
+Now we write two tests for the signal-field.
+One just returns the given argument, one returns an empty string, one
+creates a large string and one tries to test for a format-string bug
+using the format-string "\%n" which says the function using this string
+to write something on the stack.
 \begin{verbatim}
 t = Fuzz::Tests.new
 t.register Fuzz::Test.new("char") {|arg, size| arg }
-t.register Fuzz::Test.new("char") {|arg, size| "A"*1000 }  # long-string
-t.register Fuzz::Test.new("char") {|arg, size| "%n"*1000 } # format-string
-
+t.register Fuzz::Test.new("char") {|arg, size| "" }         # empty-string 
+t.register Fuzz::Test.new("char") {|arg, size| "A"*1000 }   # long-string
+t.register Fuzz::Test.new("char") {|arg, size| "%n"*1000 }  # format-string
 si.prepare! t
 \end{verbatim}
-Now we need a connection to the control-port through which we can send our data.
+As you can see we also applied the tests to our SignalItem using the "prepare!"
+method.\\
+Of course we also need a socket connecting to the control-port so we load our
+configuration-file and setup a options hash that we use to create a new Connection object.
 \begin{verbatim}
+config = YAML::load_file "config/config.yml"
+
+observer = Fuzz::BinaryObserver.new "#{config["BINDIR"]}/tor", config["COREDIR"], "-f #{config["CONFDIR"]}/torrc", "&> /dev/null"
+observer.observe!
+
 options = {
-    :host => "127.0.0.1",    # ip where our tor process is running
-    :port => "2323",         # number of the control-port
-    :debug => true,          # much output but shows the permutations
+    :host => config["HOST"],    # ip where our tor process is running
+    :port => config["CONTROLPORT"],         # number of the control-port
+    :debug => true,          # more output but to show you how it works 
+                             # its okay :)
     :type => :tcp,           # tcp-connection
     :timeout => 0.5          # timeout between each sending
 }
 c = Fuzz::Connection.new(options)
-c.fuzz!( si, " " )
 \end{verbatim}
-This is allready enough to fuzz the Signal Item but it doesnt give us any
-information when the tor-process has been crashed by the fuzzer. Cause
-this is very important when running a larg amount of tests automatically
-one can use the Observer and Coremanager classes.\\
-To start a binary as a child of the observer class 
-\subsection{Do the Fuzz!}
+Also included in the options hash is an observer item. This Object starts a new 
+tor process if none is allready running. It also can check if new corefiles 
+have appeared in the core-directory and prints information out of these files if 
+it found a new core-file.
 
+Now everything is complete and we can start the test using the method "fuzz!" 
+from the Connection class. This Method takes the Item thats going to be fuzzed 
+and a join-character to join the data properly.
+\begin{verbatim}
+c.fuzz!(si, " ")
+\end{verbatim}
+Everything together can be found in the file tutorial-example.rb included in the
+example directory of the T.O.P.F Source-directory.\\
+Running all this should result in an output similar to this:\\
+\begin{verbatim}
+D, [2007-08-29T17:53:29.481354 #32593] DEBUG -- : [x] calculated 4 permutations of struct SignalItem /tor/
+I, [2007-08-29T17:53:29.492493 #32593]  INFO -- : [x] /home/Benedikt/topf/binary/tor allready running
+I, [2007-08-29T17:53:29.492963 #32593]  INFO -- : [x] fuzzing struct 1 of 1 with 4 permutations
+D, [2007-08-29T17:53:29.493126 #32593] DEBUG -- : sending data: SIGNAL  
+D, [2007-08-29T17:53:29.493388 #32593] DEBUG -- : sending data: SIGNAL AAAAAAA...A
+D, [2007-08-29T17:53:29.493561 #32593] DEBUG -- : sending data: SIGNAL %n%n%n%...%n
+D, [2007-08-29T17:53:29.493561 #32593] DEBUG -- : sending data: SIGNAL %n%n%n%...%n
+D, [2007-08-29T18:03:20.273310 #32649] DEBUG -- : sending data: SIGNAL RELOAD 
+I, [2007-08-29T17:53:29.494169 #32593]  INFO -- : [?] no new corefile found
+\end{verbatim}
 \section{T.O.P.F Reference}
 \subsection{Fuzz}
 \subsubsection{Test-Cases}
+Is implemented and documented under "lib/fuzz/test.rb"
 \subsubsection{Tests}
+Is implemented and documented under "lib/fuzz/tests.rb"
 \subsubsection{Connection}
+Is implemented and documented under "lib/fuzz/connection.rb"
 \subsubsection{Observer}
+Is implemented and documented under "lib/fuzz/observer.rb"
 \subsection{Dir}
 \subsection{Control}
 \subsection{Cell}
-\subsection{Logger}
 \subsection{Backtrace}
 \subsection{Proxy}
 \subsubsection{Http-Proxy}
@@ -175,12 +225,14 @@
 \section{Appendix}
 \section{Links}
 \label{links}
+\label{control-spec}
 \begin{verbatim}
 http://en.wikipedia.org/wiki/Fuzzing
 http://events.ccc.de/congress/2005/fahrplan/attachments/582-paper_fuzzing.pdf
 http://immunitysec.com/downloads/usingspike3.ppt
 http://en.wikipedia.org/wiki/Ruby_%28programming_language%29
 http://www.ruby-lang.org
+http://tor.eff.org/doc/control-spec.txt
 \end{verbatim}
 
 \end{document}

Added: topf/trunk/examples/tutorial-example.rb
===================================================================
--- topf/trunk/examples/tutorial-example.rb	                        (rev 0)
+++ topf/trunk/examples/tutorial-example.rb	2007-08-29 19:19:35 UTC (rev 11302)
@@ -0,0 +1,39 @@
+require "../lib/topf"
+
+class SignalItem < FuzzStruct
+    text :item, 6, :fuzzable => false
+    text :signal, 13
+    char :crlf, 2*8, :fuzzable => false
+
+    initial_value.item = "SIGNAL" 
+    initial_value.crlf = "\r\n"
+end
+
+begin
+    si = SignalItem.new
+    si.signal = "RELOAD"
+    
+    t = Fuzz::Tests.new
+    t.register Fuzz::Test.new("char") {|arg, size| arg }
+    t.register Fuzz::Test.new("char") {|arg, size| "" }         # empty-string 
+    t.register Fuzz::Test.new("char") {|arg, size| "A"*1000 }   # long-string
+    t.register Fuzz::Test.new("char") {|arg, size| "%n"*1000 }  # format-string
+    si.prepare! t
+    
+    config = YAML::load_file "../config/config.yml"
+
+    observer = Fuzz::BinaryObserver.new "#{config["BINDIR"]}/tor", config["COREDIR"], "-f #{config["CONFDIR"]}/torrc", "&> /dev/null"
+    observer.observe!
+
+    options = {
+        :host => config["HOST"],    # ip where our tor process is running
+        :port => config["CONTROLPORT"],         # number of the control-port
+        :debug => true,          # more output but to show you how it works 
+        # its okay :)
+        :type => :tcp,           # tcp-connection
+        :timeout => 0.5,          # timeout between each sending
+        :observer => observer
+    }
+    c = Fuzz::Connection.new(options)
+    c.fuzz!( si, " " )
+end

Modified: topf/trunk/lib/fuzz/connection.rb
===================================================================
--- topf/trunk/lib/fuzz/connection.rb	2007-08-29 19:02:43 UTC (rev 11301)
+++ topf/trunk/lib/fuzz/connection.rb	2007-08-29 19:19:35 UTC (rev 11302)
@@ -41,7 +41,7 @@
         def fuzz!(structs, join_character="", args={})
             structs = [structs] if !structs.is_a? Array
             structs.each_with_index do |struct, index|
-                Fuzz::LOGGER.info "[x] fuzzing struct %d of %d with %d permutations" % [index+1, structs.size, 0]
+                Fuzz::LOGGER.info "[x] fuzzing struct %d of %d with %d permutations" % [index+1, structs.size, struct.permutations]
 
                 Fuzz.fuzz(@observer, struct){|struct|
                     data = struct.join( join_character )

Modified: topf/trunk/lib/fuzz/observer.rb
===================================================================
--- topf/trunk/lib/fuzz/observer.rb	2007-08-29 19:02:43 UTC (rev 11301)
+++ topf/trunk/lib/fuzz/observer.rb	2007-08-29 19:19:35 UTC (rev 11302)
@@ -35,8 +35,11 @@
 
         def is_running?
             reg = Regexp.new( @programname.split("/").last )
-            result = IO.popen("ps faux").readlines.find_all{|x| x=~ reg }
+            pp reg
+            result = IO.popen("ps -eo \"%p %c\"").readlines.find_all{|x| x =~ reg }
             if result.size > 0
+                @pid = result.to_s.slice(/\d+/)
+                @running = true
                 true
             else
                 false

Modified: topf/trunk/lib/fuzz-struct/fuzz-struct.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/fuzz-struct.rb	2007-08-29 19:02:43 UTC (rev 11301)
+++ topf/trunk/lib/fuzz-struct/fuzz-struct.rb	2007-08-29 19:19:35 UTC (rev 11302)
@@ -556,7 +556,7 @@
   end
 
   def permutations
-      @permutations.first.size
+      @permutations.collect{|x| x.size}.max
   end
 
   def fuzz!(opts = DEFAULT_INSPECT_OPTS)