ronin-support 0.4.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.github/workflows/ruby.yml +28 -0
  4. data/.ruby-version +1 -0
  5. data/.yardopts +1 -1
  6. data/ChangeLog.md +121 -33
  7. data/Gemfile +17 -18
  8. data/README.md +57 -33
  9. data/Rakefile +10 -3
  10. data/gemspec.yml +16 -7
  11. data/lib/ronin/binary.rb +21 -0
  12. data/lib/ronin/binary/hexdump.rb +20 -0
  13. data/lib/ronin/binary/hexdump/parser.rb +403 -0
  14. data/lib/ronin/binary/struct.rb +567 -0
  15. data/lib/ronin/binary/template.rb +454 -0
  16. data/lib/ronin/extensions.rb +5 -5
  17. data/lib/ronin/extensions/enumerable.rb +5 -5
  18. data/lib/ronin/extensions/file.rb +39 -33
  19. data/lib/ronin/extensions/ip_addr.rb +29 -31
  20. data/lib/ronin/extensions/kernel.rb +5 -5
  21. data/lib/ronin/extensions/meta.rb +5 -5
  22. data/lib/ronin/extensions/regexp.rb +50 -5
  23. data/lib/ronin/extensions/resolv.rb +7 -9
  24. data/lib/ronin/extensions/string.rb +10 -10
  25. data/lib/ronin/formatting.rb +5 -5
  26. data/lib/ronin/formatting/binary.rb +5 -5
  27. data/lib/ronin/formatting/digest.rb +5 -5
  28. data/lib/ronin/formatting/extensions.rb +5 -5
  29. data/lib/ronin/formatting/extensions/binary.rb +7 -5
  30. data/lib/ronin/formatting/extensions/binary/array.rb +61 -0
  31. data/lib/ronin/formatting/extensions/binary/base64.rb +106 -0
  32. data/lib/ronin/formatting/extensions/binary/file.rb +44 -11
  33. data/lib/ronin/formatting/extensions/binary/float.rb +65 -0
  34. data/lib/ronin/formatting/extensions/binary/integer.rb +66 -50
  35. data/lib/ronin/formatting/extensions/binary/string.rb +81 -205
  36. data/lib/ronin/formatting/extensions/digest.rb +5 -5
  37. data/lib/ronin/formatting/extensions/digest/file.rb +5 -5
  38. data/lib/ronin/formatting/extensions/digest/string.rb +5 -5
  39. data/lib/ronin/formatting/extensions/html.rb +5 -5
  40. data/lib/ronin/formatting/extensions/html/integer.rb +9 -13
  41. data/lib/ronin/formatting/extensions/html/string.rb +31 -39
  42. data/lib/ronin/formatting/extensions/http.rb +5 -5
  43. data/lib/ronin/formatting/extensions/http/integer.rb +6 -6
  44. data/lib/ronin/formatting/extensions/http/string.rb +7 -7
  45. data/lib/ronin/formatting/extensions/sql.rb +5 -5
  46. data/lib/ronin/formatting/extensions/sql/string.rb +22 -24
  47. data/lib/ronin/formatting/extensions/text.rb +5 -5
  48. data/lib/ronin/formatting/extensions/text/array.rb +13 -11
  49. data/lib/ronin/formatting/extensions/text/string.rb +70 -13
  50. data/lib/ronin/formatting/html.rb +5 -5
  51. data/lib/ronin/formatting/http.rb +5 -5
  52. data/lib/ronin/formatting/sql.rb +5 -5
  53. data/lib/ronin/formatting/text.rb +5 -5
  54. data/lib/ronin/fuzzing.rb +5 -5
  55. data/lib/ronin/fuzzing/extensions.rb +5 -5
  56. data/lib/ronin/fuzzing/extensions/string.rb +42 -213
  57. data/lib/ronin/fuzzing/fuzzer.rb +110 -0
  58. data/lib/ronin/fuzzing/fuzzing.rb +33 -26
  59. data/lib/ronin/fuzzing/mutator.rb +161 -0
  60. data/lib/ronin/fuzzing/repeater.rb +81 -0
  61. data/lib/ronin/fuzzing/template.rb +133 -0
  62. data/lib/ronin/mixin.rb +2 -2
  63. data/lib/ronin/network.rb +7 -5
  64. data/lib/ronin/network/dns.rb +64 -24
  65. data/lib/ronin/network/esmtp.rb +5 -5
  66. data/lib/ronin/network/extensions.rb +5 -5
  67. data/lib/ronin/network/extensions/dns.rb +5 -5
  68. data/lib/ronin/network/extensions/dns/net.rb +5 -5
  69. data/lib/ronin/network/extensions/esmtp.rb +5 -5
  70. data/lib/ronin/network/extensions/esmtp/net.rb +5 -5
  71. data/lib/ronin/network/extensions/http.rb +5 -5
  72. data/lib/ronin/network/extensions/http/net.rb +5 -5
  73. data/lib/ronin/network/extensions/http/uri/http.rb +5 -5
  74. data/lib/ronin/network/extensions/imap.rb +5 -5
  75. data/lib/ronin/network/extensions/imap/net.rb +5 -5
  76. data/lib/ronin/network/extensions/pop3.rb +5 -5
  77. data/lib/ronin/network/extensions/pop3/net.rb +5 -5
  78. data/lib/ronin/network/extensions/smtp.rb +5 -5
  79. data/lib/ronin/network/extensions/smtp/net.rb +5 -5
  80. data/lib/ronin/network/extensions/ssl.rb +5 -5
  81. data/lib/ronin/network/extensions/ssl/net.rb +5 -5
  82. data/lib/ronin/network/extensions/tcp.rb +5 -5
  83. data/lib/ronin/network/extensions/tcp/net.rb +5 -5
  84. data/lib/ronin/network/extensions/telnet.rb +5 -5
  85. data/lib/ronin/network/extensions/telnet/net.rb +5 -5
  86. data/lib/ronin/network/extensions/udp.rb +5 -5
  87. data/lib/ronin/network/extensions/udp/net.rb +5 -5
  88. data/lib/ronin/network/ftp.rb +149 -0
  89. data/lib/ronin/network/http.rb +5 -5
  90. data/lib/ronin/network/http/exceptions.rb +5 -5
  91. data/lib/ronin/network/http/exceptions/unknown_request.rb +5 -5
  92. data/lib/ronin/network/http/http.rb +65 -70
  93. data/lib/ronin/network/http/proxy.rb +5 -5
  94. data/lib/ronin/network/imap.rb +16 -15
  95. data/lib/ronin/network/mixins.rb +6 -5
  96. data/lib/ronin/network/mixins/dns.rb +5 -5
  97. data/lib/ronin/network/mixins/esmtp.rb +5 -5
  98. data/lib/ronin/network/mixins/ftp.rb +155 -0
  99. data/lib/ronin/network/mixins/http.rb +58 -587
  100. data/lib/ronin/network/mixins/imap.rb +5 -5
  101. data/lib/ronin/network/mixins/mixin.rb +5 -5
  102. data/lib/ronin/network/mixins/pop3.rb +5 -5
  103. data/lib/ronin/network/mixins/smtp.rb +5 -5
  104. data/lib/ronin/network/mixins/ssl.rb +5 -5
  105. data/lib/ronin/network/mixins/tcp.rb +43 -10
  106. data/lib/ronin/network/mixins/telnet.rb +5 -5
  107. data/lib/ronin/network/mixins/udp.rb +126 -6
  108. data/lib/ronin/network/mixins/unix.rb +279 -0
  109. data/lib/ronin/network/network.rb +5 -5
  110. data/lib/ronin/network/pop3.rb +10 -10
  111. data/lib/ronin/network/proxy.rb +578 -0
  112. data/lib/ronin/network/smtp.rb +5 -5
  113. data/lib/ronin/network/smtp/email.rb +6 -6
  114. data/lib/ronin/network/smtp/smtp.rb +12 -13
  115. data/lib/ronin/network/ssl.rb +16 -17
  116. data/lib/ronin/network/tcp.rb +7 -310
  117. data/lib/ronin/network/tcp/proxy.rb +417 -0
  118. data/lib/ronin/network/tcp/tcp.rb +452 -0
  119. data/lib/ronin/network/telnet.rb +34 -28
  120. data/lib/ronin/network/udp.rb +7 -271
  121. data/lib/ronin/network/udp/proxy.rb +191 -0
  122. data/lib/ronin/network/udp/udp.rb +452 -0
  123. data/lib/ronin/network/unix.rb +286 -0
  124. data/lib/ronin/path.rb +35 -39
  125. data/lib/ronin/spec/ui/output.rb +6 -12
  126. data/lib/ronin/support.rb +6 -5
  127. data/lib/ronin/support/inflector.rb +8 -12
  128. data/lib/ronin/support/support.rb +7 -5
  129. data/lib/ronin/support/version.rb +6 -6
  130. data/lib/ronin/templates.rb +5 -5
  131. data/lib/ronin/templates/erb.rb +5 -5
  132. data/lib/ronin/templates/template.rb +5 -5
  133. data/lib/ronin/ui/output.rb +5 -5
  134. data/lib/ronin/ui/output/helpers.rb +42 -28
  135. data/lib/ronin/ui/output/output.rb +17 -21
  136. data/lib/ronin/ui/output/terminal.rb +5 -5
  137. data/lib/ronin/ui/output/terminal/color.rb +15 -9
  138. data/lib/ronin/ui/output/terminal/raw.rb +5 -5
  139. data/lib/ronin/ui/shell.rb +8 -11
  140. data/lib/ronin/wordlist.rb +110 -30
  141. data/ronin-support.gemspec +39 -109
  142. data/spec/binary/hexdump/helpers/hexdumps.rb +13 -0
  143. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/ascii.bin +0 -0
  144. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_decimal_shorts.txt +0 -0
  145. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_bytes.txt +0 -0
  146. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_shorts.txt +0 -0
  147. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_bytes.txt +0 -0
  148. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_shorts.txt +0 -0
  149. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_repeated.txt +0 -0
  150. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_bytes.txt +0 -0
  151. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_ints.txt +0 -0
  152. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_quads.txt +0 -0
  153. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_shorts.txt +0 -0
  154. data/spec/binary/hexdump/helpers/hexdumps/od_doubles.txt +17 -0
  155. data/spec/binary/hexdump/helpers/hexdumps/od_floats.txt +17 -0
  156. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_bytes.txt +0 -0
  157. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_ints.txt +0 -0
  158. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_quads.txt +0 -0
  159. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_shorts.txt +0 -0
  160. data/spec/binary/hexdump/helpers/hexdumps/od_named_chars.txt +17 -0
  161. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_bytes.txt +0 -0
  162. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_ints.txt +0 -0
  163. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_quads.txt +0 -0
  164. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_shorts.txt +0 -0
  165. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_repeated.txt +0 -0
  166. data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/repeated.bin +0 -0
  167. data/spec/binary/hexdump/parser_spec.rb +302 -0
  168. data/spec/binary/struct_spec.rb +496 -0
  169. data/spec/binary/template_spec.rb +416 -0
  170. data/spec/extensions/enumerable_spec.rb +4 -4
  171. data/spec/extensions/file_spec.rb +12 -14
  172. data/spec/extensions/ip_addr_spec.rb +76 -50
  173. data/spec/extensions/kernel_spec.rb +7 -7
  174. data/spec/extensions/regexp_spec.rb +119 -59
  175. data/spec/extensions/resolv_spec.rb +2 -2
  176. data/spec/extensions/string_spec.rb +31 -30
  177. data/spec/formatting/binary/array_spec.rb +26 -0
  178. data/spec/formatting/binary/base64_spec.rb +50 -0
  179. data/spec/formatting/binary/float_spec.rb +36 -0
  180. data/spec/formatting/binary/integer_spec.rb +76 -50
  181. data/spec/formatting/binary/string_spec.rb +91 -198
  182. data/spec/formatting/digest/string_spec.rb +5 -5
  183. data/spec/formatting/html/integer_spec.rb +6 -6
  184. data/spec/formatting/html/string_spec.rb +10 -10
  185. data/spec/formatting/http/integer_spec.rb +3 -3
  186. data/spec/formatting/http/string_spec.rb +5 -5
  187. data/spec/formatting/sql/string_spec.rb +21 -19
  188. data/spec/formatting/text/array_spec.rb +15 -15
  189. data/spec/formatting/text/string_spec.rb +58 -28
  190. data/spec/fuzzing/extensions/string_spec.rb +87 -0
  191. data/spec/fuzzing/fuzzer_spec.rb +109 -0
  192. data/spec/fuzzing/fuzzing_spec.rb +24 -0
  193. data/spec/fuzzing/mutator_spec.rb +112 -0
  194. data/spec/fuzzing/repeater_spec.rb +57 -0
  195. data/spec/fuzzing/template_spec.rb +54 -0
  196. data/spec/mixin_spec.rb +10 -12
  197. data/spec/network/dns_spec.rb +89 -23
  198. data/spec/network/ftp_spec.rb +81 -0
  199. data/spec/network/http/http_spec.rb +237 -144
  200. data/spec/network/http/proxy_spec.rb +37 -37
  201. data/spec/network/network_spec.rb +2 -2
  202. data/spec/network/proxy_spec.rb +121 -0
  203. data/spec/network/shared/unix_server.rb +31 -0
  204. data/spec/network/smtp/email_spec.rb +14 -14
  205. data/spec/network/ssl_spec.rb +53 -3
  206. data/spec/network/tcp/proxy_spec.rb +118 -0
  207. data/spec/network/tcp/tcp_spec.rb +316 -0
  208. data/spec/network/telnet_spec.rb +67 -0
  209. data/spec/network/udp/udp_spec.rb +298 -0
  210. data/spec/network/unix_spec.rb +182 -0
  211. data/spec/path_spec.rb +43 -18
  212. data/spec/spec_helper.rb +2 -3
  213. data/spec/support/inflector_spec.rb +4 -4
  214. data/spec/support_spec.rb +1 -1
  215. data/spec/templates/erb_spec.rb +3 -3
  216. data/spec/templates/template_spec.rb +10 -10
  217. data/spec/ui/shell_spec.rb +15 -15
  218. data/spec/wordlist_spec.rb +80 -19
  219. metadata +176 -121
  220. data/.gemtest +0 -0
  221. data/spec/formatting/binary/helpers/hexdumps.rb +0 -16
  222. data/spec/fuzzing/string_spec.rb +0 -158
  223. data/spec/network/tcp_spec.rb +0 -247
  224. data/spec/network/udp_spec.rb +0 -248
