ronin 2.0.5 → 2.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +3 -3
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +5 -1
  5. data/ChangeLog.md +56 -1
  6. data/Gemfile +66 -29
  7. data/README.md +162 -17
  8. data/Rakefile +9 -0
  9. data/data/completions/ronin +655 -0
  10. data/data/templates/dns_proxy.rb.erb +35 -0
  11. data/gemspec.yml +27 -13
  12. data/lib/ronin/cli/binary_template.rb +124 -0
  13. data/lib/ronin/cli/commands/archive.rb +104 -0
  14. data/lib/ronin/cli/commands/banner_grab.rb +2 -0
  15. data/lib/ronin/cli/commands/bitflip.rb +1 -1
  16. data/lib/ronin/cli/commands/bitsquat.rb +119 -0
  17. data/lib/ronin/cli/commands/cert_dump.rb +20 -4
  18. data/lib/ronin/cli/commands/cert_gen.rb +9 -19
  19. data/lib/ronin/cli/commands/cert_grab.rb +4 -3
  20. data/lib/ronin/cli/commands/completion.rb +115 -0
  21. data/lib/ronin/cli/commands/dns_proxy.rb +235 -0
  22. data/lib/ronin/cli/commands/http.rb +80 -8
  23. data/lib/ronin/cli/commands/ip.rb +101 -0
  24. data/lib/ronin/cli/commands/iprange.rb +25 -8
  25. data/lib/ronin/cli/commands/netcat.rb +2 -0
  26. data/lib/ronin/cli/commands/new/dns_listener.rb +37 -0
  27. data/lib/ronin/cli/commands/new/dns_proxy.rb +99 -0
  28. data/lib/ronin/cli/commands/new/exploit.rb +34 -0
  29. data/lib/ronin/cli/commands/new/http_listener.rb +37 -0
  30. data/lib/ronin/cli/commands/new/nokogiri.rb +33 -0
  31. data/lib/ronin/cli/commands/new/payload.rb +34 -0
  32. data/lib/ronin/cli/commands/new/project.rb +1 -1
  33. data/lib/ronin/cli/commands/new/script.rb +1 -1
  34. data/lib/ronin/cli/commands/new/web_app.rb +37 -0
  35. data/lib/ronin/cli/commands/new/web_server.rb +37 -0
  36. data/lib/ronin/cli/commands/new/web_spider.rb +37 -0
  37. data/lib/ronin/cli/commands/new.rb +3 -1
  38. data/lib/ronin/cli/commands/pack.rb +339 -0
  39. data/lib/ronin/cli/commands/public_suffix_list.rb +2 -0
  40. data/lib/ronin/cli/commands/tld_list.rb +2 -0
  41. data/lib/ronin/cli/commands/unarchive.rb +128 -0
  42. data/lib/ronin/cli/commands/unhexdump.rb +3 -1
  43. data/lib/ronin/cli/commands/unpack.rb +195 -0
  44. data/lib/ronin/cli/commands/url.rb +2 -0
  45. data/lib/ronin/cli/http_shell.rb +25 -0
  46. data/lib/ronin/cli.rb +10 -0
  47. data/lib/ronin/version.rb +1 -1
  48. data/man/ronin-archive.1.md +49 -0
  49. data/man/ronin-asn.1 +60 -77
  50. data/man/ronin-asn.1.md +25 -21
  51. data/man/ronin-banner-grab.1 +10 -21
  52. data/man/ronin-banner-grab.1.md +9 -5
  53. data/man/ronin-bitflip.1 +35 -61
  54. data/man/ronin-bitflip.1.md +30 -26
  55. data/man/ronin-bitsquat.1 +40 -0
  56. data/man/ronin-bitsquat.1.md +43 -0
  57. data/man/ronin-cert-dump.1 +44 -54
  58. data/man/ronin-cert-dump.1.md +18 -14
  59. data/man/ronin-cert-gen.1 +73 -94
  60. data/man/ronin-cert-gen.1.md +38 -34
  61. data/man/ronin-cert-grab.1 +29 -37
  62. data/man/ronin-cert-grab.1.md +12 -8
  63. data/man/ronin-completion.1 +78 -0
  64. data/man/ronin-completion.1.md +80 -0
  65. data/man/ronin-decode.1 +32 -63
  66. data/man/ronin-decode.1.md +29 -25
  67. data/man/ronin-decrypt.1 +42 -57
  68. data/man/ronin-decrypt.1.md +20 -16
  69. data/man/ronin-dns-proxy.1 +100 -0
  70. data/man/ronin-dns-proxy.1.md +70 -0
  71. data/man/ronin-dns.1 +10 -21
  72. data/man/ronin-dns.1.md +9 -5
  73. data/man/ronin-email-addr.1 +27 -40
  74. data/man/ronin-email-addr.1.md +15 -11
  75. data/man/ronin-encode.1 +93 -63
  76. data/man/ronin-encode.1.md +64 -26
  77. data/man/ronin-encrypt.1 +42 -57
  78. data/man/ronin-encrypt.1.md +20 -16
  79. data/man/ronin-entropy.1 +11 -21
  80. data/man/ronin-entropy.1.md +8 -4
  81. data/man/ronin-escape.1 +22 -46
  82. data/man/ronin-escape.1.md +22 -18
  83. data/man/ronin-extract.1 +74 -149
  84. data/man/ronin-extract.1.md +73 -69
  85. data/man/ronin-grep.1 +77 -155
  86. data/man/ronin-grep.1.md +76 -72
  87. data/man/ronin-help.1 +3 -14
  88. data/man/ronin-help.1.md +2 -2
  89. data/man/ronin-hexdump.1 +249 -265
  90. data/man/ronin-hexdump.1.md +93 -89
  91. data/man/ronin-highlight.1 +8 -18
  92. data/man/ronin-highlight.1.md +8 -4
  93. data/man/ronin-hmac.1 +17 -30
  94. data/man/ronin-hmac.1.md +14 -10
  95. data/man/ronin-homoglyph.1 +11 -22
  96. data/man/ronin-homoglyph.1.md +10 -6
  97. data/man/ronin-host.1 +23 -47
  98. data/man/ronin-host.1.md +22 -18
  99. data/man/ronin-http.1 +40 -69
  100. data/man/ronin-http.1.md +40 -30
  101. data/man/ronin-ip.1 +70 -80
  102. data/man/ronin-ip.1.md +44 -28
  103. data/man/ronin-iprange.1 +14 -22
  104. data/man/ronin-iprange.1.md +12 -5
  105. data/man/ronin-irb.1 +9 -17
  106. data/man/ronin-irb.1.md +7 -3
  107. data/man/ronin-md5.1 +13 -24
  108. data/man/ronin-md5.1.md +11 -7
  109. data/man/ronin-netcat.1 +25 -51
  110. data/man/ronin-netcat.1.md +25 -21
  111. data/man/ronin-new-dns-proxy.1 +45 -0
  112. data/man/ronin-new-dns-proxy.1.md +44 -0
  113. data/man/ronin-new-project.1 +32 -45
  114. data/man/ronin-new-project.1.md +11 -11
  115. data/man/ronin-new-script.1 +10 -22
  116. data/man/ronin-new-script.1.md +4 -4
  117. data/man/ronin-new.1 +56 -31
  118. data/man/ronin-new.1.md +48 -8
  119. data/man/ronin-pack.1 +977 -0
  120. data/man/ronin-pack.1.md +929 -0
  121. data/man/ronin-proxy.1 +37 -63
  122. data/man/ronin-proxy.1.md +29 -25
  123. data/man/ronin-public-suffix-list.1 +16 -32
  124. data/man/ronin-public-suffix-list.1.md +13 -9
  125. data/man/ronin-quote.1 +17 -36
  126. data/man/ronin-quote.1.md +17 -13
  127. data/man/ronin-rot.1 +26 -39
  128. data/man/ronin-rot.1.md +15 -11
  129. data/man/ronin-sha1.1 +13 -24
  130. data/man/ronin-sha1.1.md +11 -7
  131. data/man/ronin-sha256.1 +13 -24
  132. data/man/ronin-sha256.1.md +11 -7
  133. data/man/ronin-sha512.1 +13 -24
  134. data/man/ronin-sha512.1.md +11 -7
  135. data/man/ronin-strings.1 +30 -55
  136. data/man/ronin-strings.1.md +27 -23
  137. data/man/ronin-tips.1 +8 -16
  138. data/man/ronin-tips.1.md +7 -3
  139. data/man/ronin-tld-list.1 +16 -32
  140. data/man/ronin-tld-list.1.md +13 -9
  141. data/man/ronin-typo.1 +14 -28
  142. data/man/ronin-typo.1.md +13 -9
  143. data/man/ronin-typosquat.1 +15 -32
  144. data/man/ronin-typosquat.1.md +15 -11
  145. data/man/ronin-unarchive.1.md +41 -0
  146. data/man/ronin-unescape.1 +22 -46
  147. data/man/ronin-unescape.1.md +22 -18
  148. data/man/ronin-unhexdump.1 +81 -91
  149. data/man/ronin-unhexdump.1.md +16 -12
  150. data/man/ronin-unpack.1 +978 -0
  151. data/man/ronin-unpack.1.md +920 -0
  152. data/man/ronin-unquote.1 +17 -36
  153. data/man/ronin-unquote.1.md +17 -13
  154. data/man/ronin-url.1 +19 -40
  155. data/man/ronin-url.1.md +19 -15
  156. data/man/ronin-xor.1 +14 -28
  157. data/man/ronin-xor.1.md +13 -9
  158. data/man/ronin.1 +208 -29
  159. data/man/ronin.1.md +156 -11
  160. data/scripts/setup +58 -0
  161. metadata +162 -73
  162. data/lib/ronin/config.rb +0 -95
  163. /data/data/{new → templates}/project/.gitignore +0 -0
  164. /data/data/{new → templates}/project/.ruby-version.erb +0 -0
  165. /data/data/{new → templates}/project/Dockerfile.erb +0 -0
  166. /data/data/{new → templates}/project/Gemfile.erb +0 -0
  167. /data/data/{new → templates}/project/Rakefile +0 -0
  168. /data/data/{new → templates}/project/project.rb.erb +0 -0
  169. /data/data/{new → templates}/script.rb.erb +0 -0
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # Ronin is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Ronin is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Ronin. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/cli/completion_command'
20
+ require 'ronin/repos/cli/commands/completion'
21
+ require 'ronin/wordlists/cli/commands/completion'
22
+ require 'ronin/db/cli/commands/completion'
23
+ require 'ronin/fuzzer/cli/commands/completion'
24
+ require 'ronin/web/cli/commands/completion'
25
+ require 'ronin/vulns/cli/commands/completion'
26
+ require 'ronin/payloads/cli/commands/completion'
27
+ require 'ronin/exploits/cli/commands/completion'
28
+ require 'ronin/listener/cli/commands/completion'
29
+ require 'ronin/nmap/cli/commands/completion'
30
+ require 'ronin/masscan/cli/commands/completion'
31
+ require 'ronin/recon/cli/commands/completion'
32
+ require 'ronin/root'
33
+
34
+ module Ronin
35
+ class CLI
36
+ module Commands
37
+ #
38
+ # Manages the shell completion rule for `ronin` and all other `ronin-*`
39
+ # commands.
40
+ #
41
+ # ## Usage
42
+ #
43
+ # ronin completion [options]
44
+ #
45
+ # ## Options
46
+ #
47
+ # --print Prints the shell completion file
48
+ # --install Installs the shell completion file
49
+ # --uninstall Uninstalls the shell completion file
50
+ # -h, --help Print help information
51
+ #
52
+ # ## Examples
53
+ #
54
+ # ronin completion --print
55
+ # ronin completion --install
56
+ # ronin completion --uninstall
57
+ #
58
+ # @since 2.1.0
59
+ #
60
+ class Completion < Core::CLI::CompletionCommand
61
+
62
+ man_dir File.join(ROOT,'man')
63
+ man_page 'ronin-completion.1'
64
+
65
+ description 'Manages the shell completion rules for ronin and all other ronin-* commands'
66
+
67
+ # All shell completion files for `ronin` and the other `ronin-*`
68
+ # commands.
69
+ COMPLETION_FILES = [
70
+ File.join(ROOT,'data','completions','ronin'),
71
+
72
+ Repos::CLI::Commands::Completion.completion_file,
73
+ Wordlists::CLI::Commands::Completion.completion_file,
74
+ DB::CLI::Commands::Completion.completion_file,
75
+ Fuzzer::CLI::Commands::Completion.completion_file,
76
+ Web::CLI::Commands::Completion.completion_file,
77
+ Vulns::CLI::Commands::Completion.completion_file,
78
+ Payloads::CLI::Commands::Completion.completion_file,
79
+ Exploits::CLI::Commands::Completion.completion_file,
80
+ Listener::CLI::Commands::Completion.completion_file,
81
+ Nmap::CLI::Commands::Completion.completion_file,
82
+ Masscan::CLI::Commands::Completion.completion_file,
83
+ Recon::CLI::Commands::Completion.completion_file
84
+ ]
85
+
86
+ #
87
+ # Prints all completion files.
88
+ #
89
+ def print_completion_file
90
+ COMPLETION_FILES.each do |completion_file|
91
+ super(completion_file)
92
+ end
93
+ end
94
+
95
+ #
96
+ # Installs all completion files.
97
+ #
98
+ def install_completion_file
99
+ COMPLETION_FILES.each do |completion_file|
100
+ super(completion_file)
101
+ end
102
+ end
103
+
104
+ #
105
+ # Uninstall all completion files.
106
+ #
107
+ def uninstall_completion_file
108
+ COMPLETION_FILES.each do |completion_file|
109
+ super(completion_file)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,235 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # Ronin is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Ronin is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Ronin. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/cli/command'
20
+ require 'ronin/dns/proxy'
21
+
22
+ module Ronin
23
+ class CLI
24
+ module Commands
25
+ #
26
+ # Starts a DNS proxy.
27
+ #
28
+ # ## Usage
29
+ #
30
+ # ronin dns-proxy [options] [HOST] PORT
31
+ #
32
+ # ## Options
33
+ #
34
+ # -n, --nameserver IP The upstream nameserver IP to use
35
+ # -r RECORD_TYPE:NAME:RESULT|RECORD_TYPE:/REGEXP/:RESULT,
36
+ # --rule Adds a rule to the DNS proxy
37
+ # -h, --help Print help information
38
+ #
39
+ # ## Arguments
40
+ #
41
+ # [HOST] The host name to listen on.
42
+ # PORT The port number to listen on.
43
+ #
44
+ # @since 2.1.0
45
+ #
46
+ class DnsProxy < Command
47
+
48
+ usage '[options] [HOST] PORT'
49
+
50
+ option :nameserver, short: '-n',
51
+ value: {
52
+ type: String,
53
+ usage: 'IP'
54
+ },
55
+ desc: 'The upstream nameserver IP to use' do |ip|
56
+ @nameservers << ip
57
+ end
58
+
59
+ option :rule, short: '-r',
60
+ value: {
61
+ type: %r{\A[^:]+:(?:[^:]+|/[^/:]+/):.+\z},
62
+ usage: 'RECORD_TYPE:NAME:RESULT|RECORD_TYPE:/REGEXP/:RESULT'
63
+ },
64
+ desc: 'Adds a rule to the DNS proxy' do |rule|
65
+ @rules << parse_rule(rule)
66
+ end
67
+
68
+ argument :host, required: false,
69
+ desc: 'The host to listen on'
70
+
71
+ argument :port, required: true,
72
+ desc: 'The port number to listen on'
73
+
74
+ description 'Starts a DNS proxy'
75
+
76
+ man_page 'ronin-dns-proxy.1'
77
+
78
+ # The upstream nameserver IP addresses to forward DNS queries to.
79
+ #
80
+ # @return [Array<String>]
81
+ attr_reader :nameservers
82
+
83
+ # The rules for the DNS proxy server.
84
+ #
85
+ # @return [Array<(Symbol, String, String), (Symbol, Regexp, String)>]
86
+ attr_reader :rules
87
+
88
+ #
89
+ # Initializes the `ronin dns-proxy` command.
90
+ #
91
+ # @param [Hash{Symbol => Object}] kwargs
92
+ # Additional keyword arguments for the command.
93
+ #
94
+ def initialize(**kwargs)
95
+ super(**kwargs)
96
+
97
+ @nameservers = []
98
+ @rules = []
99
+ end
100
+
101
+ #
102
+ # Runs the `ronin dns-proxy` command.
103
+ #
104
+ def run(host='127.0.0.1',port)
105
+ port = port.to_i
106
+
107
+ DNS::Proxy.run(host,port,**proxy_kwargs)
108
+ end
109
+
110
+ #
111
+ # The keyword arguments for `Ronin::DNS::Proxy.run`.
112
+ #
113
+ # @return [Hash{Symbol => Object}]
114
+ #
115
+ def proxy_kwargs
116
+ kwargs = {rules: @rules}
117
+
118
+ unless @nameservers.empty?
119
+ kwargs[:nameservers] = @nameservers
120
+ end
121
+
122
+ return kwargs
123
+ end
124
+
125
+ # Record types.
126
+ RECORD_TYPES = {
127
+ 'A' => :A,
128
+ 'AAAA' => :AAAA,
129
+ 'ANY' => :ANY,
130
+ 'CNAME' => :CNAME,
131
+ 'HINFO' => :HINFO,
132
+ 'LOC' => :LOC,
133
+ 'MINFO' => :MINFO,
134
+ 'MX' => :MX,
135
+ 'NS' => :NS,
136
+ 'PTR' => :PTR,
137
+ 'SOA' => :SOA,
138
+ 'SRV' => :SRV,
139
+ 'TXT' => :TXT,
140
+ 'WKS' => :WKS
141
+ }
142
+
143
+ #
144
+ # Parses a record type name.
145
+ #
146
+ # @param [String] record_type
147
+ # The record type to parse.
148
+ #
149
+ # @return [:A, :AAAA, :ANY, :CNAME, :HINFO, :LOC, :MINFO, :MX, :NS, :PTR, :SOA, :SRV, :TXT, :WKS]
150
+ # The parsed record type.
151
+ #
152
+ # @raise [OptionParser::InvalidArgument]
153
+ # The record type was unknown.
154
+ #
155
+ def parse_record_type(record_type)
156
+ RECORD_TYPES.fetch(record_type) do
157
+ raise(OptionParser::InvalidArgument,"invalid record type: #{record_type.inspect}")
158
+ end
159
+ end
160
+
161
+ #
162
+ # Parses the name field of a record.
163
+ #
164
+ # @param [String] name
165
+ # The name field to parse.
166
+ #
167
+ # @return [String, Regex]
168
+ # The parsed name. If the name field starts with a `/` and ends with a
169
+ # `/`, then a Regexp will be returned.
170
+ #
171
+ # @raise [OptionParser::InvalidArgument]
172
+ # The name field regex could not be parsed.
173
+ #
174
+ def parse_record_name(name)
175
+ if name.start_with?('/') && name.end_with?('/')
176
+ begin
177
+ Regexp.new(name[1..-2])
178
+ rescue RegexpError => error
179
+ raise(OptionParser::InvalidArgument,"invalid Regexp: #{error.message}")
180
+ end
181
+ else
182
+ name
183
+ end
184
+ end
185
+
186
+ # Error names.
187
+ ERROR_CODES = {
188
+ 'NoError' => :NoError,
189
+ 'FormErr' => :FormErr,
190
+ 'ServFail' => :ServFail,
191
+ 'NXDomain' => :NXDomain,
192
+ 'NotImp' => :NotImp,
193
+ 'Refused' => :Refused,
194
+ 'NotAuth' => :NotAuth
195
+ }
196
+
197
+ #
198
+ # Parses a result value.
199
+ #
200
+ # @param [String] result
201
+ # A result value to parse.
202
+ #
203
+ # @return [String, :NoError, :FormErr, :ServFail, :NXDomain, :NotImp, :Refused, :NotAuth]
204
+ # The parsed result value or a DNS error code.
205
+ #
206
+ def parse_rule_result(result)
207
+ ERROR_CODES.fetch(result,result)
208
+ end
209
+
210
+ #
211
+ # Parses a rule string.
212
+ #
213
+ # @param [String] rule
214
+ # The string to parse.
215
+ #
216
+ # @return [(Symbol, String, String), (Symbol, Regexp, String)]
217
+ # The parsed rule.
218
+ #
219
+ # @raise [OptionParser::InvalidArgument]
220
+ # The rule string could not be parsed.
221
+ #
222
+ def parse_rule(rule)
223
+ record_type, name, result = rule.split(':',3)
224
+
225
+ [
226
+ parse_record_type(record_type),
227
+ parse_record_name(name),
228
+ parse_rule_result(result)
229
+ ]
230
+ end
231
+
232
+ end
233
+ end
234
+ end
235
+ end
@@ -20,6 +20,7 @@ require 'ronin/cli/value_processor_command'
20
20
  require 'ronin/cli/printing/http'
