ronin-support 1.0.0.beta3 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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|