ronin-support 1.0.0.beta3 → 1.0.1

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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +14 -0
  3. data/.rubocop.yml +109 -0
  4. data/ChangeLog.md +12 -1
  5. data/Gemfile +8 -4
  6. data/README.md +1 -1
  7. data/Rakefile +2 -2
  8. data/examples/ssl_proxy.rb +2 -1
  9. data/examples/tcp_proxy.rb +6 -4
  10. data/lib/ronin/support/archive/tar/writer.rb +2 -2
  11. data/lib/ronin/support/archive/tar.rb +4 -4
  12. data/lib/ronin/support/archive/zip/reader.rb +2 -2
  13. data/lib/ronin/support/binary/array.rb +4 -7
  14. data/lib/ronin/support/binary/bit_flip.rb +7 -1
  15. data/lib/ronin/support/binary/buffer.rb +22 -22
  16. data/lib/ronin/support/binary/byte_slice.rb +17 -17
  17. data/lib/ronin/support/binary/cstring.rb +7 -4
  18. data/lib/ronin/support/binary/ctypes/arch/arm/big_endian.rb +4 -0
  19. data/lib/ronin/support/binary/ctypes/arch/arm.rb +3 -0
  20. data/lib/ronin/support/binary/ctypes/arch/arm64/big_endian.rb +4 -0
  21. data/lib/ronin/support/binary/ctypes/arch/arm64.rb +3 -0
  22. data/lib/ronin/support/binary/ctypes/arch/mips/little_endian.rb +4 -0
  23. data/lib/ronin/support/binary/ctypes/arch/mips.rb +3 -0
  24. data/lib/ronin/support/binary/ctypes/arch/mips64/little_endian.rb +4 -0
  25. data/lib/ronin/support/binary/ctypes/arch/mips64.rb +3 -0
  26. data/lib/ronin/support/binary/ctypes/arch/ppc.rb +3 -0
  27. data/lib/ronin/support/binary/ctypes/arch/ppc64.rb +3 -0
  28. data/lib/ronin/support/binary/ctypes/arch/x86.rb +3 -0
  29. data/lib/ronin/support/binary/ctypes/arch/x86_64.rb +3 -0
  30. data/lib/ronin/support/binary/ctypes/array_type.rb +1 -1
  31. data/lib/ronin/support/binary/ctypes/big_endian.rb +3 -0
  32. data/lib/ronin/support/binary/ctypes/enum_type.rb +2 -2
  33. data/lib/ronin/support/binary/ctypes/little_endian.rb +3 -0
  34. data/lib/ronin/support/binary/ctypes/native.rb +3 -0
  35. data/lib/ronin/support/binary/ctypes/scalar_type.rb +2 -2
  36. data/lib/ronin/support/binary/ctypes/struct_type.rb +3 -3
  37. data/lib/ronin/support/binary/ctypes/type_resolver.rb +7 -8
  38. data/lib/ronin/support/binary/ctypes/unbounded_array_type.rb +1 -1
  39. data/lib/ronin/support/binary/ctypes/union_type.rb +3 -3
  40. data/lib/ronin/support/binary/ctypes.rb +3 -3
  41. data/lib/ronin/support/binary/memory.rb +2 -2
  42. data/lib/ronin/support/binary/packet.rb +3 -0
  43. data/lib/ronin/support/binary/stack.rb +3 -4
  44. data/lib/ronin/support/binary/struct/member.rb +5 -3
  45. data/lib/ronin/support/binary/struct.rb +81 -79
  46. data/lib/ronin/support/binary/template.rb +1 -0
  47. data/lib/ronin/support/binary/unhexdump/parser.rb +11 -11
  48. data/lib/ronin/support/binary/union.rb +22 -22
  49. data/lib/ronin/support/cli/ansi.rb +0 -1
  50. data/lib/ronin/support/cli/io_shell/core_ext/io.rb +1 -1
  51. data/lib/ronin/support/cli/io_shell.rb +4 -4
  52. data/lib/ronin/support/cli/printing.rb +3 -3
  53. data/lib/ronin/support/compression/zlib.rb +1 -1
  54. data/lib/ronin/support/core_ext/enumerable.rb +0 -2
  55. data/lib/ronin/support/core_ext/file.rb +1 -1
  56. data/lib/ronin/support/core_ext/kernel.rb +6 -5
  57. data/lib/ronin/support/core_ext/string.rb +2 -2
  58. data/lib/ronin/support/crypto/cert.rb +11 -15
  59. data/lib/ronin/support/crypto/cert_chain.rb +1 -1
  60. data/lib/ronin/support/crypto/cipher/aes.rb +3 -0
  61. data/lib/ronin/support/crypto/cipher/aes128.rb +4 -1
  62. data/lib/ronin/support/crypto/cipher/aes256.rb +4 -1
  63. data/lib/ronin/support/crypto/cipher.rb +1 -1
  64. data/lib/ronin/support/crypto/core_ext/file.rb +1 -1
  65. data/lib/ronin/support/crypto/key/methods.rb +4 -1
  66. data/lib/ronin/support/crypto/key.rb +5 -2
  67. data/lib/ronin/support/crypto/openssl.rb +1 -1
  68. data/lib/ronin/support/crypto.rb +0 -1
  69. data/lib/ronin/support/encoding/base16.rb +1 -1
  70. data/lib/ronin/support/encoding/base32.rb +28 -17
  71. data/lib/ronin/support/encoding/c/core_ext/integer.rb +1 -1
  72. data/lib/ronin/support/encoding/c.rb +4 -4
  73. data/lib/ronin/support/encoding/hex.rb +2 -2
  74. data/lib/ronin/support/encoding/js/core_ext/integer.rb +1 -1
  75. data/lib/ronin/support/encoding/js.rb +4 -4
  76. data/lib/ronin/support/encoding/powershell/core_ext/integer.rb +2 -2
  77. data/lib/ronin/support/encoding/powershell.rb +4 -5
  78. data/lib/ronin/support/encoding/ruby.rb +4 -4
  79. data/lib/ronin/support/encoding/shell/core_ext/integer.rb +2 -2
  80. data/lib/ronin/support/encoding/shell.rb +3 -3
  81. data/lib/ronin/support/encoding/sql.rb +1 -1
  82. data/lib/ronin/support/encoding/xml.rb +2 -2
  83. data/lib/ronin/support/encoding.rb +95 -0
  84. data/lib/ronin/support/network/asn/list.rb +6 -1
  85. data/lib/ronin/support/network/asn/record.rb +3 -0
  86. data/lib/ronin/support/network/asn/record_set.rb +3 -0
  87. data/lib/ronin/support/network/asn.rb +167 -6
  88. data/lib/ronin/support/network/dns/resolver.rb +3 -0
  89. data/lib/ronin/support/network/domain.rb +21 -21
  90. data/lib/ronin/support/network/email_address.rb +1 -5
  91. data/lib/ronin/support/network/esmtp/mixin.rb +1 -0
  92. data/lib/ronin/support/network/ftp/mixin.rb +1 -1
  93. data/lib/ronin/support/network/host.rb +75 -47
  94. data/lib/ronin/support/network/http/core_ext.rb +1 -1
  95. data/lib/ronin/support/network/http.rb +317 -80
  96. data/lib/ronin/support/network/ip.rb +8 -10
  97. data/lib/ronin/support/network/ip_range/cidr.rb +1 -5
  98. data/lib/ronin/support/network/ip_range/glob.rb +1 -0
  99. data/lib/ronin/support/network/ip_range/range.rb +1 -1
  100. data/lib/ronin/support/network/ip_range.rb +1 -3
  101. data/lib/ronin/support/network/proxy.rb +4 -4
  102. data/lib/ronin/support/network/public_suffix/list.rb +10 -8
  103. data/lib/ronin/support/network/public_suffix/suffix_set.rb +3 -0
  104. data/lib/ronin/support/network/public_suffix.rb +9 -4
  105. data/lib/ronin/support/network/smtp/email.rb +0 -9
  106. data/lib/ronin/support/network/smtp/mixin.rb +2 -2
  107. data/lib/ronin/support/network/ssl/local_cert.rb +1 -3
  108. data/lib/ronin/support/network/ssl/mixin.rb +13 -13
  109. data/lib/ronin/support/network/ssl/openssl.rb +1 -1
  110. data/lib/ronin/support/network/ssl/proxy.rb +14 -16
  111. data/lib/ronin/support/network/ssl.rb +4 -2
  112. data/lib/ronin/support/network/tcp/proxy.rb +3 -3
  113. data/lib/ronin/support/network/tcp.rb +10 -12
  114. data/lib/ronin/support/network/telnet/mixin.rb +14 -14
  115. data/lib/ronin/support/network/tld/list.rb +2 -1
  116. data/lib/ronin/support/network/tld.rb +7 -4
  117. data/lib/ronin/support/network/tls/proxy.rb +1 -1
  118. data/lib/ronin/support/network/tls.rb +0 -2
  119. data/lib/ronin/support/network/udp/proxy.rb +5 -5
  120. data/lib/ronin/support/network/udp.rb +14 -16
  121. data/lib/ronin/support/path.rb +3 -3
  122. data/lib/ronin/support/text/erb/mixin.rb +3 -0
  123. data/lib/ronin/support/text/homoglyph/table.rb +3 -3
  124. data/lib/ronin/support/text/patterns/credentials.rb +2 -2
  125. data/lib/ronin/support/text/patterns/crypto.rb +1 -1
  126. data/lib/ronin/support/text/patterns/file_system.rb +3 -4
  127. data/lib/ronin/support/text/patterns/network.rb +10 -10
  128. data/lib/ronin/support/text/patterns/numeric.rb +1 -1
  129. data/lib/ronin/support/text/patterns/source_code.rb +2 -2
  130. data/lib/ronin/support/text/random.rb +2 -2
  131. data/lib/ronin/support/text/typo/generator.rb +2 -2
  132. data/lib/ronin/support/version.rb +1 -1
  133. data/ronin-support.gemspec +6 -5
  134. metadata +3 -2