21
21
  require 'ronin/cli/http_shell'
22
22
  require 'ronin/support/network/http'
23
+ require 'ronin/support/network/http/cookie'
23
24
 
24
25
  require 'command_kit/options/verbose'
25
26
  require 'addressable/uri'
@@ -57,9 +58,11 @@ module Ronin
57
58
  # --shell URL Open an interactive HTTP shell
58
59
  # -P, --proxy URL The proxy to use
59
60
  # -U, --user-agent-string STRING The User-Agent string to use
60
- # -u chrome-linux|chrome-macos|chrome-windows|chrome-iphone|chrome-ipad|chrome-android|firefox-linux|firefox-macos|firefox-windows|firefox-iphone|firefox-ipad|firefox-android|safari-macos|safari-iphone|safari-ipad|edge,
61
- # --user-agent The User-Agent to use
61
+ # -u random|chrome|firefox|safari|linux|macos|windows|iphone|ipad|android|chrome_linux|chrome_macos|chrome_windows|chrome_iphone|chrome_ipad|chrome_android|firefox_linux|firefox_macos|firefox_windows|firefox_iphone|firefox_ipad|firefox_android|safari_macos|safari_iphone|safari_ipad|edge,
62
+ # --user-agent The User-Agent alias to use
62
63
  # -H, --header "NAME: VALUE" Adds a header to the request
