rex-text 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ #
10
+ # Return the index of the first badchar in +data+, otherwise return
11
+ # nil if there wasn't any badchar occurences.
12
+ #
13
+ # @param data [String] The string to check for bad characters
14
+ # @param badchars [String] A list of characters considered to be bad
15
+ # @return [Fixnum] Index of the first bad character if any exist in +data+
16
+ # @return [nil] If +data+ contains no bad characters
17
+ def self.badchar_index(data, badchars = '')
18
+ badchars.unpack("C*").each { |badchar|
19
+ pos = data.index(badchar.chr)
20
+ return pos if pos
21
+ }
22
+ return nil
23
+ end
24
+
25
+ #
26
+ # Removes bad characters from a string.
27
+ #
28
+ # Modifies +data+ in place
29
+ #
30
+ # @param data [#delete]
31
+ # @param badchars [String] A list of characters considered to be bad
32
+ def self.remove_badchars(data, badchars = '')
33
+ return data if badchars.length == 0
34
+ badchars_pat = badchars.unpack("C*").map{|c| "\\x%.2x" % c}.join
35
+ data.gsub!(/[#{badchars_pat}]/n, '')
36
+ data
37
+ end
38
+
39
+ #
40
+ # Returns all chars that are not in the supplied set
41
+ #
42
+ # @param keepers [String]
43
+ # @return [String] All characters not contained in +keepers+
44
+ def self.charset_exclude(keepers)
45
+ excluded_bytes = [*(0..255)] - keepers.unpack("C*")
46
+ excluded_bytes.pack("C*")
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,87 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ #
10
+ # Base32 code
11
+ #
12
+
13
+ # Based on --> https://github.com/stesla/base32
14
+
15
+ # Copyright (c) 2007-2011 Samuel Tesla
16
+
17
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ # of this software and associated documentation files (the "Software"), to deal
19
+ # in the Software without restriction, including without limitation the rights
20
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ # copies of the Software, and to permit persons to whom the Software is
22
+ # furnished to do so, subject to the following conditions:
23
+
24
+ # The above copyright notice and this permission notice shall be included in
25
+ # all copies or substantial portions of the Software.
26
+
27
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33
+ # THE SOFTWARE.
34
+
35
+
36
+ #
37
+ # Base32 encoder
38
+ #
39
+ def self.b32encode(bytes_in)
40
+ n = (bytes_in.length * 8.0 / 5.0).ceil
41
+ p = n < 8 ? 5 - (bytes_in.length * 8) % 5 : 0
42
+ c = bytes_in.inject(0) {|m,o| (m << 8) + o} << p
43
+ [(0..n-1).to_a.reverse.collect {|i| Base32[(c >> i * 5) & 0x1f].chr},
44
+ ("=" * (8-n))]
45
+ end
46
+
47
+ def self.encode_base32(str)
48
+ bytes = str.bytes
49
+ result = ''
50
+ size= 5
51
+ while bytes.any? do
52
+ bytes.each_slice(size) do |a|
53
+ bytes_out = b32encode(a).flatten.join
54
+ result << bytes_out
55
+ bytes = bytes.drop(size)
56
+ end
57
+ end
58
+ return result
59
+ end
60
+
61
+ #
62
+ # Base32 decoder
63
+ #
64
+ def self.b32decode(bytes_in)
65
+ bytes = bytes_in.take_while {|c| c != 61} # strip padding
66
+ n = (bytes.length * 5.0 / 8.0).floor
67
+ p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
68
+ c = bytes.inject(0) {|m,o| (m << 5) + Base32.index(o.chr)} >> p
69
+ (0..n-1).to_a.reverse.collect {|i| ((c >> i * 8) & 0xff).chr}
70
+ end
71
+
72
+ def self.decode_base32(str)
73
+ bytes = str.bytes
74
+ result = ''
75
+ size= 8
76
+ while bytes.any? do
77
+ bytes.each_slice(size) do |a|
78
+ bytes_out = b32decode(a).flatten.join
79
+ result << bytes_out
80
+ bytes = bytes.drop(size)
81
+ end
82
+ end
83
+ return result
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,42 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+
10
+ #
11
+ # Base64 encoder
12
+ #
13
+ def self.encode_base64(str, delim='')
14
+ [str.to_s].pack("m").gsub(/\s+/, delim)
15
+ end
16
+
17
+ #
18
+ # Base64 decoder
19
+ #
20
+ def self.decode_base64(str)
21
+ str.to_s.unpack("m")[0]
22
+ end
23
+
24
+ #
25
+ # Base64 encoder (URL-safe RFC6920)
26
+ #
27
+ def self.encode_base64url(str, delim='')
28
+ encode_base64(str, delim).
29
+ tr('+/', '-_').
30
+ gsub('=', '')
31
+ end
32
+
33
+ #
34
+ # Base64 decoder (URL-safe RFC6920, ignores invalid characters)
35
+ #
36
+ def self.decode_base64url(str)
37
+ decode_base64(
38
+ str.gsub(/[^a-zA-Z0-9_\-]/, '').
39
+ tr('-_', '+/'))
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,117 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ #
10
+ # Creates a comma separated list of numbers
11
+ #
12
+ def self.to_num(str, wrap = DefaultWrap)
13
+ code = str.unpack('C*')
14
+ buff = ""
15
+ 0.upto(code.length-1) do |byte|
16
+ if(byte % 15 == 0) and (buff.length > 0)
17
+ buff << "\r\n"
18
+ end
19
+ buff << sprintf('0x%.2x, ', code[byte])
20
+ end
21
+ # strip , at the end
22
+ buff = buff.chomp(', ')
23
+ buff << "\r\n"
24
+ return buff
25
+ end
26
+
27
+ #
28
+ # Creates a comma separated list of dwords
29
+ #
30
+ def self.to_dword(str, wrap = DefaultWrap)
31
+ code = str
32
+ alignnr = str.length % 4
33
+ if (alignnr > 0)
34
+ code << "\x00" * (4 - alignnr)
35
+ end
36
+ codevalues = Array.new
37
+ code.split("").each_slice(4) do |chars4|
38
+ chars4 = chars4.join("")
39
+ dwordvalue = chars4.unpack('*V')
40
+ codevalues.push(dwordvalue[0])
41
+ end
42
+ buff = ""
43
+ 0.upto(codevalues.length-1) do |byte|
44
+ if(byte % 8 == 0) and (buff.length > 0)
45
+ buff << "\r\n"
46
+ end
47
+ buff << sprintf('0x%.8x, ', codevalues[byte])
48
+ end
49
+ # strip , at the end
50
+ buff = buff.chomp(', ')
51
+ buff << "\r\n"
52
+ return buff
53
+ end
54
+
55
+ #
56
+ # Returns the words in +str+ as an Array.
57
+ #
58
+ # strict - include *only* words, no boundary characters (like spaces, etc.)
59
+ #
60
+ def self.to_words( str, strict = false )
61
+ splits = str.split( /\b/ )
62
+ splits.reject! { |w| !(w =~ /\w/) } if strict
63
+ splits
64
+ end
65
+
66
+ #
67
+ # Pack a value as 64 bit litle endian; does not exist for Array.pack
68
+ #
69
+ def self.pack_int64le(val)
70
+ [val & 0x00000000ffffffff, val >> 32].pack("V2")
71
+ end
72
+
73
+ #
74
+ # Rotate a 32-bit value to the right by +cnt+ bits
75
+ #
76
+ # @param val [Fixnum] The value to rotate
77
+ # @param cnt [Fixnum] Number of bits to rotate by
78
+ def self.ror(val, cnt)
79
+ bits = [val].pack("N").unpack("B32")[0].split(//)
80
+ 1.upto(cnt) do |c|
81
+ bits.unshift( bits.pop )
82
+ end
83
+ [bits.join].pack("B32").unpack("N")[0]
84
+ end
85
+
86
+ #
87
+ # Rotate a 32-bit value to the left by +cnt+ bits
88
+ #
89
+ # @param val (see ror)
90
+ # @param cnt (see ror)
91
+ # @return (see ror)
92
+ def self.rol(val, cnt)
93
+ bits = [val].pack("N").unpack("B32")[0].split(//)
94
+ 1.upto(cnt) do |c|
95
+ bits.push( bits.shift )
96
+ end
97
+ [bits.join].pack("B32").unpack("N")[0]
98
+ end
99
+
100
+ #
101
+ # Removes noise from 2 Strings and return a refined String version.
102
+ #
103
+ def self.refine( str1, str2 )
104
+ return str1 if str1 == str2
105
+
106
+ # get the words of the first str in an array
107
+ s_words = to_words( str1 )
108
+
109
+ # get the words of the second str in an array
110
+ o_words = to_words( str2 )
111
+
112
+ # get what hasn't changed (the rdiff, so to speak) as a string
113
+ (s_words - (s_words - o_words)).join
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ #
10
+ # Calculate the block API hash for the given module/function
11
+ #
12
+ # @param mod [String] The name of the module containing the target function.
13
+ # @param fun [String] The name of the function.
14
+ #
15
+ # @return [String] The hash of the mod/fun pair in string format
16
+ def self.block_api_hash(mod, fun)
17
+ unicode_mod = (mod.upcase + "\x00").unpack('C*').pack('v*')
18
+ mod_hash = self.ror13_hash(unicode_mod)
19
+ fun_hash = self.ror13_hash(fun + "\x00")
20
+ "0x#{(mod_hash + fun_hash & 0xFFFFFFFF).to_s(16)}"
21
+ end
22
+
23
+ #
24
+ # Calculate the ROR13 hash of a given string
25
+ #
26
+ # @return [Fixnum]
27
+ def self.ror13_hash(name)
28
+ hash = 0
29
+ name.unpack("C*").each {|c| hash = ror(hash, 13); hash += c }
30
+ hash
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ # @param str [String] Data to checksum
10
+ # @return [Fixnum] 8-bit checksum
11
+ def self.checksum8(str)
12
+ (str.unpack("C*").inject(:+) || 0) % 0x100
13
+ end
14
+
15
+ # @param str [String] Little-endian data to checksum
16
+ # @return [Fixnum] 16-bit checksum
17
+ def self.checksum16_le(str)
18
+ (str.unpack("v*").inject(:+) || 0) % 0x10000
19
+ end
20
+
21
+ # @param str [String] Big-endian data to checksum
22
+ # @return [Fixnum] 16-bit checksum
23
+ def self.checksum16_be(str)
24
+ (str.unpack("n*").inject(:+) || 0) % 0x10000
25
+ end
26
+
27
+ # @param str [String] Little-endian data to checksum
28
+ # @return [Fixnum] 32-bit checksum
29
+ def self.checksum32_le(str)
30
+ (str.unpack("V*").inject(:+) || 0) % 0x100000000
31
+ end
32
+
33
+ # @param str [String] Big-endian data to checksum
34
+ # @return [Fixnum] 32-bit checksum
35
+ def self.checksum32_be(str)
36
+ (str.unpack("N*").inject(:+) || 0) % 0x100000000
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,105 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Text
4
+ # We are re-opening the module to add these module methods.
5
+ # Breaking them up this way allows us to maintain a little higher
6
+ # degree of organisation and make it easier to find what you're looking for
7
+ # without hanging the underlying calls that we historically rely upon.
8
+
9
+ #
10
+ # Compresses a string, eliminating all superfluous whitespace before and
11
+ # after lines and eliminating all lines.
12
+ #
13
+ # @param str [String] The string in which to crunch whitespace
14
+ # @return [String] Just like +str+, but with repeated whitespace characters
15
+ # trimmed down to a single space
16
+ def self.compress(str)
17
+ str.gsub(/\n/m, ' ').gsub(/\s+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '')
18
+ end
19
+
20
+
21
+
22
+ # Returns true if zlib can be used.
23
+ def self.zlib_present?
24
+ begin
25
+ temp = Zlib
26
+ return true
27
+ rescue
28
+ return false
29
+ end
30
+ end
31
+
32
+ # backwards compat for just a bit...
33
+ def self.gzip_present?
34
+ self.zlib_present?
35
+ end
36
+
37
+ #
38
+ # Compresses a string using zlib
39
+ #
40
+ # @param str [String] The string to be compressed
41
+ # @param level [Fixnum] One of the Zlib compression level constants
42
+ # @return [String] The compressed version of +str+
43
+ def self.zlib_deflate(str, level = Zlib::BEST_COMPRESSION)
44
+ if self.zlib_present?
45
+ z = Zlib::Deflate.new(level)
46
+ dst = z.deflate(str, Zlib::FINISH)
47
+ z.close
48
+ return dst
49
+ else
50
+ raise RuntimeError, "Gzip support is not present."
51
+ end
52
+ end
53
+
54
+ #
55
+ # Uncompresses a string using zlib
56
+ #
57
+ # @param str [String] Compressed string to inflate
58
+ # @return [String] The uncompressed version of +str+
59
+ def self.zlib_inflate(str)
60
+ if(self.zlib_present?)
61
+ zstream = Zlib::Inflate.new
62
+ buf = zstream.inflate(str)
63
+ zstream.finish
64
+ zstream.close
65
+ return buf
66
+ else
67
+ raise RuntimeError, "Gzip support is not present."
68
+ end
69
+ end
70
+
71
+ #
72
+ # Compresses a string using gzip
73
+ #
74
+ # @param str (see zlib_deflate)
75
+ # @param level [Fixnum] Compression level, 1 (fast) to 9 (best)
76
+ # @return (see zlib_deflate)
77
+ def self.gzip(str, level = 9)
78
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
79
+ raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
80
+
81
+ s = ""
82
+ s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
83
+ gz = Zlib::GzipWriter.new(StringIO.new(s, 'wb'), level)
84
+ gz << str
85
+ gz.close
86
+ return s
87
+ end
88
+
89
+ #
90
+ # Uncompresses a string using gzip
91
+ #
92
+ # @param str (see zlib_inflate)
93
+ # @return (see zlib_inflate)
94
+ def self.ungzip(str)
95
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
96
+
97
+ s = ""
98
+ s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
99
+ gz = Zlib::GzipReader.new(StringIO.new(str, 'rb'))
100
+ s << gz.read
101
+ gz.close
102
+ return s
103
+ end
104
+ end
105
+ end