ruckus 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|