64
+ # -C, --cookie COOKIE Sets the Cookie header
65
+ # -c, --cookie-param NAME=VALUE Sets an additional cookie param
63
66
  # -B, --body STRING The request body
64
67
  # -F, --body-file FILE Sends the file as the request body
65
68
  # -f, --form-data NAME=VALUE Adds a value to the form data
@@ -76,7 +79,7 @@ module Ronin
76
79
  include Printing::HTTP
77
80
 
78
81
  # `http://` and `https://` URL validation regex.
79
- URL_REGEX = URI::DEFAULT_PARSER.make_regexp(%w[http https])
82
+ URL_REGEX = /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/
80
83
 
81
84
  usage '[options] {URL [...] | --shell URL}'
82
85
 
@@ -178,13 +181,46 @@ module Ronin
178
181
  @user_agent = ua
179
182
  end
180
183
 
184
+ # Mapping of user-agent aliases.
185
+ USER_AGENT_ALIASES = {
186
+ 'random' => :random,
187
+ 'chrome' => :chrome,
188
+ 'firefox' => :firefox,
189
+ 'safari' => :safari,
190
+ 'linux' => :linux,
191
+ 'macos' => :macos,
192
+ 'windows' => :windows,
193
+ 'iphone' => :iphone,
194
+ 'ipad' => :ipad,
195
+ 'android' => :android,
196
+
197
+ 'chrome_linux' => :chrome_linux,
198
+ 'chrome_macos' => :chrome_macos,
199
+ 'chrome_windows' => :chrome_windows,
200
+ 'chrome_iphone' => :chrome_iphone,
201
+ 'chrome_ipad' => :chrome_ipad,
202
+ 'chrome_android' => :chrome_android,
203
+
204
+ 'firefox_linux' => :firefox_linux,
205
+ 'firefox_macos' => :firefox_macos,
206
+ 'firefox_windows' => :firefox_windows,
207
+ 'firefox_iphone' => :firefox_iphone,
208
+ 'firefox_ipad' => :firefox_ipad,
209
+
210
+ 'firefox_android' => :firefox_android,
211
+
212
+ 'safari_macos' => :safari_macos,
213
+ 'safari_iphone' => :safari_iphone,
214
+ 'safari_ipad' => :safari_ipad,
215
+
216
+ 'edge' => :edge
217
+ }
218
+
181
219
  option :user_agent, short: '-u',