@@ -27,7 +27,7 @@ module Ronin
27
27
  # @since 1.0.0
28
28
  #
29
29
  module Printing
30
- @@debug = false
30
+ @debug = false
31
31
 
32
32
  #
33
33
  # The current debug mode.
@@ -38,7 +38,7 @@ module Ronin
38
38
  # @api semipublic
39
39
  #
40
40
  def self.debug?
41
- @@debug
41
+ @debug
42
42
  end
43
43
 
44
44
  #
@@ -53,7 +53,7 @@ module Ronin
53
53
  # @api semipublic
54
54
  #
55
55
  def self.debug=(debug_mode)
56
- @@debug = debug_mode
56
+ @debug = debug_mode
57
57
  end
58
58
 
59
59
  # Enables or disables debug mode.
@@ -18,7 +18,7 @@
18
18
 
19
19
  begin
20
20
  require 'zlib'
21
- rescue ::LoadError
21
+ rescue LoadError
22
22
  warn "WARNING: Ruby was not compiled with zlib support"
23
23
  end
24
24
 
@@ -17,7 +17,6 @@
17
17
  #
18
18
 
19
19
  module Enumerable
20
-
21
20
  #
22
21
  # Maps the elements to a Hash.
23
22
  #
@@ -49,5 +48,4 @@ module Enumerable
49
48
  each { |element| new_hash[element] }