@@ -0,0 +1,110 @@
1
+ #
2
+ # Copyright (c) 2006-2021 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of ronin-support.
5
+ #
6
+ # ronin-support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # ronin-support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/fuzzing/fuzzing'
21
+ require 'ronin/extensions/regexp'
22
+
23
+ require 'strscan'
24
+
25
+ module Ronin
26
+ module Fuzzing
27
+ #
28
+ # Fuzzing class that incrementally fuzzes a String, given substitution
29
+ # rules.
30
+ #
31
+ # @api semipublic
32
+ #
33
+ # @since 0.5.0
34
+ #
35
+ class Fuzzer
36
+
37
+ # Patterns and their substitutions
38
+ attr_reader :rules
39
+
40
+ #
41
+ # Initializes a new Fuzzer.
42
+ #
43
+ # @param [Hash{Regexp,String,Symbol => Enumerable,Symbol}] rules
44
+ # Patterns and their substitutions.
45
+ #
46
+ def initialize(rules)
47
+ @rules = {}
48
+
49
+ rules.each do |pattern,substitution|
50
+ pattern = case pattern
51
+ when Regexp then pattern
52
+ when String then Regexp.new(Regexp.escape(pattern))
53
+ when Symbol then Regexp.const_get(pattern.to_s.upcase)
54
+ else
55
+ raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp")
56
+ end
57
+
58
+ substitution = case substitution
59
+ when Enumerable then substitution
60
+ when Symbol then Fuzzing[substitution]
61
+ else
62
+ raise(TypeError,"substitutions must be Enumerable or a Symbol")
63
+ end
64
+
65
+ @rules[pattern] = substitution
66
+ end
67
+ end
68
+
69
+ #
70
+ # Incrementally fuzzes the String.
71
+ #
72
+ # @yield [fuzz]
73
+ # The given block will be passed every fuzzed String.
74
+ #
75
+ # @yieldparam [String] fuzz
76
+ # A fuzzed String.
77
+ #
78
+ # @return [Enumerator]
79
+ # If no block is given, an Enumerator will be returned.
80
+ #
81
+ def each(string)
82
+ return enum_for(__method__,string) unless block_given?
83
+
84
+ @rules.each do |pattern,substitution|
85
+ scanner = StringScanner.new(string)
86
+ indices = []
87
+
88
+ while scanner.scan_until(pattern)
89
+ indices << [scanner.pos - scanner.matched_size, scanner.matched_size]
90
+ end
91
+
92
+ indices.each do |index,length|
93
+ substitution.each do |substitute|
94
+ substitute = case substitute
95
+ when Proc then substitute[string[index,length]]
96
+ when Integer then substitute.chr
97
+ else substitute.to_s
98
+ end
99
+
100
+ fuzzed = string.dup
101
+ fuzzed[index,length] = substitute
102
+ yield fuzzed
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -1,20 +1,20 @@
1
1
  #
