ronin-support 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/ChangeLog.md +42 -1
- data/README.md +4 -1
- data/gemspec.yml +2 -1
- data/lib/ronin/extensions.rb +2 -0
- data/lib/ronin/extensions/enumerable.rb +54 -0
- data/lib/ronin/extensions/file.rb +70 -2
- data/lib/ronin/extensions/ip_addr.rb +45 -45
- data/lib/ronin/extensions/regexp.rb +45 -0
- data/lib/ronin/extensions/resolv.rb +80 -0
- data/lib/ronin/extensions/string.rb +35 -32
- data/lib/ronin/formatting/extensions/binary/integer.rb +12 -5
- data/lib/ronin/formatting/extensions/binary/string.rb +44 -16
- data/lib/ronin/formatting/extensions/html/integer.rb +51 -31
- data/lib/ronin/formatting/extensions/html/string.rb +50 -31
- data/lib/ronin/formatting/extensions/http/integer.rb +10 -2
- data/lib/ronin/formatting/extensions/sql.rb +20 -0
- data/lib/ronin/formatting/extensions/sql/string.rb +98 -0
- data/lib/ronin/formatting/extensions/text/array.rb +11 -9
- data/lib/ronin/formatting/extensions/text/string.rb +213 -29
- data/lib/ronin/formatting/sql.rb +20 -0
- data/lib/ronin/network/extensions/http.rb +1 -0
- data/lib/ronin/network/extensions/http/net.rb +2 -2
- data/lib/ronin/network/extensions/http/uri/http.rb +226 -0
- data/lib/ronin/network/extensions/imap/net.rb +1 -1
- data/lib/ronin/network/extensions/ssl/net.rb +7 -1
- data/lib/ronin/network/http/proxy.rb +20 -21
- data/lib/ronin/network/mixins.rb +27 -0
- data/lib/ronin/network/mixins/esmtp.rb +165 -0
- data/lib/ronin/network/mixins/http.rb +723 -0
- data/lib/ronin/network/mixins/imap.rb +151 -0
- data/lib/ronin/network/mixins/pop3.rb +141 -0
- data/lib/ronin/network/mixins/smtp.rb +159 -0
- data/lib/ronin/network/mixins/tcp.rb +331 -0
- data/lib/ronin/network/mixins/telnet.rb +199 -0
- data/lib/ronin/network/mixins/udp.rb +227 -0
- data/lib/ronin/network/ssl.rb +17 -11
- data/lib/ronin/path.rb +3 -3
- data/lib/ronin/spec/ui/output.rb +28 -0
- data/lib/ronin/support.rb +3 -0
- data/lib/ronin/support/version.rb +1 -1
- data/lib/ronin/ui/output.rb +21 -0
- data/lib/ronin/ui/output/helpers.rb +248 -0
- data/lib/ronin/ui/output/output.rb +146 -0
- data/lib/ronin/ui/output/terminal.rb +21 -0
- data/lib/ronin/ui/output/terminal/color.rb +118 -0
- data/lib/ronin/ui/output/terminal/raw.rb +103 -0
- data/lib/ronin/ui/shell.rb +219 -0
- data/ronin-support.gemspec +1 -1
- data/spec/extensions/enumerable_spec.rb +24 -0
- data/spec/extensions/file_spec.rb +39 -0
- data/spec/extensions/ip_addr_spec.rb +6 -0
- data/spec/extensions/resolv_spec.rb +18 -0
- data/spec/formatting/html/integer_spec.rb +2 -2
- data/spec/formatting/html/string_spec.rb +1 -1
- data/spec/formatting/sql/string_spec.rb +55 -0
- data/spec/formatting/text/string_spec.rb +110 -0
- data/spec/network/ssl_spec.rb +10 -4
- data/spec/ui/classes/test_shell.rb +22 -0
- data/spec/ui/output_spec.rb +32 -0
- data/spec/ui/shell_spec.rb +79 -0
- metadata +132 -90
data/ronin-support.gemspec
CHANGED
@@ -99,7 +99,7 @@ Gem::Specification.new do |gemspec|
|
|
99
99
|
end
|
100
100
|
|
101
101
|
if gemspec.respond_to?(:required_rubygems_version=)
|
102
|
-
gemspec.required_rubygems_version = metadata['
|
102
|
+
gemspec.required_rubygems_version = metadata['required_rubygems_version']
|
103
103
|
end
|
104
104
|
|
105
105
|
parse_versions = lambda { |versions|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/extensions/enumerable'
|
3
|
+
|
4
|
+
describe Enumerable do
|
5
|
+
describe "#map_hash" do
|
6
|
+
it "should map elements to a Hash" do
|
7
|
+
[1, 2, 3].map_hash { |i| i ** 2 }.should == {
|
8
|
+
1 => 1,
|
9
|
+
2 => 4,
|
10
|
+
3 => 9
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not map the same element twice" do
|
15
|
+
[1, 2, 2].map_hash { |i| rand }.keys.should =~ [1, 2]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set the default_proc of the Hash" do
|
19
|
+
hash = [].map_hash { |i| i ** 2 }
|
20
|
+
|
21
|
+
hash[3].should == 9
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'ronin/extensions/file'
|
3
3
|
|
4
|
+
require 'tempfile'
|
5
|
+
|
4
6
|
describe File do
|
5
7
|
subject { File }
|
6
8
|
|
@@ -8,6 +10,43 @@ describe File do
|
|
8
10
|
subject.should respond_to(:escape_path)
|
9
11
|
end
|
10
12
|
|
13
|
+
describe "each_line" do
|
14
|
+
let(:lines) { %w[one two three] }
|
15
|
+
|
16
|
+
before(:all) do
|
17
|
+
@file = Tempfile.new('ronin-support')
|
18
|
+
@file.puts(*lines)
|
19
|
+
@file.close
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should enumerate over each line in the file" do
|
23
|
+
File.each_line(@file.path).to_a.should == lines
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "each_row" do
|
28
|
+
let(:rows) do
|
29
|
+
[
|
30
|
+
%w[one two three],
|
31
|
+
%w[four five six]
|
32
|
+
]
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:separator) { '|' }
|
36
|
+
let(:newline) { "\r\n" }
|
37
|
+
let(:lines) { rows.map { |row| row.join(separator) }.join(newline) }
|
38
|
+
|
39
|
+
before(:all) do
|
40
|
+
@file = Tempfile.new('ronin-support')
|
41
|
+
@file.write(lines)
|
42
|
+
@file.close
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should enumerate over each row from each line" do
|
46
|
+
File.each_row(@file.path,separator).to_a.should == rows
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
11
50
|
describe "escape_path" do
|
12
51
|
it "should remove null-bytes" do
|
13
52
|
File.escape_path("hello\0world\0").should == "helloworld"
|
@@ -160,10 +160,16 @@ describe IPAddr do
|
|
160
160
|
let(:bad_ip) { IPAddr.new('0.0.0.0') }
|
161
161
|
|
162
162
|
describe "#lookup" do
|
163
|
+
let(:nameserver) { '4.2.2.1' }
|
164
|
+
|
163
165
|
it "should lookup the host-name for an IP" do
|
164
166
|
ip.lookup.should include('localhost')
|
165
167
|
end
|
166
168
|
|
169
|
+
it "may lookup host-names via other nameservers" do
|
170
|
+
ip.lookup(nameserver).should be_empty
|
171
|
+
end
|
172
|
+
|
167
173
|
it "should return an empty Array for unknown IP addresses" do
|
168
174
|
bad_ip.lookup.should be_empty
|
169
175
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/extensions/resolv'
|
3
|
+
|
4
|
+
describe Resolv do
|
5
|
+
describe "resolver" do
|
6
|
+
let(:nameserver) { '4.2.2.1' }
|
7
|
+
|
8
|
+
subject { Resolv }
|
9
|
+
|
10
|
+
it "should create a new Resolv::DNS object if a nameserver is given" do
|
11
|
+
subject.resolver(nameserver).should be_kind_of(Resolv::DNS)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return the default resolver otherwise" do
|
15
|
+
subject.resolver.should == Resolv
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -53,14 +53,14 @@ describe Integer do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "#format_js" do
|
56
|
-
let(:js_escaped) {
|
56
|
+
let(:js_escaped) { '\x26' }
|
57
57
|
|
58
58
|
it "should JavaScript format ascii bytes" do
|
59
59
|
subject.format_js.should == js_escaped
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should JavaScript format unicode bytes" do
|
63
|
-
0xd556.format_js.should ==
|
63
|
+
0xd556.format_js.should == '\uD556'
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -94,7 +94,7 @@ describe String do
|
|
94
94
|
end
|
95
95
|
|
96
96
|
describe "#format_js" do
|
97
|
-
let(:js_formatted) {
|
97
|
+
let(:js_formatted) { '\x6F\x6E\x65\x20\x26\x20\x74\x77\x6F' }
|
98
98
|
|
99
99
|
it "should JavaScript escape all characters" do
|
100
100
|
subject.format_js.should == js_formatted
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/formatting/extensions/sql/string'
|
3
|
+
|
4
|
+
describe String do
|
5
|
+
before(:all) do
|
6
|
+
@string = '/etc/passwd'
|
7
|
+
@sql_encoded = '0x2f6574632f706173737764'
|
8
|
+
@string_with_quotes = %{"O'Brian"}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should provide the #sql_escape method" do
|
12
|
+
@string.should respond_to(:sql_escape)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should provide the #sql_encode method" do
|
16
|
+
@string.should respond_to(:sql_encode)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should provide the #sql_decode method" do
|
20
|
+
@string.should respond_to(:sql_decode)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "SQL escaping" do
|
24
|
+
it "should be able to single-quote escape" do
|
25
|
+
@string_with_quotes.sql_escape(:single).should == %{'"O''Brian"'}
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to double-quote escape" do
|
29
|
+
@string_with_quotes.sql_escape(:double).should == %{"""O'Brian"""}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "SQL-hex encoding" do
|
34
|
+
it "should be able to be SQL-hex encoded" do
|
35
|
+
@string.sql_encode.should == @sql_encoded
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return an empty String if empty" do
|
39
|
+
''.sql_encode.should == ''
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "SQL-hex decoding" do
|
44
|
+
it "should be able to be SQL-hex decoded" do
|
45
|
+
encoded = @string.sql_encode
|
46
|
+
|
47
|
+
encoded.should == @sql_encoded
|
48
|
+
encoded.sql_decode.should == @string
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should be able to decode SQL comma-escaping" do
|
52
|
+
"'Conan O''Brian'".sql_decode.should == "Conan O'Brian"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -4,6 +4,10 @@ require 'ronin/formatting/text'
|
|
4
4
|
describe String do
|
5
5
|
subject { "hello" }
|
6
6
|
|
7
|
+
it "should provide String.generate" do
|
8
|
+
described_class.should respond_to(:generate)
|
9
|
+
end
|
10
|
+
|
7
11
|
it "should provide String#format_chars" do
|
8
12
|
should respond_to(:format_chars)
|
9
13
|
end
|
@@ -24,6 +28,112 @@ describe String do
|
|
24
28
|
should respond_to(:insert_after)
|
25
29
|
end
|
26
30
|
|
31
|
+
describe "generate" do
|
32
|
+
subject { described_class }
|
33
|
+
|
34
|
+
it "should generate Strings from CharSets" do
|
35
|
+
strings = subject.generate(:lowercase_hexadecimal, :numeric).to_a
|
36
|
+
|
37
|
+
strings.grep(/^[0-9a-f][0-9]$/).should == strings
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should generate Strings from lengths of CharSets" do
|
41
|
+
strings = subject.generate([:numeric, 2]).to_a
|
42
|
+
|
43
|
+
strings.grep(/^[0-9]{2}$/).should == strings
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should generate Strings from varying lengths of CharSets" do
|
47
|
+
strings = subject.generate([:numeric, 1..2]).to_a
|
48
|
+
|
49
|
+
strings.grep(/^[0-9]{1,2}$/).should == strings
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should generate Strings from custom CharSets" do
|
53
|
+
strings = subject.generate([%w[a b c], 2]).to_a
|
54
|
+
|
55
|
+
strings.grep(/^[abc]{2}$/).should == strings
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should generate Strings containing known Strings" do
|
59
|
+
strings = subject.generate('foo', [%w[a b c], 2]).to_a
|
60
|
+
|
61
|
+
strings.grep(/^foo[abc]{2}$/).should == strings
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should raise a TypeError for non String, Symbol, Enumerable CharSets" do
|
65
|
+
lambda {
|
66
|
+
subject.generate([Object.new, 2]).to_a
|
67
|
+
}.should raise_error(TypeError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should raise an ArgumentError for unknown CharSets" do
|
71
|
+
lambda {
|
72
|
+
subject.generate([:foo_bar, 2]).to_a
|
73
|
+
}.should raise_error(ArgumentError)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should raise a TypeError for non Integer,Array,Range lengths" do
|
77
|
+
lambda {
|
78
|
+
subject.generate([:numeric, 'foo']).to_a
|
79
|
+
}.should raise_error(TypeError)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#fuzz" do
|
84
|
+
subject { 'GET /one/two/three' }
|
85
|
+
|
86
|
+
it "should match Regexps" do
|
87
|
+
fuzzed = subject.fuzz(/GET/ => ['get']).to_a
|
88
|
+
|
89
|
+
fuzzed.should == ['get /one/two/three']
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should match Strings" do
|
93
|
+
fuzzed = subject.fuzz('GET' => ['get']).to_a
|
94
|
+
|
95
|
+
fuzzed.should == ['get /one/two/three']
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should match Integers" do
|
99
|
+
fuzzed = subject.fuzz(0x20 => ["\t"]).to_a
|
100
|
+
|
101
|
+
fuzzed.should == ["GET\t/one/two/three"]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should substitute using Procs" do
|
105
|
+
fuzzed = subject.fuzz('GET' => [lambda { |s| s.downcase }]).to_a
|
106
|
+
|
107
|
+
fuzzed.should == ['get /one/two/three']
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should substitute using Integers" do
|
111
|
+
fuzzed = subject.fuzz(' ' => [0x09]).to_a
|
112
|
+
|
113
|
+
fuzzed.should == ["GET\t/one/two/three"]
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should incrementally replace each occurrence" do
|
117
|
+
fuzzed = subject.fuzz('/' => ["\n\r"]).to_a
|
118
|
+
|
119
|
+
fuzzed.should == [
|
120
|
+
"GET \n\rone/two/three",
|
121
|
+
"GET /one\n\rtwo/three",
|
122
|
+
"GET /one/two\n\rthree"
|
123
|
+
]
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should replace each occurrence with each substitution" do
|
127
|
+
fuzzed = subject.fuzz('GET' => ["\n\rGET", "G\n\rET", "GET\n\r"]).to_a
|
128
|
+
|
129
|
+
fuzzed.should == [
|
130
|
+
"\n\rGET /one/two/three",
|
131
|
+
"G\n\rET /one/two/three",
|
132
|
+
"GET\n\r /one/two/three"
|
133
|
+
]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
27
137
|
describe "#format_bytes" do
|
28
138
|
it "should format each byte in the String" do
|
29
139
|
subject.format_bytes { |b|
|
data/spec/network/ssl_spec.rb
CHANGED
@@ -2,13 +2,19 @@ require 'spec_helper'
|
|
2
2
|
require 'ronin/network/ssl'
|
3
3
|
|
4
4
|
describe Network::SSL do
|
5
|
-
describe '
|
6
|
-
|
7
|
-
|
5
|
+
describe 'VERIFY' do
|
6
|
+
subject { Network::SSL::VERIFY }
|
7
|
+
|
8
|
+
it "should map verify mode names to OpenSSL VERIFY_* constants" do
|
9
|
+
subject[:peer].should == OpenSSL::SSL::VERIFY_PEER
|
8
10
|
end
|
9
11
|
|
10
12
|
it "should default to VERIFY_NONE if no verify mode name is given" do
|
11
|
-
subject.
|
13
|
+
subject[nil].should == OpenSSL::SSL::VERIFY_NONE
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise an exception for unknown verify modes" do
|
17
|
+
lambda { subject[:foo_bar] }.should raise_error
|
12
18
|
end
|
13
19
|
end
|
14
20
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'ronin/ui/shell'
|
2
|
+
|
3
|
+
class TestShell < Ronin::UI::Shell
|
4
|
+
|
5
|
+
def a_public_method
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def command1
|
11
|
+
:command1
|
12
|
+
end
|
13
|
+
|
14
|
+
def command_with_arg(arg)
|
15
|
+
arg
|
16
|
+
end
|
17
|
+
|
18
|
+
def command_with_args(*args)
|
19
|
+
args
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/ui/output'
|
3
|
+
|
4
|
+
describe UI::Output do
|
5
|
+
it "should be quiet by default" do
|
6
|
+
should be_quiet
|
7
|
+
end
|
8
|
+
|
9
|
+
it "may become verbose" do
|
10
|
+
subject.verbose!
|
11
|
+
|
12
|
+
should be_verbose
|
13
|
+
should_not be_quiet
|
14
|
+
should_not be_silent
|
15
|
+
end
|
16
|
+
|
17
|
+
it "may become quiet" do
|
18
|
+
subject.quiet!
|
19
|
+
|
20
|
+
should be_quiet
|
21
|
+
should_not be_silent
|
22
|
+
should_not be_verbose
|
23
|
+
end
|
24
|
+
|
25
|
+
it "may become silent" do
|
26
|
+
subject.silent!
|
27
|
+
|
28
|
+
should be_silent
|
29
|
+
should_not be_quiet
|
30
|
+
should_not be_verbose
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/ui/shell'
|
3
|
+
|
4
|
+
require 'ui/classes/test_shell'
|
5
|
+
|
6
|
+
describe UI::Shell do
|
7
|
+
context "with handler callback" do
|
8
|
+
let(:line) { 'one two three' }
|
9
|
+
|
10
|
+
it "should call the input handler with the shell and input line" do
|
11
|
+
lines = []
|
12
|
+
shell = described_class.new { |shell,input| lines << input }
|
13
|
+
|
14
|
+
shell.call(line)
|
15
|
+
|
16
|
+
lines.should == [line]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with commands" do
|
21
|
+
subject { TestShell.new }
|
22
|
+
|
23
|
+
describe "#commands" do
|
24
|
+
it "should include builtin methods" do
|
25
|
+
subject.commands.should include(:help, :exit)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should include protected methods" do
|
29
|
+
subject.commands.should include(:command1, :command_with_arg, :command_with_args)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not include public methods" do
|
33
|
+
subject.commands.should_not include(:a_public_method)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#call" do
|
38
|
+
it "should ignore empty lines" do
|
39
|
+
subject.call('').should == false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should ignore white-space lines" do
|
43
|
+
subject.call(" \t ").should == false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not allow calling the handler method" do
|
47
|
+
subject.call('handler').should == false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not allow calling unknown commands" do
|
51
|
+
subject.call('an_unknown_command').should == false
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not allow calling unknown commands" do
|
55
|
+
subject.call('an_unknown_command').should == false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not allow calling public methods" do
|
59
|
+
subject.call('a_public_method').should == false
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should allow calling protected methods" do
|
63
|
+
subject.call('command1').should == :command1
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should raise an exception when passing invalid number of arguments" do
|
67
|
+
lambda {
|
68
|
+
subject.call('command_with_arg too many args')
|
69
|
+
}.should raise_error(ArgumentError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should splat the command arguments to the command method" do
|
73
|
+
subject.call('command_with_args one two three').should == [
|
74
|
+
'one', 'two', 'three'
|
75
|
+
]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|