50
49
  return new_hash
51
50
  end
52
-
53
51
  end
@@ -104,7 +104,7 @@ class File
104
104
  path = expand_path(File.join('/',path))
105
105
 
106
106
  # remove the leading slash
107
- return path[1..-1]
107
+ return path[1..]
108
108
  end
109
109
 
110
110
  end
@@ -39,10 +39,11 @@ module Kernel
39
39
  # @api public
40
40
  #
41
41
  def try
42
- begin
43
- yield() if block_given?
44
- rescue Exception
45
- return nil
46
- end
42
+ yield() if block_given?
43
+ rescue SyntaxError => error
44
+ # re-raise syntax errors
45
+ raise(error)
46
+ rescue StandardError
47
+ # ignore any exceptions
47
48
  end
48
49
  end
@@ -199,7 +199,7 @@ class String
199
199
  other_index = (other.length - i - 1)
200
200
 
201
201
  if self[index] != other[other_index]
202
- return self[(index + 1)..-1]
202
+ return self[(index + 1)..]
203
203
  end
204
204
  end
205
205
 
@@ -220,7 +220,7 @@ class String
220
220
  #
221
221
  def uncommon_substring(other)
222
222
  prefix = common_prefix(other)
223
- postfix = self[prefix.length..-1].common_suffix(other[prefix.length..-1])
223
+ postfix = self[prefix.length..].common_suffix(other[prefix.length..])
224
224
 
225
225
  return self[prefix.length...(length - postfix.length)]
226
226
  end
@@ -66,7 +66,7 @@ module Ronin
66
66
  # The populated name.
67
67
  #
68
68
  def self.build(common_name: nil, organizational_unit: nil, organization: nil, locality: nil, state: nil, province: nil, country: nil)