2
- # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
2
+ # Copyright (c) 2006-2021 Hal Brodigan (postmodern.mod3 at gmail.com)
3
3
  #
4
- # This file is part of Ronin Support.
4
+ # This file is part of ronin-support.
5
5
  #
6
- # Ronin Support is free software: you can redistribute it and/or modify
6
+ # ronin-support is free software: you can redistribute it and/or modify
7
7
  # it under the terms of the GNU Lesser General Public License as published
8
8
  # by the Free Software Foundation, either version 3 of the License, or
9
9
  # (at your option) any later version.
10
10
  #
11
- # Ronin Support is distributed in the hope that it will be useful,
11
+ # ronin-support is distributed in the hope that it will be useful,
12
12
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
13
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
  # GNU Lesser General Public License for more details.
15
15
  #
16
16
  # You should have received a copy of the GNU Lesser General Public License
17
- # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
17
+ # along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
20
  require 'set'
@@ -29,10 +29,10 @@ module Ronin
29
29
  #
30
30
  module Fuzzing
31
31
  # Short String lengths
32
- SHORT_LENGTHS = SortedSet[1, 100, 500, 1_000, 10_000]
32
+ SHORT_LENGTHS = Set[1, 100, 500, 1_000, 10_000]
33
33
 
34
34
  # Long String lengths