182
220
  value: {
183
- type: Support::Network::HTTP::UserAgents::ALIASES.transform_keys { |key|
184
- key.to_s.tr('_','-')
185
- }
221
+ type: USER_AGENT_ALIASES
186
222
  },
187
- desc: 'The User-Agent to use' do |name|
223
+ desc: 'The User-Agent alias to use' do |name|
188
224
  @user_agent = name
189
225
  end
190
226
 
@@ -199,6 +235,35 @@ module Ronin
199
235
  @headers[name] = value
200
236
  end
201
237
 
238
+ option :cookie, short: '-C',
239
+ value: {
240
+ type: String,
241
+ usage: 'COOKIE'
242
+ },
243
+ desc: 'Sets the Cookie header' do |cookie|
244
+ cookie = Support::Network::HTTP::Cookie.parse(cookie)
245
+
246
+ if @cookie
247
+ @cookie.merge!(cookie)
248
+ else
249
+ @cookie = cookie
250
+ end
251
+ end
252
+
253
+ option :cookie_param, short: '-c',
254
+ value: {
255
+ type: /[^\s=]+=\w+/,
256
+ usage: 'NAME=VALUE'
257
+ },
258
+ desc: 'Sets an additional cookie param' do |param|
259
+ name, value = param.split('=',2)
260
+
261
+ # lazy initialize the cookie
262
+ @cookie ||= Support::Network::HTTP::Cookie.new
263
+
264
+ @cookie[name] = value
265
+ end
266
+
202
267
  option :body, short: '-B',