69
- name = new()
69
+ name = new
70
70
  name.add_entry("CN",common_name) if common_name
71
71
  name.add_entry("OU",organizational_unit) if organizational_unit
72
72
  name.add_entry("O",organization) if organization
@@ -83,9 +83,7 @@ module Ronin
83
83
  # @return [Hash{String => String}]
84
84
  #
85
85
  def entries
86
- @entries ||= Hash[to_a.map { |(oid,value,type)|
87
- [oid, value]
88
- }]
86
+ @entries ||= to_a.to_h { |(oid,value,type)| [oid, value] }
89
87
  end
90
88
 
91
89
  alias to_h entries
@@ -328,7 +326,7 @@ module Ronin
328
326
  def self.generate(version: 2,
329
327
  serial: 0,
330
328
  not_before: Time.now,
331
- not_after: not_before+ONE_YEAR,
329
+ not_after: not_before + ONE_YEAR,
332
330
  subject: nil,
333
331
  extensions: nil,
334
332
  # signing arguments
@@ -336,9 +334,10 @@ module Ronin
336
334
  ca_cert: nil,
337
335
  ca_key: nil,
338
336
  signing_hash: :sha256)
339
- cert = new()
337
+ cert = new
338
+
340
339
  cert.version = version
341
- cert.serial = if ca_cert then ca_cert.serial+1
340
+ cert.serial = if ca_cert then ca_cert.serial + 1
342
341
  else serial
343
342
  end
344
343
 
@@ -351,11 +350,10 @@ module Ronin
351
350
  end
352
351
 
353
352
  if extensions
354
- extension_factory = OpenSSL::X509::ExtensionFactory.new()
353
+ extension_factory = OpenSSL::X509::ExtensionFactory.new
354
+
355
355
  extension_factory.subject_certificate = cert
356
- extension_factory.issuer_certificate = if ca_cert then ca_cert
357
- else cert
358
- end
356
+ extension_factory.issuer_certificate = ca_cert || cert
359
357
 
360
358
  extensions.each do |name,(value,critical)|
361
359
  ext = extension_factory.create_extension(name,value,critical)
@@ -363,9 +361,7 @@ module Ronin
363
361
  end
364
362
  end
365
363
 
366
- signing_key = if ca_key then ca_key
367
- else key
368
- end
364
+ signing_key = ca_key || key
369
365
  signing_digest = OpenSSL::Digest.const_get(signing_hash.upcase).new
370
366
 
371
367
  cert.sign(signing_key,signing_digest)
@@ -421,7 +417,7 @@ module Ronin
421
417
  # The Hash of extension OID names and extension objects.
422
418
  #
423
419
  def extensions_hash
424
- Hash[extensions.map { |ext| [ext.oid, ext] }]
420
+ extensions.to_h { |ext| [ext.oid, ext] }
425
421
  end
426
422
 
427
423
  #
@@ -59,7 +59,7 @@ module Ronin
59
59
  #
60
60
  def self.parse(string)
61
61
  cert_buffer = String.new
62
- certs = []
62
+ certs = []
63
63
 
64
64
  string.each_line do |line|
65
65
  cert_buffer << line
@@ -22,6 +22,9 @@ module Ronin
22
22
  module Support
23
23
  module Crypto
24
24
  class Cipher < OpenSSL::Cipher
25
+ #
26
+ # The AES cipher.
27
+ #
25
28
  class AES < Cipher
26
29
 
27
30
  # The AES cipher key size.
@@ -22,6 +22,9 @@ module Ronin
22
22
  module Support
23
23
  module Crypto
24
24
  class Cipher < OpenSSL::Cipher
25
+ #
26
+ # The AES128 cipher.
27
+ #
25
28
  class AES128 < AES
26
29
 
27
30
  #
@@ -44,7 +47,7 @@ module Ronin
44
47
  # The list of supported AES 128bit cipher names.
45
48
  #
46
49
  def self.supported
47
- super().grep(/^aes[-]?128/)
50
+ super().grep(/^aes(?:-)?128/)
48
51
  end
49
52
 
50
53
  end
@@ -22,6 +22,9 @@ module Ronin
22
22
  module Support
23
23
  module Crypto
24
24
  class Cipher < OpenSSL::Cipher
25
+ #
26
+ # The AES256 cipher.
27
+ #
25
28
  class AES256 < AES
26
29
 
27
30
  #
