ronin-support 0.5.0.rc1 → 0.5.0.rc2
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/ChangeLog.md +6 -1
- data/lib/ronin/fuzzing/extensions/string.rb +21 -208
- data/lib/ronin/fuzzing/fuzzer.rb +118 -0
- data/lib/ronin/fuzzing/fuzzing.rb +7 -2
- data/lib/ronin/fuzzing/mutator.rb +161 -0
- data/lib/ronin/fuzzing/repeater.rb +81 -0
- data/lib/ronin/fuzzing/template.rb +133 -0
- data/lib/ronin/network/mixins/http.rb +51 -580
- data/lib/ronin/support/version.rb +1 -1
- data/lib/ronin/wordlist.rb +9 -4
- data/spec/fuzzing/extensions/string_spec.rb +87 -0
- data/spec/fuzzing/fuzzer_spec.rb +109 -0
- data/spec/fuzzing/fuzzing_spec.rb +24 -0
- data/spec/fuzzing/mutator_spec.rb +112 -0
- data/spec/fuzzing/repeater_spec.rb +57 -0
- data/spec/fuzzing/template_spec.rb +54 -0
- data/spec/spec_helper.rb +3 -3
- metadata +12 -3
- data/spec/fuzzing/string_spec.rb +0 -158
data/lib/ronin/wordlist.rb
CHANGED
@@ -17,8 +17,9 @@
|
|
17
17
|
# along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
|
18
18
|
#
|
19
19
|
|
20
|
+
require 'ronin/fuzzing/template'
|
21
|
+
require 'ronin/fuzzing/mutator'
|
20
22
|
require 'ronin/extensions/regexp'
|
21
|
-
require 'ronin/fuzzing/extensions'
|
22
23
|
|
23
24
|
require 'set'
|
24
25
|
|
@@ -224,12 +225,16 @@ module Ronin
|
|
224
225
|
def each(&block)
|
225
226
|
return enum_for(:each) unless block
|
226
227
|
|
228
|
+
mutator = unless @mutations.empty?
|
229
|
+
Fuzzing::Mutator.new(@mutations)
|
230
|
+
end
|
231
|
+
|
227
232
|
each_word do |word|
|
228
233
|
yield word
|
229
234
|
|
230
|
-
|
235
|
+
if mutator
|
231
236
|
# perform additional mutations
|
232
|
-
|
237
|
+
mutator.each(word,&block)
|
233
238
|
end
|
234
239
|
end
|
235
240
|
end
|
@@ -252,7 +257,7 @@ module Ronin
|
|
252
257
|
# @api public
|
253
258
|
#
|
254
259
|
def each_n_words(n,&block)
|
255
|
-
|
260
|
+
Fuzzing::Template[[each, n]].each(&block)
|
256
261
|
end
|
257
262
|
|
258
263
|
#
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/extensions/string'
|
3
|
+
|
4
|
+
describe String do
|
5
|
+
it "should provide String.generate" do
|
6
|
+
described_class.should respond_to(:generate)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should provide String#repeating" do
|
10
|
+
subject.should respond_to(:repeating)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should provide String#fuzz" do
|
14
|
+
subject.should respond_to(:fuzz)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should provide String#mutate" do
|
18
|
+
subject.should respond_to(:mutate)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "generate" do
|
22
|
+
subject { described_class }
|
23
|
+
|
24
|
+
it "should generate Strings from a template" do
|
25
|
+
strings = subject.generate([:numeric, 2]).to_a
|
26
|
+
|
27
|
+
strings.grep(/^[0-9]{2}$/).should == strings
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#repeating" do
|
32
|
+
subject { 'A' }
|
33
|
+
|
34
|
+
context "when n is an Integer" do
|
35
|
+
let(:n) { 100 }
|
36
|
+
|
37
|
+
it "should multiply the String by n" do
|
38
|
+
subject.repeating(n).should == (subject * n)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when n is Enumerable" do
|
43
|
+
let(:n) { [128, 512, 1024] }
|
44
|
+
|
45
|
+
it "should repeat the String by each length" do
|
46
|
+
strings = subject.repeating(n).to_a
|
47
|
+
|
48
|
+
strings.should == n.map { |length| subject * length }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#fuzz" do
|
54
|
+
subject { "foo bar" }
|
55
|
+
|
56
|
+
it "should apply each fuzzing rule individually" do
|
57
|
+
strings = subject.fuzz(/o/ => ['O', '0'], /a/ => ['A', '@']).to_a
|
58
|
+
|
59
|
+
strings.should =~ [
|
60
|
+
"fOo bar",
|
61
|
+
"f0o bar",
|
62
|
+
"foO bar",
|
63
|
+
"fo0 bar",
|
64
|
+
"foo bAr",
|
65
|
+
"foo b@r"
|
66
|
+
]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#mutate" do
|
71
|
+
subject { "foo bar" }
|
72
|
+
|
73
|
+
it "should apply every combination of mutation rules" do
|
74
|
+
strings = subject.mutate(/o/ => ['0'], /a/ => ['@']).to_a
|
75
|
+
|
76
|
+
strings.should =~ [
|
77
|
+
"f0o bar",
|
78
|
+
"fo0 bar",
|
79
|
+
"f00 bar",
|
80
|
+
"foo b@r",
|
81
|
+
"f0o b@r",
|
82
|
+
"fo0 b@r",
|
83
|
+
"f00 b@r"
|
84
|
+
]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/fuzzer'
|
3
|
+
|
4
|
+
describe Fuzzing::Fuzzer do
|
5
|
+
let(:string) { 'GET /one/two/three' }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
subject { described_class }
|
9
|
+
|
10
|
+
context "patterns" do
|
11
|
+
let(:substitutions) { ['bar'] }
|
12
|
+
|
13
|
+
it "should accept Regexps" do
|
14
|
+
fuzzer = subject.new(/foo/ => substitutions)
|
15
|
+
|
16
|
+
fuzzer.rules.should have_key(/foo/)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when given Strings" do
|
20
|
+
subject { described_class.new('foo' => substitutions) }
|
21
|
+
|
22
|
+
it "should convert to Regexp" do
|
23
|
+
subject.rules.should have_key(/foo/)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when given Symbols" do
|
28
|
+
subject { described_class.new(:word => substitutions) }
|
29
|
+
|
30
|
+
it "should lookup the Regexp constant" do
|
31
|
+
subject.rules.should have_key(Regexp::WORD)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "otherwise" do
|
36
|
+
it "should raise a TypeError" do
|
37
|
+
lambda {
|
38
|
+
subject.new(Object.new => substitutions)
|
39
|
+
}.should raise_error(TypeError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "substitutions" do
|
45
|
+
let(:pattern) { /foo/ }
|
46
|
+
|
47
|
+
it "should accept Enumerable values" do
|
48
|
+
fuzzer = subject.new(pattern => ['bar'])
|
49
|
+
|
50
|
+
fuzzer.rules[pattern].should == ['bar']
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when given Symbols" do
|
54
|
+
subject { described_class.new(pattern => :bad_strings) }
|
55
|
+
|
56
|
+
it "should map to an Enumerator for a Fuzzing method" do
|
57
|
+
subject.rules[pattern].should be_kind_of(Enumerable)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "otherwise" do
|
62
|
+
it "should raise a TypeError" do
|
63
|
+
lambda {
|
64
|
+
subject.new(pattern => Object.new)
|
65
|
+
}.should raise_error(TypeError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#each" do
|
72
|
+
let(:string) { "foo bar" }
|
73
|
+
|
74
|
+
subject { described_class.new(/o/ => ['O', '0'], /a/ => ['A', '@']) }
|
75
|
+
|
76
|
+
it "should apply each fuzzing rule individually" do
|
77
|
+
subject.each(string).to_a.should =~ [
|
78
|
+
"fOo bar",
|
79
|
+
"f0o bar",
|
80
|
+
"foO bar",
|
81
|
+
"fo0 bar",
|
82
|
+
"foo bAr",
|
83
|
+
"foo b@r"
|
84
|
+
]
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when mutations contain Integers" do
|
88
|
+
subject { described_class.new(/o/ => [48]) }
|
89
|
+
|
90
|
+
it "should convert them to characters" do
|
91
|
+
subject.each(string).to_a.should =~ [
|
92
|
+
"f0o bar",
|
93
|
+
"fo0 bar"
|
94
|
+
]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when mutations contain Procs" do
|
99
|
+
subject { described_class.new(/o/ => [lambda { |str| str.upcase }]) }
|
100
|
+
|
101
|
+
it "should call them with the matched String" do
|
102
|
+
subject.each(string).to_a.should =~ [
|
103
|
+
"fOo bar",
|
104
|
+
"foO bar"
|
105
|
+
]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/fuzzing'
|
3
|
+
|
4
|
+
describe Fuzzing do
|
5
|
+
describe "[]" do
|
6
|
+
let(:method) { :bad_strings }
|
7
|
+
|
8
|
+
it "should return Enumerators for fuzzing methods" do
|
9
|
+
subject[method].should be_kind_of(Enumerable)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise NoMethodError for unknown methods" do
|
13
|
+
lambda {
|
14
|
+
subject[:foo]
|
15
|
+
}.should raise_error(NoMethodError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not allow accessing inherited methods" do
|
19
|
+
lambda {
|
20
|
+
subject[:instance_eval]
|
21
|
+
}.should raise_error(NoMethodError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/mutator'
|
3
|
+
|
4
|
+
describe Fuzzing::Mutator do
|
5
|
+
let(:string) { 'GET /one/two/three' }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
subject { described_class }
|
9
|
+
|
10
|
+
context "patterns" do
|
11
|
+
let(:substitutions) { ['bar'] }
|
12
|
+
|
13
|
+
it "should accept Regexps" do
|
14
|
+
fuzzer = subject.new(/foo/ => substitutions)
|
15
|
+
|
16
|
+
fuzzer.rules.should have_key(/foo/)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when given Strings" do
|
20
|
+
subject { described_class.new('foo' => substitutions) }
|
21
|
+
|
22
|
+
it "should convert to Regexp" do
|
23
|
+
subject.rules.should have_key(/foo/)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when given Symbols" do
|
28
|
+
subject { described_class.new(:word => substitutions) }
|
29
|
+
|
30
|
+
it "should lookup the Regexp constant" do
|
31
|
+
subject.rules.should have_key(Regexp::WORD)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "otherwise" do
|
36
|
+
it "should raise a TypeError" do
|
37
|
+
lambda {
|
38
|
+
subject.new(Object.new => substitutions)
|
39
|
+
}.should raise_error(TypeError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "mutations" do
|
45
|
+
let(:pattern) { /foo/ }
|
46
|
+
|
47
|
+
it "should accept Enumerable values" do
|
48
|
+
fuzzer = subject.new(pattern => ['bar'])
|
49
|
+
|
50
|
+
fuzzer.rules[pattern].should == ['bar']
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when given Symbols" do
|
54
|
+
subject { described_class.new(pattern => :bad_strings) }
|
55
|
+
|
56
|
+
it "should map to an Enumerator for a Fuzzing method" do
|
57
|
+
subject.rules[pattern].should be_kind_of(Enumerable)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "otherwise" do
|
62
|
+
it "should raise a TypeError" do
|
63
|
+
lambda {
|
64
|
+
subject.new(pattern => Object.new)
|
65
|
+
}.should raise_error(TypeError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#each" do
|
72
|
+
let(:string) { "foo bar" }
|
73
|
+
|
74
|
+
subject { described_class.new(/o/ => ['0'], /a/ => ['@']) }
|
75
|
+
|
76
|
+
it "should apply every combination of mutation rules" do
|
77
|
+
subject.each(string).to_a.should =~ [
|
78
|
+
"f0o bar",
|
79
|
+
"fo0 bar",
|
80
|
+
"f00 bar",
|
81
|
+
"foo b@r",
|
82
|
+
"f0o b@r",
|
83
|
+
"fo0 b@r",
|
84
|
+
"f00 b@r"
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when mutations contain Integers" do
|
89
|
+
subject { described_class.new(/o/ => [48]) }
|
90
|
+
|
91
|
+
it "should convert them to characters" do
|
92
|
+
subject.each(string).to_a.should =~ [
|
93
|
+
"f0o bar",
|
94
|
+
"fo0 bar",
|
95
|
+
"f00 bar"
|
96
|
+
]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when mutations contain Procs" do
|
101
|
+
subject { described_class.new(/o/ => [lambda { |str| str.upcase }]) }
|
102
|
+
|
103
|
+
it "should call them with the matched String" do
|
104
|
+
subject.each(string).to_a.should =~ [
|
105
|
+
"fOo bar",
|
106
|
+
"foO bar",
|
107
|
+
"fOO bar"
|
108
|
+
]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/repeater'
|
3
|
+
|
4
|
+
describe Fuzzing::Repeater do
|
5
|
+
describe "#initialize" do
|
6
|
+
subject { described_class }
|
7
|
+
|
8
|
+
context "when lengths is an Integer" do
|
9
|
+
it "should coerce lengths to an Enumerable" do
|
10
|
+
repeator = subject.new(10)
|
11
|
+
|
12
|
+
repeator.lengths.should be_kind_of(Enumerable)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when lengths is not Enumerable or an Integer" do
|
17
|
+
it "should raise a TypeError" do
|
18
|
+
lambda {
|
19
|
+
subject.new(Object.new)
|
20
|
+
}.should raise_error(TypeError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#each" do
|
26
|
+
let(:repeatable) { 'A' }
|
27
|
+
|
28
|
+
context "when lengths was an Integer" do
|
29
|
+
let(:length) { 10 }
|
30
|
+
|
31
|
+
subject { described_class.new(length) }
|
32
|
+
|
33
|
+
it "should yield one repeated value" do
|
34
|
+
values = subject.each(repeatable).to_a
|
35
|
+
|
36
|
+
values.should == [repeatable * length]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when lengths was Enumerable" do
|
41
|
+
let(:lengths) { (1..4) }
|
42
|
+
|
43
|
+
subject { described_class.new(lengths) }
|
44
|
+
|
45
|
+
it "should yield repeated values for each length" do
|
46
|
+
values = subject.each(repeatable).to_a.should
|
47
|
+
|
48
|
+
values.should == [
|
49
|
+
repeatable * 1,
|
50
|
+
repeatable * 2,
|
51
|
+
repeatable * 3,
|
52
|
+
repeatable * 4
|
53
|
+
]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/fuzzing/template'
|
3
|
+
|
4
|
+
describe Fuzzing::Template do
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
it "should generate Strings from CharSets" do
|
8
|
+
strings = subject.new([:lowercase_hexadecimal, :numeric]).to_a
|
9
|
+
|
10
|
+
strings.grep(/^[0-9a-f][0-9]$/).should == strings
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should generate Strings from lengths of CharSets" do
|
14
|
+
strings = subject.new([[:numeric, 2]]).to_a
|
15
|
+
|
16
|
+
strings.grep(/^[0-9]{2}$/).should == strings
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should generate Strings from varying lengths of CharSets" do
|
20
|
+
strings = subject.new([[:numeric, 1..2]]).to_a
|
21
|
+
|
22
|
+
strings.grep(/^[0-9]{1,2}$/).should == strings
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should generate Strings from custom CharSets" do
|
26
|
+
strings = subject.new([[%w[a b c], 2]]).to_a
|
27
|
+
|
28
|
+
strings.grep(/^[abc]{2}$/).should == strings
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should generate Strings containing known Strings" do
|
32
|
+
strings = subject.new(['foo', [%w[a b c], 2]]).to_a
|
33
|
+
|
34
|
+
strings.grep(/^foo[abc]{2}$/).should == strings
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise a TypeError for non String, Symbol, Enumerable CharSets" do
|
38
|
+
lambda {
|
39
|
+
subject.new([[Object.new, 2]]).to_a
|
40
|
+
}.should raise_error(TypeError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise an ArgumentError for unknown CharSets" do
|
44
|
+
lambda {
|
45
|
+
subject.new([[:foo_bar, 2]]).to_a
|
46
|
+
}.should raise_error(ArgumentError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should raise a TypeError for non Integer,Array,Range lengths" do
|
50
|
+
lambda {
|
51
|
+
subject.new([[:numeric, 'foo']]).to_a
|
52
|
+
}.should raise_error(TypeError)
|
53
|
+
end
|
54
|
+
end
|