35
- LONG_LENGTHS = SortedSet[
35
+ LONG_LENGTHS = Set[
36
36
  128, 255, 256, 257, 511, 512, 513, 1023, 1024, 2048, 2049, 4095,
37
37
  4096, 4097, 5_000, 10_000, 20_000, 32762, 32763, 32764, 32765, 32766,
38
38
  32767, 32768, 32769,
@@ -58,14 +58,21 @@ module Ronin
58
58
  # @return [Enumerator]
59
59
  # An Enumerator for the fuzzer method.
60
60
  #
61
+ # @raise [NoMethodError]
62
+ # The fuzzing method could not be found.
63
+ #
61
64
  # @api semipublic
62
65
  #
63
66
  def self.[](name)
64
- if (!Object.respond_to?(name) && respond_to?(name))
65
- enum_for(name)
67
+ if (!respond_to?(name) || Module.respond_to?(name))
68
+ raise(NoMethodError,"no such fuzzing method: #{name}")
66
69
  end
70
+
71
+ return enum_for(name)
67
72
  end
68
73
 
74
+ module_function
75
+
69
76
  #
70
77
  # Various bad-strings.
71
78
  #
@@ -77,7 +84,7 @@ module Ronin
77
84
  # or null-bytes (see {NULL_BYTES}), of varying length
78
85
  # (see {SHORT_LENGTHS} and {LONG_LENGTHS}).
79
86
  #
80
- def self.bad_strings(&block)
87
+ def bad_strings(&block)
81
88
  yield ''
82
89
 
83
90
  chars = [
@@ -118,7 +125,7 @@ module Ronin
118
125
  # @yieldparam [String] fmt_string
119
126
  # A format-string containing format operators (see {FORMAT_STRINGS}).
120
127
  #
121
- def self.format_strings(&block)
128
+ def format_strings(&block)
122
129
  FORMAT_STRINGS.each do |fmt|
123
130
  yield fmt
124
131
  yield fmt * 100
@@ -136,7 +143,7 @@ module Ronin
136
143
  # @yieldparam [String] path
137
144
  # A known bad path.
138
145
  #
139
- def self.bad_paths(&block)
146
+ def bad_paths(&block)
140
147
  padding = 'A' * 5_000
141
148
 
142
149
  yield "/.:/#{padding}\x00\x00"
@@ -166,7 +173,7 @@ module Ronin
166
173
  # @yieldparam [String] bitfield
167
174
  # A bit-field (8bit - 64bit).
168
175
  #
169
- def self.bit_fields(&block)
176
+ def bit_fields(&block)
170
177
  ("\x00".."\xff").each do |c|
171
178
  yield c
172
179
  yield c << c # x2
@@ -184,7 +191,7 @@ module Ronin
184
191
  # @yieldparam [String] bitfield
185
192
  # A signed bit-field (8bit - 64bit).
186
193
  #
187
- def self.signed_bit_fields(&block)
194
+ def signed_bit_fields(&block)
188
195
  ("\x80".."\xff").each do |c|
189
196
  yield c
190
197
  yield c << c # x2
@@ -202,7 +209,7 @@ module Ronin
202
209
  # @yieldparam [String] int
203
210
  # A unsigned 8bit integer.
204
211
  #
205
- def self.uint8(&block)
212
+ def uint8(&block)
206
213
  ("\x00".."\xff").each(&block)
207
214
  end
208
215
 
@@ -215,7 +222,7 @@ module Ronin
215
222
  # @yieldparam [String] int
216
223
  # A unsigned 16bit integer.
217
224
  #
218
- def self.uint16
225
+ def uint16
219
226
  uint8 { |c| yield c * 2 }
220
227
  end
221
228
 
@@ -228,7 +235,7 @@ module Ronin
228
235
  # @yieldparam [String] int
229
236
  # A unsigned 32bit integer.
230
237
  #
231
- def self.uint32
238
+ def uint32
232
239
  uint8 { |c| yield c * 4 }
233
240
  end
234
241
 
@@ -241,7 +248,7 @@ module Ronin
241
248
  # @yieldparam [String] int
242
249
  # A unsigned 64bit integer.
243
250
  #
244
- def self.uint64
251
+ def uint64
245
252
  uint8 { |c| yield c * 8 }
246
253
  end
247
254
 
@@ -254,7 +261,7 @@ module Ronin
254
261
  # @yieldparam [String] int
255
262
  # A signed 8bit integer.
256
263
  #
257
- def self.int8(&block)
264
+ def int8(&block)
258
265
  ("\x00".."\x70").each(&block)
259
266
  end
260
267
 
@@ -267,7 +274,7 @@ module Ronin
267
274
  # @yieldparam [String] int
268
275
  # A signed 16bit integer.
269
276
  #
270
- def self.int16
277
+ def int16
271
278
  int8 { |c| yield c * 2 }
272
279
  end
273
280
 
@@ -280,7 +287,7 @@ module Ronin
280
287
  # @yieldparam [String] int
281
288
  # A signed 32bit integer.
282
289
  #
283
- def self.int32
290
+ def int32
284
291
  int8 { |c| yield c * 4 }
285
292
  end
286
293
 
@@ -293,7 +300,7 @@ module Ronin
293
300
  # @yieldparam [String] int
294
301
  # A signed 64bit integer.
295
302
  #
296
- def self.int64
303
+ def int64
297
304
  int8 { |c| yield c * 8 }
298
305
  end
299
306
 
@@ -306,7 +313,7 @@ module Ronin
306
313
  # @yieldparam [String] int
307
314
  # A negative-signed 8bit integer.
308
315
  #
309
- def self.sint8(&block)
316
+ def sint8(&block)
310
317
  ("\x80".."\xff").each(&block)
311
318
  end
312
319
 
@@ -319,7 +326,7 @@ module Ronin
319
326
  # @yieldparam [String] int
320
327
  # A negative-signed 16bit integer.
321
328
  #
322
- def self.sint16
329
+ def sint16
323
330
  sint8 { |c| yield c * 2 }
324
331
  end
325
332
 
@@ -332,7 +339,7 @@ module Ronin
332
339
  # @yieldparam [String] int
333
340
  # A negative-signed 32bit integer.
334
341
  #
335
- def self.sint32
342
+ def sint32
336
343
  sint8 { |c| yield c * 4 }
337
344
  end
338
345
 
@@ -345,7 +352,7 @@ module Ronin
345
352
  # @yieldparam [String] int
346
353
  # A negative-signed 64bit integer.
347
354
  #
348
- def self.sint64
355
+ def sint64
349
356
  sint8 { |c| yield c * 8 }
350
357
  end
351
358
 
@@ -0,0 +1,161 @@
1
+ #
2
+ # Copyright (c) 2006-2021 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of ronin-support.
5
+ #
6
+ # ronin-support is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # ronin-support is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/fuzzing/fuzzing'
21
+ require 'ronin/extensions/regexp'
22
+
23
+ require 'combinatorics/list_comprehension'
24
+ require 'combinatorics/power_set'
25
+ require 'combinatorics/generator'
26
+ require 'strscan'
27
+ require 'set'
28
+
29
+ module Ronin
30
+ module Fuzzing
31
+ #
32
+ # Fuzzer class that permutates over every mutation of a String, given
33
+ # mutation rules.
34
+ #
35
+ # @api semipublic
36
+ #
37
+ # @since 0.5.0
38
+ #
39
+ class Mutator
40
+
41
+ # Mutation rules
42
+ attr_reader :rules
43
+
44
+ #
45
+ # Initialize the Mutator.
46
+ #
47
+ # @param [Hash{Regexp,String,Symbol => Symbol,Enumerable}] rules
48
+ # The patterns and substitutions to mutate the String with.
49
+ #
50
+ # @raise [TypeError]
51
+ # A mutation pattern was not a Regexp, String or Symbol.
52
+ # A mutation substitution was not a Symbol or Enumerable.
53
+ #
54
+ def initialize(rules)
55
+ @rules = {}
56
+
57
+ rules.each do |pattern,mutation|
58
+ pattern = case pattern
59
+ when Regexp
60
+ pattern
61
+ when String
62
+ Regexp.new(Regexp.escape(pattern))
63
+ when Symbol
64
+ Regexp.const_get(pattern.to_s.upcase)
65
+ else
66
+ raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp")
67
+ end
68
+
69
+ mutation = case mutation
70
+ when Enumerable
71
+ mutation
72
+ when Symbol
73
+ Ronin::Fuzzing[mutation]
74
+ else
75
+ raise(TypeError,"mutation #{mutation.inspect} must be a Symbol or Enumerable")
76
+ end
77
+
78
+ @rules[pattern] = mutation
79
+ end
80
+ end
81
+
82
+ #
83
+ # Permutes over every possible mutation of the String.
84
+ #
85
+ # @param [String] string
86
+ # The String to be mutated.
87
+ #
88
+ # @yield [mutant]
89
+ # The given block will be yielded every possible mutant String.
90
+ #
91
+ # @yieldparam [String] mutant
92
+ # A mutated String.
93
+ #
94
+ # @return [Enumerator]
95
+ # If no block is given, an Enumerator will be returned.
96
+ #
97
+ def each(string)
98
+ return enum_for(__method__,string) unless block_given?
99
+
100
+ matches = Set[]
101
+
102
+ @rules.each do |pattern,mutation|
103
+ scanner = StringScanner.new(string)
104
+
105
+ while scanner.scan_until(pattern)
106
+ length = scanner.matched_size
107
+ index = scanner.pos - length
108
+ original = scanner.matched
109
+
110
+ mutator = Combinatorics::Generator.new do |g|
111
+ mutation.each do |mutate|
112
+ g.yield case mutate
113
+ when Proc
114
+ mutate.call(original)
115
+ when Integer
116
+ mutate.chr
117
+ else
118
+ mutate.to_s
119
+ end
120
+ end
121
+ end
122
+
123
+ matches << [index, length, mutator]
124
+ end
125
+ end
126
+
127
+ matches.powerset do |submatches|
128
+ # ignore the empty Set
129
+ next if submatches.empty?
130
+
131
+ # sort the submatches by index
132
+ submatches = submatches.sort_by { |index,length,mutator| index }
133
+ sets = []
134
+ prev_index = 0
135
+
136
+ submatches.each do |index,length,mutator|
137
+ # add the previous substring to the set of Strings
138
+ if index > prev_index
139
+ sets << [string[prev_index,index - prev_index]]
140
+ end
141
+
142
+ # add the mutator to the set of Strings
143
+ sets << mutator
144
+
145
+ prev_index = index + length
146
+ end
147
+
148
+ # add the remaining substring to the set of Strings
149
+ if prev_index < string.length
150
+ sets << [string[prev_index..-1]]
151
+ end
152
+
153
+ sets.comprehension { |strings| yield strings.join }
154
+ end
155
+
156
+ return nil
157
+ end
158
+
159
+ end
160
+ end
161
+ end