@@ -44,7 +47,7 @@ module Ronin
44
47
  # The list of supported AES 256bit cipher names.
45
48
  #
46
49
  def self.supported
47
- super().grep(/^aes[-]?256/)
50
+ super().grep(/^aes(?:-)?256/)
48
51
  end
49
52
 
50
53
  end
@@ -43,7 +43,7 @@ module Ronin
43
43
  # @see https://rubydoc.info/stdlib/openssl/OpenSSL/Cipher.html
44
44
  #
45
45
  # @since 1.0.0
46
- #
46
+ #
47
47
  # @api public
48
48
  #
49
49
  class Cipher < OpenSSL::Cipher
@@ -172,7 +172,7 @@ class File
172
172
  def self.hmac(path, key: , digest: :sha1)
173
173
  hmac = Ronin::Support::Crypto.hmac(key: key, digest: digest)
174
174
 
175
- open(path,'rb') do |file|
175
+ File.open(path,'rb') do |file|
176
176
  until file.eof?
177
177
  hmac.update(file.read(16384))
178
178
  end
@@ -40,6 +40,9 @@ module Ronin
40
40
  key_class.extend ClassMethods
41
41
  end
42
42
 
43
+ #
44
+ # Class-methods.
45
+ #
43
46
  module ClassMethods
44
47
  #
45
48
  # Generates a new random key.
@@ -151,7 +154,7 @@ module Ronin
151
154
  cipher = OpenSSL::Cipher.new(cipher)
152
155
  encoding_method.call(cipher,password)
153
156
  else
154
- encoding_method.call()
157
+ encoding_method.call
155
158
  end
156
159
 
157
160
  File.write(path,exported)
@@ -24,6 +24,9 @@ require 'ronin/support/crypto/key/rsa'
24
24
  module Ronin
25
25
  module Support
26
26
  module Crypto
27
+ #
28
+ # Top-level methods for working with public/private keys.
29
+ #
27
30
  module Key
28
31
  #
29
32
  # Parses an PEM encoded key.
@@ -42,7 +45,7 @@ module Ronin
42
45
  #
43
46
  # @raise [ArgumentError]
44
47
  # The key type could not be determined from the key file.
45
- #
48
+ #
46
49
  # @api public
47
50
  #
48
51
  def self.parse(key, password: nil)
@@ -93,7 +96,7 @@ module Ronin
93
96
  #
94
97
  # @raise [ArgumentError]
95
98
  # The key type could not be determined from the key file.
96
- #
99
+ #
97
100
  # @api public
98
101
  #
99
102
  def self.load_file(path)
@@ -18,6 +18,6 @@
18
18
 
19
19
  begin
20
20
  require 'openssl'
21
- rescue ::LoadError
21
+ rescue LoadError
22
22
  warn "WARNING: Ruby was not compiled with OpenSSL support"
23
23
  end
@@ -656,7 +656,6 @@ module Ronin
656
656
  when Key::RSA then key
657
657
  when OpenSSL::PKey::RSA then Key::RSA.new(key)
658
658
  when String then Key::RSA.load(key, password: password)
659
- else
660
659
  end
661
660
  else
662
661
  raise(ArgumentError,"either key: or key_file: keyword arguments must be given")
@@ -51,7 +51,7 @@ module Ronin
51
51
  encoded = String.new
52
52
 
53
53
  data.each_byte do |byte|
54
- encoded << "%.2x" % byte
54
+ encoded << ("%.2x" % byte)
55
55
  end
56
56
 
57
57
  return encoded
@@ -72,14 +72,16 @@ module Ronin
72
72
  return decoded
73
73
  end
74
74
 
75
- private
76
-
77
75
  # Base32 alphabet
76
+ #
77
+ # @api private
78
78
  TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
79
79
 
80
80
  #
81
81
  # Represents a chunk of data.
82
82
  #
83
+ # @api private
84
+ #
83
85
  class Chunk
84
86
 
85
87
  #
@@ -103,8 +105,13 @@ module Ronin
103
105
  #
104
106
  def decode(output=String.new)
105
107
  bytes = @bytes.take_while { |b| b != 61 } # strip padding