203
268
  value: {
204
269
  type: String,
@@ -262,9 +327,14 @@ module Ronin
262
327
  # @return [Hash{String => String}]
263
328
  attr_reader :headers
264
329
 
330
+ # The optional `Cookie` header to send.
331
+ #
332
+ # @return [Ronin::Support::Network::HTTP::Cookie, nil]
333
+ attr_reader :cookie
334
+
265
335
  # Optional `User-agent` string to use.
266
336
  #
267
- # @return [String, nil]
337
+ # @return [String, Symbol, nil]
268
338
  attr_reader :user_agent
269
339
 
270
340
  # Additional URL query params.
@@ -294,6 +364,7 @@ module Ronin
294
364
  @proxy = nil
295
365
  @http_method = :get
296
366
  @headers = {}
367
+ @cookie = nil
297
368
  @user_agent = nil
298
369
  @query_params = {}
299
370
  @form_data = {}
@@ -347,6 +418,7 @@ module Ronin
347
418
  begin
348
419
  Support::Network::HTTP.request(
349
420
  @http_method, uri, proxy: @proxy,
421
+ cookie: @cookie,
350
422
  user_agent: @user_agent,
351
423
  query_params: @query_params,
352
424
  headers: @headers,
@@ -19,6 +19,7 @@
19
19
  require 'ronin/cli/value_processor_command'
20
20
  require 'ronin/support/network/ip'
21
21
  require 'uri'
22
+ require 'ipaddr'
22
23
 
23
24
  module Ronin
24
25
  class CLI
@@ -40,6 +41,10 @@ module Ronin
40
41
  # -D, --decimal Converts the IP address to decimal format
41
42
  # -O, --octal Converts the IP address to octal format
42
43
  # -B, --binary Converts the IP address to binary format
44
+ # --hex-octet Converts the IP address to hexadecimal format by octet
45
+ # --octal-octet Converts the IP address to octal format by octet
46
+ # --ipv6-compat Converts the IPv4 address to an IPv6 compatible address
47
+ # --ipv6-expanded Expands a shortened or compressed IPv6 address
43
48
  # -C, --cidr NETMASK Converts the IP address into a CIDR range
44
49
  # -H, --host Converts the IP address to a host name
45
50
  # -p, --port PORT Appends the port number to each IP
@@ -89,6 +94,16 @@ module Ronin
89
94
  option :binary, short: '-B',
90
95
  desc: 'Converts the IP address to binary format'
91
96
 
97
+ option :hex_octet,
98
+ desc: 'Converts the IP address to hexadecimal format by octet'
99
+
100
+ option :octal_octet,
101
+ desc: 'Converts the IP address to octal format by octet'
102
+
103
+ option :ipv6_compat, desc: 'Converts the IPv4 address to an IPv6 compatible address'
104
+
105
+ option :ipv6_expanded, desc: 'Expands a shortened or compressed IPv6 address'
106
+
92
107
  option :cidr, short: '-C',
93
108
  value: {
94
109
  type: String,
@@ -225,19 +240,105 @@ module Ronin
225
240
  # The formatted IP address.
226
241
  #
227
242
  def format_ip(ip)
243
+ if ip.ipv4?
244
+ format_ipv4(ip)
245
+ else
246
+ format_ipv6(ip)
247
+ end
248
+ end
249
+
250
+ private
251
+
252
+ #
253
+ # Formats an IPv4 address.
254
+ #
255
+ # @param [Ronin::Support::Network::IP] ip
256
+ # The IP address to format.
257
+ #
258
+ # @return [String]
259
+ # The formatted IP address.
260
+ #
261
+ def format_ipv4(ip)
228
262
  if options[:hex]
229
263
  "0x%x" % ip.to_i
264
+ elsif options[:hex_octet]
265
+ ipv4_hex_octet(ip)
230
266
  elsif options[:decimal]
231
267
  "%u" % ip.to_i
232
268
  elsif options[:octal]
233
269
  "0%o" % ip.to_i
270
+ elsif options[:octal_octet]
271
+ ip.to_s.split(".").map { |octet| "0%o" % octet.to_i }.join(".")
272
+ elsif options[:binary]
273
+ "%b" % ip.to_i
274
+ elsif options[:ipv6_compat]
275
+ ip.ipv4_mapped.to_s
276
+ elsif options[:ipv6_expanded]
277
+ print_error "called with --ipv6-expanded for #{ip}"
278
+ exit(1)
279
+ else
280
+ ip.to_s
281
+ end
282
+ end
283
+
284
+ #
285
+ # Formats an IPv6 address.
286
+ #
287
+ # @param [Ronin::Support::Network::IP] ip
288
+ # The IP address to format.
289
+ #
290
+ # @return [String]
291
+ # The formatted IP address.
292
+ #
293
+ def format_ipv6(ip)
294
+ if options[:decimal]
295
+ "%u" % ip.to_i
296
+ elsif options[:hex]
297
+ "0x%x" % ip.to_i
298
+ elsif options[:octal]
299
+ "0%o" % ip.to_i
300
+ elsif options[:octal_octet]
301
+ print_error "called with --octal-octet for #{ip}"
302
+ exit(1)
303
+ elsif options[:hex_octet]
304
+ if ip.ipv4_mapped?
305
+ "::ffff:#{ipv4_hex_octet(ip.ipv4)}"
306
+ else
307
+ print_error "called with --hex-octet for #{ip}"
308
+ exit(1)
309
+ end
234
310
  elsif options[:binary]
235
311
  "%b" % ip.to_i
312
+ elsif options[:ipv6_expanded]
313
+ ip.canonical
314
+ elsif options[:ipv6_compat]
315
+ print_error "called with --ipv6-compat for #{ip}"
316
+ exit(1)
236
317
  else
237
318
  ip.to_s
238
319
  end
239
320
  end
240
321
 
322
+ #
323
+ # Converts the octets of an IP address to hex
324
+ #
325
+ # @param [Ronin::Support::Network::IP] ip
326
+ # The IP address to convert.
327
+ #
328
+ # @return [String]
329
+ # The formatted IP address.
330
+ #
331
+ def ipv4_hex_octet(ip)
332
+ ip_uint = ip.to_i
333
+
334
+ format(
335
+ "%<octet1>x.%<octet2>x.%<octet3>x.%<octet4>x",
336
+ octet1: (ip_uint & 0xff000000) >> 24,
337
+ octet2: (ip_uint & 0xff0000) >> 16,
338
+ octet3: (ip_uint & 0xff00) >> 8,
339
+ octet4: (ip_uint & 0xff)
340
+ )
341
+ end
241
342
  end
242
343
  end
243
344
  end
@@ -34,6 +34,7 @@ module Ronin
34
34
  # -f, --file FILE Optional file to read values from
35
35
  # --start IP Starting IP address
36
36
  # --stop IP Stopping IP address
37
+ # -s, --size Prints the size of the IP range
37
38
  # -h, --help Print help information
38
39
  #
39
40
  # ## Arguments
@@ -68,6 +69,9 @@ module Ronin
68
69
  @stop << ip
69
70
  end
70
71
 
72
+ option :size, short: '-s',
73
+ desc: 'Prints the size of the IP range'
74
+
71
75
  argument :ip_range, required: false,
72
76
  repeats: true,
73
77
  desc: 'The IP Range to enumerate'
@@ -110,9 +114,7 @@ module Ronin
110
114
  @start.zip(@stop).each do |(start,stop)|
111
115
  range = Support::Network::IPRange::Range.new(start,stop)
112
116
 
113
- range.each do |ip|
114
- puts ip
115
- end
117
+ process_ip_range(range)
116
118
  end
117
119
  else
118
120
  super(*ip_ranges)
@@ -122,13 +124,28 @@ module Ronin
122
124
  #
123
125
  # Processes an IP range.
124
126
  #
125
- # @param [String] ip_range
127
+ # @param [String] string
126
128
  #
127
- def process_value(ip_range)
128
- ip_range = Support::Network::IPRange.new(ip_range)
129
+ def process_value(string)
130
+ range = Support::Network::IPRange.new(string)
131
+
132
+ process_ip_range(range)
133
+ end
129
134
 
130
- ip_range.each do |ip|
131
- puts ip
135
+ #
136
+ # Processes a parsed IP range object.
137
+ #
138
+ # @param [Ronin::Support::Network::IPRange,
139
+ # Ronin::Support::Network::IPRange::Range] ip_range
140
+ # The IP range to process.
141
+ #
142
+ def process_ip_range(ip_range)
143
+ if options[:size]
144
+ puts ip_range.size
145
+ else
146
+ ip_range.each do |ip|
147
+ puts ip
148
+ end
132
149
  end
133
150
  end
134
151