ronin-support 0.2.0 → 0.3.0
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/.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
|