106
- n = (bytes.length * 5.0 / 8.0).floor
107
- p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
108
+
109
+ n = ((bytes.length * 5.0) / 8.0).floor
110
+ p = if bytes.length < 8
111
+ 5 - ((n * 8) % 5)
112
+ else
113
+ 0
114
+ end
108
115
  c = bytes.reduce(0) { |m,o|
109
116
  unless (i = Base32::TABLE.index(o.chr))
110
117
  raise ArgumentError, "invalid character '#{o.chr}'"
@@ -113,8 +120,8 @@ module Ronin
113
120
  (m << 5) + i
114
121
  } >> p
115
122
 
116
- (0..n-1).reverse_each.each do |i|
117
- output << ((c >> i * 8) & 0xff).chr
123
+ (0..(n - 1)).reverse_each do |i|
124
+ output << ((c >> (i * 8)) & 0xff).chr
118
125
  end
119
126
 
120
127
  return output
@@ -130,15 +137,19 @@ module Ronin
130
137
  # The Base32 encoded chunk.
131
138
  #
132
139
  def encode(output=String.new)
133
- n = (@bytes.length * 8.0 / 5.0).ceil
134
- p = n < 8 ? 5 - (@bytes.length * 8) % 5 : 0
135
- c = @bytes.inject(0) {|m,o| (m << 8) + o} << p
136
-
137
- (0..n-1).reverse_each do |i|
138
- output << Base32::TABLE[(c >> i * 5) & 0x1f].chr
140
+ n = ((@bytes.length * 8.0) / 5.0).ceil
141
+ p = if n < 8
142
+ 5 - ((@bytes.length * 8) % 5)
143
+ else
144
+ 0
145
+ end
146
+ c = @bytes.inject(0) { |m,o| (m << 8) + o } << p
147
+
148
+ (0..(n - 1)).reverse_each do |i|
149
+ output << Base32::TABLE[(c >> (i * 5)) & 0x1f].chr
139
150
  end
140
151
 
141
- return output << ("=" * (8-n))
152
+ return output << ("=" * (8 - n))
142
153
  end
143
154
 
144
155
  end
@@ -154,11 +165,11 @@ module Ronin
154
165
  #
155
166
  # @yieldparam [Chunk] chunk
156
167
  #
168
+ # @api private
169
+ #
157
170
  def self.each_chunk(data,size)
158
- bytes = data.bytes
159
-
160
- data.bytes.each_slice(size) do |bytes|
161
- yield Chunk.new(bytes)
171
+ data.bytes.each_slice(size) do |byte_slice|
172
+ yield Chunk.new(byte_slice)
162
173
  end
163
174
  end
164
175
  end
@@ -29,7 +29,7 @@ class Integer
29
29
  # @raise [RangeError]
30
30
  # The integer value is negative.
31
31
  #
32
- # @example
32
+ # @example
33
33
  # 0x41.c_escape
34
34
  # # => "A"
35
35
  # 0x22.c_escape
@@ -93,7 +93,7 @@ module Ronin
93
93
  # @raise [RangeError]
94
94
  # The integer value is negative.
95
95
  #
96
- # @example
96
+ # @example
97
97
  # Encoding::C.escape_byte(0x41)
98
98
  # # => "A"
99
99
  # Encoding::C.escape_byte(0x22)
@@ -223,11 +223,11 @@ module Ronin
223
223
  until scanner.eos?
224
224
  unescaped << case (char = scanner.getch)
225
225
  when "\\" # backslash
226
- if (hex_char = scanner.scan(/x[0-9a-fA-F]{1,2}/)) # \xXX
226
+ if (hex_char = scanner.scan(/x[0-9a-fA-F]{1,2}/)) # \xXX
227
227
  hex_char[1..].to_i(16).chr
228
- elsif (hex_char = scanner.scan(/u[0-9a-fA-F]{4,8}/)) # \u..
228
+ elsif (hex_char = scanner.scan(/u[0-9a-fA-F]{4,8}/)) # \u..
229
229
  hex_char[1..].to_i(16).chr(Encoding::UTF_8)
230
- elsif (octal_char = scanner.scan(/[0-7]{1,3}/)) # \N, \NN, or \NNN
230
+ elsif (octal_char = scanner.scan(/[0-7]{1,3}/)) # \N, \NN, or \NNN
231
231
  octal_char.to_i(8).chr
232
232
  elsif (special_char = scanner.getch) # \[A-Za-z]
233
233
  BACKSLASHED_CHARS.fetch(special_char,special_char)
@@ -198,11 +198,11 @@ module Ronin
198
198
  until scanner.eos?
199
199
  buffer << case (char = scanner.getch)
200
200
  when '\\'
