ruckus 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +22 -0
- data/README +0 -0
- data/README.markdown +51 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/ruckus.rb +70 -0
- data/lib/ruckus/blob.rb +113 -0
- data/lib/ruckus/choice.rb +55 -0
- data/lib/ruckus/dfuzz.rb +231 -0
- data/lib/ruckus/dictionary.rb +119 -0
- data/lib/ruckus/enum.rb +39 -0
- data/lib/ruckus/extensions/array.rb +33 -0
- data/lib/ruckus/extensions/class.rb +168 -0
- data/lib/ruckus/extensions/duplicable.rb +37 -0
- data/lib/ruckus/extensions/file.rb +24 -0
- data/lib/ruckus/extensions/fixnum.rb +26 -0
- data/lib/ruckus/extensions/hash.rb +10 -0
- data/lib/ruckus/extensions/integer.rb +26 -0
- data/lib/ruckus/extensions/ipaddr.rb +155 -0
- data/lib/ruckus/extensions/irb.rb +30 -0
- data/lib/ruckus/extensions/math.rb +6 -0
- data/lib/ruckus/extensions/module.rb +37 -0
- data/lib/ruckus/extensions/numeric.rb +117 -0
- data/lib/ruckus/extensions/object.rb +22 -0
- data/lib/ruckus/extensions/range.rb +16 -0
- data/lib/ruckus/extensions/socket.rb +20 -0
- data/lib/ruckus/extensions/string.rb +327 -0
- data/lib/ruckus/filter.rb +16 -0
- data/lib/ruckus/human_display.rb +79 -0
- data/lib/ruckus/ip.rb +38 -0
- data/lib/ruckus/mac_addr.rb +31 -0
- data/lib/ruckus/mutator.rb +318 -0
- data/lib/ruckus/null.rb +24 -0
- data/lib/ruckus/number.rb +360 -0
- data/lib/ruckus/parsel.rb +363 -0
- data/lib/ruckus/selector.rb +92 -0
- data/lib/ruckus/str.rb +164 -0
- data/lib/ruckus/structure.rb +263 -0
- data/lib/ruckus/structure/atcreate.rb +23 -0
- data/lib/ruckus/structure/beforebacks.rb +28 -0
- data/lib/ruckus/structure/defaults.rb +57 -0
- data/lib/ruckus/structure/factory.rb +42 -0
- data/lib/ruckus/structure/fixupfields.rb +16 -0
- data/lib/ruckus/structure/initializers.rb +14 -0
- data/lib/ruckus/structure/relate.rb +34 -0
- data/lib/ruckus/structure/replacement.rb +30 -0
- data/lib/ruckus/structure/searchmods.rb +33 -0
- data/lib/ruckus/structure/structureproxies.rb +28 -0
- data/lib/ruckus/structure/validate.rb +12 -0
- data/lib/ruckus/structure_shortcuts.rb +109 -0
- data/lib/ruckus/time_t.rb +26 -0
- data/lib/ruckus/vector.rb +97 -0
- data/ruckus.gemspec +104 -0
- data/test/test_decides.rb +61 -0
- data/test/test_mutator.rb +29 -0
- data/test/test_override.rb +23 -0
- data/test/test_replace.rb +39 -0
- metadata +138 -0
data/.document
ADDED
data/.gitignore
ADDED
data/README
ADDED
File without changes
|
data/README.markdown
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
*Under construction: we're in the process of extracting this from our toolshed
|
2
|
+
repository; please pardon the flaws.*
|
3
|
+
|
4
|
+
# Ruckus: A DOM-Inspired Ruby Smart Fuzzer
|
5
|
+
|
6
|
+
Ruckus is a:
|
7
|
+
|
8
|
+
### Fuzzer
|
9
|
+
|
10
|
+
A tool used in security testing to generate pathological inputs for
|
11
|
+
target code. Two common use cases:
|
12
|
+
|
13
|
+
* Generating malicious protocol messages to attack network
|
14
|
+
software
|
15
|
+
|
16
|
+
* Creating malicious files in specific file formats to feed
|
17
|
+
to target programs
|
18
|
+
|
19
|
+
### Smart Fuzzer
|
20
|
+
|
21
|
+
I'm stealing [Mike Eddington's](http://peachfuzzer.com/) term;
|
22
|
+
Smart Fuzzers distinguish themselves from "just plain fuzzers"
|
23
|
+
by being aware of the data format they're being used to test. In
|
24
|
+
both Eddington's Peach Fuzzer and Ruckus, you accomplish that by
|
25
|
+
defining data models (structures) to describe protocols and file
|
26
|
+
formats.
|
27
|
+
|
28
|
+
### Ruby
|
29
|
+
|
30
|
+
Peach Fuzzer is written in Python. So is Sully, Pedram Amini's
|
31
|
+
fuzzer. SPIKE is written in C. Ruckus is Ruby's answer, and it
|
32
|
+
tries to play to Ruby's strengths:
|
33
|
+
|
34
|
+
* It's much more DSL-y than Peach Fuzzer or Sully
|
35
|
+
|
36
|
+
* Unlike XML-bound Peach Fuzzer, it's "configuration files"
|
37
|
+
are code
|
38
|
+
|
39
|
+
* You don't really need to know Ruby to write those files
|
40
|
+
|
41
|
+
Long term I'm hoping Ruckus bears the same relationship to Ruby as
|
42
|
+
Expect did to Tcl.
|
43
|
+
|
44
|
+
### DOM-Inspired
|
45
|
+
|
46
|
+
Ruckus separates metadata and actual content, and structures packets
|
47
|
+
and file formats as trees of nodes, each with classes and (when desired)
|
48
|
+
DOM-style id's (we call them "tags"). Ruckus data can be manipulated
|
49
|
+
with tree traversal and "mutated" with cascading style sheet selector-type
|
50
|
+
logic.
|
51
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ruckus"
|
8
|
+
gem.summary = %Q{A DOM-Inspired Ruby Smart Fuzzer}
|
9
|
+
gem.description = %Q{Ruckus: A DOM-Inspired Ruby Smart Fuzzer}
|
10
|
+
gem.email = "td@matasano.com"
|
11
|
+
gem.homepage = "http://github.com/tduehr/ruckus"
|
12
|
+
gem.authors = ["tduehr", "tqbf"]
|
13
|
+
gem.add_development_dependency "jeweler", ">= 0"
|
14
|
+
gem.rdoc_options = ["--inline-source", "--line-numbers", "--main", "README.markdown"]
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/test_*.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "ruckus #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.4
|
data/lib/ruckus.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# == Introduction
|
4
|
+
# This is yet another binary formatter for Ruby; compare to bindata,
|
5
|
+
# bitstruct, or pack/unpack.
|
6
|
+
#
|
7
|
+
# Read in this order:
|
8
|
+
# * Parsel
|
9
|
+
# * Number
|
10
|
+
# * Str
|
11
|
+
# * Blob
|
12
|
+
# * Structure
|
13
|
+
|
14
|
+
module Ruckus
|
15
|
+
|
16
|
+
# :stopdoc:
|
17
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
18
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
19
|
+
# :startdoc:
|
20
|
+
# Returns the version string for the library.
|
21
|
+
#
|
22
|
+
def self.version
|
23
|
+
VERSION
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the library path for the module. If any arguments are given,
|
27
|
+
# they will be joined to the end of the libray path using
|
28
|
+
# <tt>File.join</tt>.
|
29
|
+
#
|
30
|
+
def self.libpath( *args )
|
31
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the lpath for the module. If any arguments are given,
|
35
|
+
# they will be joined to the end of the path using
|
36
|
+
# <tt>File.join</tt>.
|
37
|
+
#
|
38
|
+
def self.path( *args )
|
39
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Utility method used to require all files ending in .rb that lie in the
|
43
|
+
# directory below this file that has the same name as the filename passed
|
44
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
45
|
+
# the _filename_ does not have to be equivalent to the directory.
|
46
|
+
#
|
47
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
48
|
+
dir ||= ::File.basename(fname, '.*')
|
49
|
+
search_me = ::File.expand_path(
|
50
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
51
|
+
extensions = ::File.expand_path(::File.join(::File.dirname(fname),dir,'extensions','**','*.rb'))
|
52
|
+
spath = ::File.expand_path(::File.join(::File.dirname(fname), dir))
|
53
|
+
Dir.glob(extensions).each{|rb| require rb}
|
54
|
+
require ::File.join(spath, 'parsel.rb')
|
55
|
+
require ::File.join(spath, 'number.rb')
|
56
|
+
require ::File.join(spath, 'str.rb')
|
57
|
+
require ::File.join(spath, 'structure.rb')
|
58
|
+
Dir.glob(search_me).reject{|rb| rb =~ /human_display\.rb/}.each {|rb| require rb}
|
59
|
+
require ::File.join(spath, 'human_display.rb')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Ruckus.require_all_libs_relative_to(__FILE__)
|
64
|
+
|
65
|
+
# require 'extensions/extensions'
|
66
|
+
#
|
67
|
+
# %w[ parsel number ip str choice null blob filter structure dictionary
|
68
|
+
# mutator vector mac_addr enum time_t selector dfuzz ].each do |f|
|
69
|
+
# require 'ruckus/' + f
|
70
|
+
# end
|
data/lib/ruckus/blob.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# === Blobs are collections of Parsels.
|
2
|
+
|
3
|
+
module Ruckus
|
4
|
+
# A Blob wraps an array. Everything within the array is rendered
|
5
|
+
# sequentially, returning a single string. Blob rendering is effectively
|
6
|
+
# preorder tree traversal (Blobs can contain any Parsel, including other
|
7
|
+
# Blobs)
|
8
|
+
class Blob < Parsel
|
9
|
+
# No special options needed.
|
10
|
+
#
|
11
|
+
def initialize(opts={})
|
12
|
+
@value = Array.new
|
13
|
+
(opts[:populate]||[]).each do |k|
|
14
|
+
self << k.new
|
15
|
+
end
|
16
|
+
super(opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
# This is the only
|
20
|
+
# way you should add elements to a Blob for now.
|
21
|
+
#
|
22
|
+
def <<(v)
|
23
|
+
@value << v
|
24
|
+
v.parent = self
|
25
|
+
end
|
26
|
+
|
27
|
+
# How many elements are in the blob? (<tt>size</tt> returns
|
28
|
+
# the rendered size)
|
29
|
+
#
|
30
|
+
def count; @value.size; end
|
31
|
+
|
32
|
+
# Assign a value to an element of a blob, so if you assign
|
33
|
+
# blob[1] = 1, it works as expected.
|
34
|
+
#
|
35
|
+
def []=(k, v)
|
36
|
+
return @value[k].value = v if not v.kind_of? Parsel
|
37
|
+
@value[k] = v
|
38
|
+
end
|
39
|
+
|
40
|
+
# Where is <tt>o</tt> in this blob? (Pretty sure you could
|
41
|
+
# just use <tt>index</tt> for this, but whatever)
|
42
|
+
#
|
43
|
+
def place(o)
|
44
|
+
@value.each_with_index do |it, i|
|
45
|
+
if o == it
|
46
|
+
return i
|
47
|
+
end
|
48
|
+
end
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# As with Parsel; this will recurse through any embedded
|
53
|
+
# blobs.
|
54
|
+
#
|
55
|
+
def capture(str)
|
56
|
+
@value.each_with_index do |it, i|
|
57
|
+
begin
|
58
|
+
str ||= "" # XXX bug
|
59
|
+
|
60
|
+
# you don't always know the type of object
|
61
|
+
# you want to instantiate at compile time;
|
62
|
+
# it can depend on the contents of a packet.
|
63
|
+
# when it does, there's a flag set that enables
|
64
|
+
# a "factory" method which does the parse.
|
65
|
+
#
|
66
|
+
# the downside of this is once a blob has
|
67
|
+
# been parsed with a factory, its definition
|
68
|
+
# changes; that same blob can't be reused
|
69
|
+
# to parse another packet. So, just don't
|
70
|
+
# do that.
|
71
|
+
|
72
|
+
if it.class.factory?
|
73
|
+
@value[i], str = it.class.factory(str)
|
74
|
+
else
|
75
|
+
str = it.capture(str)
|
76
|
+
end
|
77
|
+
rescue IncompleteCapture
|
78
|
+
err = "at item #{ i }"
|
79
|
+
err << " named \"#{ it.name }\"" if it.name
|
80
|
+
err << " in struct \"#{ it.parent_struct.name }\"" if it.parent_struct
|
81
|
+
|
82
|
+
raise IncompleteCapture.new(err) if not str or str.empty?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
str
|
86
|
+
end
|
87
|
+
|
88
|
+
# How big in bytes is this blob and everything it contains?
|
89
|
+
# An empty blob has size 0
|
90
|
+
#
|
91
|
+
def size
|
92
|
+
@value.inject(0) {|acc, it| acc + it.size}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Render the blob, or return "" if it's empty.
|
96
|
+
#
|
97
|
+
def to_s(off=nil)
|
98
|
+
@rendered_offset = off || 0
|
99
|
+
voff = @rendered_offset
|
100
|
+
r = ""
|
101
|
+
@value.each do |it|
|
102
|
+
s, voff = it.to_s(voff)
|
103
|
+
r << s
|
104
|
+
end
|
105
|
+
|
106
|
+
if off
|
107
|
+
return r, voff
|
108
|
+
else
|
109
|
+
return r
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# === Choices pick binary structures at runtime
|
2
|
+
|
3
|
+
module Ruckus
|
4
|
+
|
5
|
+
# A choice wraps a blob, and, on input, picks what to put in the blob
|
6
|
+
# based on a code block. Use choices to dispatch protocol responses
|
7
|
+
# based on type codes, etc.
|
8
|
+
#
|
9
|
+
class Choice < Parsel
|
10
|
+
|
11
|
+
# You must call Choice.new with a block that takes two
|
12
|
+
# arguments --- an input string and a reference to the
|
13
|
+
# choice instance. For instance:
|
14
|
+
#
|
15
|
+
# data << Choice.new do |buf, this|
|
16
|
+
# if this.parent_struct.message_code == Codes::ERROR
|
17
|
+
# this << ErrorFrame.new
|
18
|
+
# else
|
19
|
+
# this << ResponseFrame.new
|
20
|
+
# end
|
21
|
+
# this[-1].capture(buf)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
def initialize(opts={}, &block)
|
25
|
+
@parent = opts[:parent]
|
26
|
+
raise "provide a block" if not block_given? and not opts[:block] and not respond_to? :choose
|
27
|
+
if not opts[:block] and not block_given?
|
28
|
+
opts[:block] = lambda {|x, y| self.choose(x)}
|
29
|
+
end
|
30
|
+
super(opts)
|
31
|
+
@block ||= block
|
32
|
+
@value = Blob.new
|
33
|
+
@value.parent = self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Just render the blob
|
37
|
+
#
|
38
|
+
def to_s(off=nil)
|
39
|
+
@rendered_offset = off || 0
|
40
|
+
(@value)? @value.to_s(off) : ""
|
41
|
+
end
|
42
|
+
|
43
|
+
# Call the block, which must return the remainder string.
|
44
|
+
#
|
45
|
+
def capture(str)
|
46
|
+
block.call(str, self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def <<(o)
|
50
|
+
@value << o
|
51
|
+
o.parent = self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/lib/ruckus/dfuzz.rb
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# = fuzz.rb
|
4
|
+
#
|
5
|
+
# Fuzz Generators
|
6
|
+
#
|
7
|
+
# Ruby 1.8 Generators use continuations (which are slow) and leak
|
8
|
+
# memory like crazy, so use generators.rb from Ruby 1.9.
|
9
|
+
#
|
10
|
+
# Author:: Dai Zovi, Dino <ddz@theta44.org>
|
11
|
+
# License:: Private
|
12
|
+
# Revision:: $Id$
|
13
|
+
#
|
14
|
+
|
15
|
+
require 'generator'
|
16
|
+
|
17
|
+
module DFuzz
|
18
|
+
# Generate Xi-F...Xi+F for each Xi in boundaries and fudge_factor F
|
19
|
+
class Fudge < Generator
|
20
|
+
def initialize(boundaries, fudge_factor, mask = nil)
|
21
|
+
super() { |g|
|
22
|
+
boundaries.each {|b|
|
23
|
+
0.upto(fudge_factor) { |f|
|
24
|
+
if (mask)
|
25
|
+
g.yield((b+f) & mask)
|
26
|
+
g.yield((b-f) & mask)
|
27
|
+
else
|
28
|
+
g.yield b+f
|
29
|
+
g.yield b-f
|
30
|
+
end
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Serially generate each variable in turn (equivalent to
|
38
|
+
# recursively nesting generators)
|
39
|
+
class Block
|
40
|
+
def initialize(defaults, generators)
|
41
|
+
@defaults = defaults
|
42
|
+
@generators = generators
|
43
|
+
end
|
44
|
+
|
45
|
+
def run(&block)
|
46
|
+
generators_index = 0
|
47
|
+
|
48
|
+
# Baseline
|
49
|
+
block.call(@defaults)
|
50
|
+
|
51
|
+
# Iterate through generators, fully exhausting each and
|
52
|
+
# calling the code block with each set of values
|
53
|
+
@generators.each { |g|
|
54
|
+
values = Array.new(@defaults)
|
55
|
+
while (g.next?)
|
56
|
+
values[generators_index] = g.next
|
57
|
+
block.call(values)
|
58
|
+
end
|
59
|
+
generators_index += 1;
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Integer < Fudge
|
65
|
+
def initialize(delta = 128)
|
66
|
+
super([0, 0x7FFF, 0xFFFF, 0x7FFFFFFF,
|
67
|
+
0x7FFFFFFFFFFFFFFF], delta)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Byte < Fudge
|
72
|
+
def initialize(delta = 16)
|
73
|
+
super([0x00, 0x01, 0x7F, 0xFF], delta, 0xFF)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Short < Fudge
|
78
|
+
def initialize(delta = 128)
|
79
|
+
super([0x0000, 0x0001, 0x7FFF, 0xFFFF], delta, 0xFFFF)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Long < Fudge
|
84
|
+
def initialize(delta = 256)
|
85
|
+
super([0x00000000, 0x0000001, 0x7FFFFFFF, 0xFFFFFFFF, 0x40000000, 0xC0000000], delta, 0xffffffff)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Char < Generator
|
90
|
+
def initialize()
|
91
|
+
c = ["A", "0", "~", "`", "!", "@", "#", "$", "%", "^", "&",
|
92
|
+
"*", "(", ")", "-", "=", "+", "[", "]", "\\", "|", ";",
|
93
|
+
":", "'", "\"", ",", "<", ".", ">", "/", "?",
|
94
|
+
" ", "~", "_", "{", "}", "\x7f","\x00","\x01",
|
95
|
+
"\x02","\x03","\x04","\x05", "\x06","\x07","\x08","\x09",
|
96
|
+
"\x0a","\x0b","\x0c","\x0d", "\x0e","\x0f","\x10","\x11",
|
97
|
+
"\x12","\x13","\x14","\x15", "\x16","\x17","\x18","\x19",
|
98
|
+
"\x1a","\x1b","\x1c","\x1d", "\x1e","\x1f",
|
99
|
+
"\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87",
|
100
|
+
"\x88","\x89","\x8a","\x8b","\x8c","\x8d","\x8e","\x8f",
|
101
|
+
"\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97",
|
102
|
+
"\x98","\x99","\x9a","\x9b","\x9c","\x9d","\x9e","\x9f",
|
103
|
+
"\xa0","\xa1","\xa2","\xa3","\xa4","\xa5","\xa6","\xa7",
|
104
|
+
"\xa8","\xa9","\xaa","\xab","\xac","\xad","\xae","\xaf",
|
105
|
+
"\xb0","\xb1","\xb2","\xb3","\xb4","\xb5","\xb6","\xb7",
|
106
|
+
"\xb8","\xb9","\xba","\xbb","\xbc","\xbd","\xbe","\xbf",
|
107
|
+
"\xc0","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6","\xc7",
|
108
|
+
"\xc8","\xc9","\xca","\xcb","\xcc","\xcd","\xce","\xcf",
|
109
|
+
"\xd0","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6","\xd7",
|
110
|
+
"\xd8","\xd9","\xda","\xdb","\xdc","\xdd","\xde","\xdf",
|
111
|
+
"\xe0","\xe1","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7",
|
112
|
+
"\xe8","\xe9","\xea","\xeb","\xec","\xed","\xee","\xef",
|
113
|
+
"\xf0","\xf1","\xf2","\xf3","\xf4","\xf5","\xf6","\xf7",
|
114
|
+
"\xf8","\xf9","\xfa","\xfb","\xfc","\xfd","\xfe","\xff", ]
|
115
|
+
super(c)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class String < Generator
|
120
|
+
def initialize(lengths=nil)
|
121
|
+
super() { |g|
|
122
|
+
# Fuzz strings are each of CHARS repeated each of
|
123
|
+
# LENGTHS times and each of strings
|
124
|
+
lengths ||= [16, 32, 64, 100, 128, 192, 256, 384, 512, 768, 1024, 2048, 3072, 4096, 6000, 8192, 10000, 16000, 20000, 32000, 50000, 64000, 72000, 100000]
|
125
|
+
strings = [
|
126
|
+
"%n%n%n%n%n%n%n%n%n%n", "%252n%252n%252n%252n%252n",
|
127
|
+
"%x%x%x%x", "%252x%252x%252x%252x",
|
128
|
+
"../../../../../../../../../../../../../etc/passwd",
|
129
|
+
"../../../../../../../../../../../../../etc/passwd%00",
|
130
|
+
"../../../../../../../../../../../../../boot.ini",
|
131
|
+
"../../../../../../../../../../../../../boot.ini%00",
|
132
|
+
"..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\boot.ini",
|
133
|
+
"..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\boot.ini%00",
|
134
|
+
"<script>alert('XSS');</script>",
|
135
|
+
"A0`~!@#\$\%^&*()-_=+[]{}\\|;:',.<>/?\""
|
136
|
+
]
|
137
|
+
chars = Char.new()
|
138
|
+
while chars.next?
|
139
|
+
c = chars.next
|
140
|
+
|
141
|
+
lengths.each { |l|
|
142
|
+
g.yield(c * l)
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
strings.each { |s|
|
147
|
+
g.yield(s)
|
148
|
+
}
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# Modules for higher-level tokens (e-mail addresses, asn1, etc)
|
155
|
+
#
|
156
|
+
class EmailAddress < Generator
|
157
|
+
def initialize()
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
####
|
164
|
+
# Unit test
|
165
|
+
####
|
166
|
+
|
167
|
+
if $0 == __FILE__
|
168
|
+
puts "Testing integers..."
|
169
|
+
i = 0
|
170
|
+
integers = Fuzz::Integer.new()
|
171
|
+
while integers.next?
|
172
|
+
integers.next
|
173
|
+
i += 1
|
174
|
+
end
|
175
|
+
puts "=> #{i} items"
|
176
|
+
|
177
|
+
puts "Testing bytes..."
|
178
|
+
i = 0
|
179
|
+
bytes = Fuzz::Byte.new()
|
180
|
+
while bytes.next?
|
181
|
+
bytes.next
|
182
|
+
i += 1
|
183
|
+
end
|
184
|
+
puts "=> #{i} items"
|
185
|
+
|
186
|
+
puts "Testing shorts"
|
187
|
+
i = 0
|
188
|
+
shorts = Fuzz::Short.new()
|
189
|
+
while shorts.next?
|
190
|
+
shorts.next
|
191
|
+
i += 1
|
192
|
+
end
|
193
|
+
puts "=> #{i} items"
|
194
|
+
|
195
|
+
puts "Testing longs"
|
196
|
+
i = 0
|
197
|
+
longs = Fuzz::Long.new()
|
198
|
+
while longs.next?
|
199
|
+
longs.next
|
200
|
+
i += 1
|
201
|
+
end
|
202
|
+
puts "=> #{i} items"
|
203
|
+
|
204
|
+
puts "Testing characters"
|
205
|
+
i = 0
|
206
|
+
characters = Fuzz::Char.new()
|
207
|
+
while characters.next?
|
208
|
+
characters.next
|
209
|
+
i += 1
|
210
|
+
end
|
211
|
+
puts "=> #{i} items"
|
212
|
+
|
213
|
+
puts "Testing strings"
|
214
|
+
i = 0
|
215
|
+
strings = Fuzz::String.new()
|
216
|
+
while strings.next?
|
217
|
+
strings.next
|
218
|
+
i += 1
|
219
|
+
end
|
220
|
+
puts "=> #{i} items"
|
221
|
+
|
222
|
+
puts "Testing Block"
|
223
|
+
b = Fuzz::Block.new(["FOO", "BAR"],
|
224
|
+
[Fuzz::String.new(), Fuzz::String.new()])
|
225
|
+
i = 0
|
226
|
+
b.run() { |a, b|
|
227
|
+
i += 1
|
228
|
+
}
|
229
|
+
puts "=> #{i} items"
|
230
|
+
|
231
|
+
end
|