201
- if (hex_escape = scanner.scan(/x[0-9a-fA-F]{4,8}/))
201
+ if (hex_escape = scanner.scan(/x[0-9a-fA-F]{4,8}/))
202
202
  hex_escape[1..].to_i(16).chr(Encoding::UTF_8)
203
203
  elsif (hex_escape = scanner.scan(/x[0-9a-fA-F]{1,2}/))
204
204
  hex_escape[1..].to_i(16).chr
205
- elsif (char = scanner.getch)
205
+ elsif (char = scanner.getch)
206
206
  BACKSLASHED_CHARS.fetch(char,char)
207
207
  end
208
208
  else
@@ -26,7 +26,7 @@ class Integer
26
26
  # @return [String]
27
27
  # The escaped JavaScript character.
28
28
  #
29
- # @example
29
+ # @example
30
30
  # 0x41.js_escape
31
31
  # # => "A"
32
32
  # 0x22.js_escape
@@ -86,7 +86,7 @@ module Ronin
86
86
  # @return [String]
87
87
  # The escaped JavaScript character.
88
88
  #
89
- # @example
89
+ # @example
90
90
  # Encoding::JS.escape_byte(0x41)
91
91
  # # => "A"
92
92
  # Encoding::JS.escape_byte(0x22)
@@ -135,7 +135,7 @@ module Ronin
135
135
  "\\f" => "\f",
136
136
  "\\r" => "\r",
137
137
  "\\\"" => "\"",
138
- "\\\'" => "'",
138
+ "\\'" => "'",
139
139
  "\\\\" => "\\"
140
140
  }
141
141
 
@@ -187,9 +187,9 @@ module Ronin
187
187
  data.scan(/[\\%]u[0-9a-fA-F]{1,4}|[\\%][0-9a-fA-F]{1,2}|\\[btnfr\'\"\\]|./) do |c|
188
188
  unescaped << BACKSLASHED_CHARS.fetch(c) do
189
189
  if (c.start_with?("\\u") || c.start_with?("%u"))
190
- c[2..-1].to_i(16)
190
+ c[2..].to_i(16)
191
191
  elsif (c.start_with?("\\") || c.start_with?("%"))
192
- c[1..-1].to_i(16)
192
+ c[1..].to_i(16)
193
193
  else
194
194
  c
195
195
  end
@@ -29,7 +29,7 @@ class Integer
29
29
  # @raise [RangeError]
30
30
  # The integer value is negative.
31
31
  #
32
- # @example
32
+ # @example
33
33
  # 0x41.powershell_encode
34
34
  # # => "[char]0x41"
35
35
  # 0x0a.powershell_encode
@@ -60,7 +60,7 @@ class Integer
60
60
  # @raise [RangeError]
61
61
  # The integer value is negative.
62
62
  #
63
- # @example
63
+ # @example
64
64
  # 0x41.powershell_escape
65
65
  # # => "A"
66
66
  # 0x08.powershell_escape
@@ -68,7 +68,7 @@ module Ronin
68
68
  # @raise [RangeError]
69
69
  # The integer value is negative.
70
70
  #
71
- # @example
71
+ # @example
72
72
  # Encoding::PowerShell.encode_byte(0x41)
73
73
  # # => "[char]0x41"
74
74
  # Encoding::PowerShell.encode_byte(0x0a)
@@ -100,7 +100,7 @@ module Ronin
100
100
  # @raise [RangeError]
101
101
  # The integer value is negative.
102
102
  #
103
- # @example
103
+ # @example
104
104
  # Encoding::PowerShell.escape_byte(0x41)
105
105
  # # => "A"
106
106
  # Encoding::PowerShell.escape_byte(0x08)
@@ -197,9 +197,9 @@ module Ronin
197
197
  until scanner.eos?
198
198
  unescaped << if (backslash_char = scanner.scan(/`[0abetnvfr]/)) # `c
199
199
  BACKSLASHED_CHARS[backslash_char[1,1]]
200
- elsif (hex_char = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{1,2}\)/)) # [char]0xXX
200
+ elsif (hex_char = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{1,2}\)/)) # [char]0xXX
201
201
  hex_char[10..-2].to_i(16).chr
202
- elsif (hex_char = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{3,}\)/)) # [char]0xXX
202
+ elsif (hex_char = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{3,}\)/)) # [char]0xXX
203
203
  hex_char[10..-2].to_i(16).chr(Encoding::UTF_8)
204
204
  elsif (unicode_char = scanner.scan(/`u\{[0-9a-fA-F]+\}/)) # `u{XXXX}'
205
205
  unicode_char[3..-2].to_i(16).chr(Encoding::UTF_8)
@@ -299,7 +299,6 @@ module Ronin
299
299
  data
300
300
  end
301
301
  end
302
-
303
302
  end
304
303
  end
305
304
  end
@@ -150,6 +150,7 @@ module Ronin
150
150
  else char
151
151
  end
152
152
  end
153
+
153
154
  UNESCAPE_CHARS['\0'] = "\0"
154
155
  UNESCAPE_CHARS['\a'] = "\a"
155
156
  UNESCAPE_CHARS['\b'] = "\b"
@@ -180,10 +181,10 @@ module Ronin
180
181
  unescaped << if (unicode_escape = scanner.scan(/\\(?:[0-7]{1,3}|[0-7])/))
181
182
  unicode_escape[1,3].to_i(8).chr
182
183
  elsif (hex_escape = scanner.scan(/\\u[0-9a-fA-F]{4,8}/))
183
- hex_escape[2..-1].to_i(16).chr(Encoding::UTF_8)
184
+ hex_escape[2..].to_i(16).chr(Encoding::UTF_8)
184
185
  elsif (hex_escape = scanner.scan(/\\x[0-9a-fA-F]{1,2}/))
185
- hex_escape[2..-1].to_i(16).chr
186
- elsif (escape = scanner.scan(/\\./))
186
+ hex_escape[2..].to_i(16).chr
187
+ elsif (escape = scanner.scan(/\\./))
187
188
  UNESCAPE_CHARS[escape]
188
189
  else
189
190
  scanner.getch
@@ -235,7 +236,6 @@ module Ronin
235
236
  data
236
237
  end
237
238
  end
238
-
239
239
  end
240
240
  end
241
241
  end
@@ -29,7 +29,7 @@ class Integer
29
29
  # @raise [RangeError]
30
30
  # The integer value is negative.
31
31
  #
32
- # @example
32
+ # @example
33
33
  # 0x41.shell_encode
34
34
  # # => "\\x41"
35
35
  # 0x0a.shell_encode
@@ -61,7 +61,7 @@ class Integer
61
61
  # @raise [RangeError]
62
62
  # The integer value is negative.
63
63
  #
64
- # @example
64
+ # @example
65
65
  # 0x41.shell_escape
66
66
  # # => "A"
67
67
  # 0x08.shell_escape
@@ -66,7 +66,7 @@ module Ronin
66
66
  # @raise [RangeError]
67
67
  # The byte value is negative.
68
68
  #
69
- # @example
69
+ # @example
70
70
  # Encoding::Shell.encode_byte(0x41)
71
71
  # # => "\\x41"
72
72
  # Encoding::Shell.encode_byte(0x0a)
@@ -98,7 +98,7 @@ module Ronin
98
98
  # @raise [RangeError]
99
99
  # The integer value is negative.
100
100
  #
101
- # @example
101
+ # @example
102
102
  # Encoding::Shell.escape(0x41)
103
103
  # # => "A"
104
104
  # Encoding::Shell.escape(0x08)
@@ -188,7 +188,7 @@ module Ronin
188
188
  until scanner.eos?
189
189
  unescaped << if (backslash_char = scanner.scan(/\\[0abetnvfr\'\"]/)) # \n
190
190
  BACKSLASHED_CHARS[backslash_char[1..]]
191
- elsif (hex_char = scanner.scan(/\\x[0-9a-fA-F]+/)) # \XX
191
+ elsif (hex_char = scanner.scan(/\\x[0-9a-fA-F]+/)) # \XX
192
192
  hex_char[2..].to_i(16).chr
193
193
  elsif (unicode_char = scanner.scan(/\\u[0-9a-fA-F]+/)) # \uXXXX
194
194
  unicode_char[2..].to_i(16).chr(Encoding::UTF_8)
@@ -116,7 +116,7 @@ module Ronin
116
116
  # The decoded String.
117
117
  #
118
118
  def self.decode(data)
119
- if (data =~ /^[0-9a-fA-F]{2,}$/ && (data.length % 2 == 0))
119
+ if (data =~ /^[0-9a-fA-F]{2,}$/ && data.length.even?)
120
120
  raw = String.new
121
121
 
122
122
  data.scan(/../) do |hex_char|