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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +52 -0
- data/Gemfile +4 -0
- data/LICENSE +27 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rex/codepage.map +104 -0
- data/lib/rex/text.rb +195 -0
- data/lib/rex/text/badchars.rb +50 -0
- data/lib/rex/text/base32.rb +87 -0
- data/lib/rex/text/base64.rb +42 -0
- data/lib/rex/text/binary_manipulation.rb +117 -0
- data/lib/rex/text/block_api.rb +33 -0
- data/lib/rex/text/checksum.rb +39 -0
- data/lib/rex/text/compress.rb +105 -0
- data/lib/rex/text/ebcdic.rb +219 -0
- data/lib/rex/text/encode.rb +104 -0
- data/lib/rex/text/hash.rb +37 -0
- data/lib/rex/text/hex.rb +204 -0
- data/lib/rex/text/illegal_sequence.rb +6 -0
- data/lib/rex/text/lang.rb +156 -0
- data/lib/rex/text/pattern.rb +91 -0
- data/lib/rex/text/rand.rb +233 -0
- data/lib/rex/text/randomize.rb +125 -0
- data/lib/rex/text/silly.rb +59 -0
- data/lib/rex/text/unicode.rb +276 -0
- data/lib/rex/text/version.rb +5 -0
- data/rex-text.gemspec +24 -0
- metadata +195 -0
- metadata.gz.sig +3 -0
|
@@ -0,0 +1,219 @@
|
|
|
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
|
+
# The Iconv translation table for IBM's mainframe / System Z
|
|
11
|
+
# (z/os, s390, mvs, etc) - This is a different implementation
|
|
12
|
+
# of EBCDIC than the Iconv_EBCDIC below.
|
|
13
|
+
# It is technically referred to as Code Page IBM1047.
|
|
14
|
+
# This will be net new (until Ruby supports 1047 code page)
|
|
15
|
+
# for all Mainframe / SystemZ based modules
|
|
16
|
+
# that need to convert ASCII to EBCDIC
|
|
17
|
+
#
|
|
18
|
+
# The bytes are indexed by ASCII conversion number
|
|
19
|
+
# e.g. Iconv_IBM1047[0x41] == \xc1 for letter "A"
|
|
20
|
+
#
|
|
21
|
+
# Note the characters CANNOT be assumed to be in any logical
|
|
22
|
+
# order. Nor are the tables reversible. Lookups must be for each byte
|
|
23
|
+
# https://gist.github.com/bigendiansmalls/b08483ecedff52cc8fa3
|
|
24
|
+
#
|
|
25
|
+
Iconv_IBM1047 = [
|
|
26
|
+
"\x00","\x01","\x02","\x03","\x37","\x2d","\x2e","\x2f",
|
|
27
|
+
"\x16","\x05","\x15","\x0b","\x0c","\x0d","\x0e","\x0f","\x10",
|
|
28
|
+
"\x11","\x12","\x13","\x3c","\x3d","\x32","\x26","\x18","\x19",
|
|
29
|
+
"\x3f","\x27","\x1c","\x1d","\x1e","\x1f","\x40","\x5a","\x7f",
|
|
30
|
+
"\x7b","\x5b","\x6c","\x50","\x7d","\x4d","\x5d","\x5c","\x4e",
|
|
31
|
+
"\x6b","\x60","\x4b","\x61","\xf0","\xf1","\xf2","\xf3","\xf4",
|
|
32
|
+
"\xf5","\xf6","\xf7","\xf8","\xf9","\x7a","\x5e","\x4c","\x7e",
|
|
33
|
+
"\x6e","\x6f","\x7c","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6",
|
|
34
|
+
"\xc7","\xc8","\xc9","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6",
|
|
35
|
+
"\xd7","\xd8","\xd9","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7",
|
|
36
|
+
"\xe8","\xe9","\xad","\xe0","\xbd","\x5f","\x6d","\x79","\x81",
|
|
37
|
+
"\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x91",
|
|
38
|
+
"\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\xa2",
|
|
39
|
+
"\xa3","\xa4","\xa5","\xa6","\xa7","\xa8","\xa9","\xc0","\x4f",
|
|
40
|
+
"\xd0","\xa1","\x07","\x20","\x21","\x22","\x23","\x24","\x25",
|
|
41
|
+
"\x06","\x17","\x28","\x29","\x2a","\x2b","\x2c","\x09","\x0a",
|
|
42
|
+
"\x1b","\x30","\x31","\x1a","\x33","\x34","\x35","\x36","\x08",
|
|
43
|
+
"\x38","\x39","\x3a","\x3b","\x04","\x14","\x3e","\xff","\x41",
|
|
44
|
+
"\xaa","\x4a","\xb1","\x9f","\xb2","\x6a","\xb5","\xbb","\xb4",
|
|
45
|
+
"\x9a","\x8a","\xb0","\xca","\xaf","\xbc","\x90","\x8f","\xea",
|
|
46
|
+
"\xfa","\xbe","\xa0","\xb6","\xb3","\x9d","\xda","\x9b","\x8b",
|
|
47
|
+
"\xb7","\xb8","\xb9","\xab","\x64","\x65","\x62","\x66","\x63",
|
|
48
|
+
"\x67","\x9e","\x68","\x74","\x71","\x72","\x73","\x78","\x75",
|
|
49
|
+
"\x76","\x77","\xac","\x69","\xed","\xee","\xeb","\xef","\xec",
|
|
50
|
+
"\xbf","\x80","\xfd","\xfe","\xfb","\xfc","\xba","\xae","\x59",
|
|
51
|
+
"\x44","\x45","\x42","\x46","\x43","\x47","\x9c","\x48","\x54",
|
|
52
|
+
"\x51","\x52","\x53","\x58","\x55","\x56","\x57","\x8c","\x49",
|
|
53
|
+
"\xcd","\xce","\xcb","\xcf","\xcc","\xe1","\x70","\xdd","\xde",
|
|
54
|
+
"\xdb","\xdc","\x8d","\x8e","\xdf"
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# This is the reverse of the above, converts EBCDIC -> ASCII
|
|
59
|
+
# The bytes are indexed by IBM1047(EBCDIC) conversion number
|
|
60
|
+
# e.g. Iconv_ISO8859_1[0xc1] = \x41 for letter "A"
|
|
61
|
+
#
|
|
62
|
+
# Note the characters CANNOT be assumed to be in any logical (e.g. sequential)
|
|
63
|
+
# order. Nor are the tables reversible. Lookups must be done byte by byte
|
|
64
|
+
#
|
|
65
|
+
Iconv_ISO8859_1 = [
|
|
66
|
+
"\x00","\x01","\x02","\x03","\x9c","\x09","\x86","\x7f",
|
|
67
|
+
"\x97","\x8d","\x8e","\x0b","\x0c","\x0d","\x0e","\x0f","\x10",
|
|
68
|
+
"\x11","\x12","\x13","\x9d","\x0a","\x08","\x87","\x18","\x19",
|
|
69
|
+
"\x92","\x8f","\x1c","\x1d","\x1e","\x1f","\x80","\x81","\x82",
|
|
70
|
+
"\x83","\x84","\x85","\x17","\x1b","\x88","\x89","\x8a","\x8b",
|
|
71
|
+
"\x8c","\x05","\x06","\x07","\x90","\x91","\x16","\x93","\x94",
|
|
72
|
+
"\x95","\x96","\x04","\x98","\x99","\x9a","\x9b","\x14","\x15",
|
|
73
|
+
"\x9e","\x1a","\x20","\xa0","\xe2","\xe4","\xe0","\xe1","\xe3",
|
|
74
|
+
"\xe5","\xe7","\xf1","\xa2","\x2e","\x3c","\x28","\x2b","\x7c",
|
|
75
|
+
"\x26","\xe9","\xea","\xeb","\xe8","\xed","\xee","\xef","\xec",
|
|
76
|
+
"\xdf","\x21","\x24","\x2a","\x29","\x3b","\x5e","\x2d","\x2f",
|
|
77
|
+
"\xc2","\xc4","\xc0","\xc1","\xc3","\xc5","\xc7","\xd1","\xa6",
|
|
78
|
+
"\x2c","\x25","\x5f","\x3e","\x3f","\xf8","\xc9","\xca","\xcb",
|
|
79
|
+
"\xc8","\xcd","\xce","\xcf","\xcc","\x60","\x3a","\x23","\x40",
|
|
80
|
+
"\x27","\x3d","\x22","\xd8","\x61","\x62","\x63","\x64","\x65",
|
|
81
|
+
"\x66","\x67","\x68","\x69","\xab","\xbb","\xf0","\xfd","\xfe",
|
|
82
|
+
"\xb1","\xb0","\x6a","\x6b","\x6c","\x6d","\x6e","\x6f","\x70",
|
|
83
|
+
"\x71","\x72","\xaa","\xba","\xe6","\xb8","\xc6","\xa4","\xb5",
|
|
84
|
+
"\x7e","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7a",
|
|
85
|
+
"\xa1","\xbf","\xd0","\x5b","\xde","\xae","\xac","\xa3","\xa5",
|
|
86
|
+
"\xb7","\xa9","\xa7","\xb6","\xbc","\xbd","\xbe","\xdd","\xa8",
|
|
87
|
+
"\xaf","\x5d","\xb4","\xd7","\x7b","\x41","\x42","\x43","\x44",
|
|
88
|
+
"\x45","\x46","\x47","\x48","\x49","\xad","\xf4","\xf6","\xf2",
|
|
89
|
+
"\xf3","\xf5","\x7d","\x4a","\x4b","\x4c","\x4d","\x4e","\x4f",
|
|
90
|
+
"\x50","\x51","\x52","\xb9","\xfb","\xfc","\xf9","\xfa","\xff",
|
|
91
|
+
"\x5c","\xf7","\x53","\x54","\x55","\x56","\x57","\x58","\x59",
|
|
92
|
+
"\x5a","\xb2","\xd4","\xd6","\xd2","\xd3","\xd5","\x30","\x31",
|
|
93
|
+
"\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\xb3",
|
|
94
|
+
"\xdb","\xdc","\xd9","\xda","\x9f"
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
# The Iconv translation table. The Iconv gem is deprecated in favor of
|
|
98
|
+
# String#encode, yet there is no encoding for EBCDIC. See #4525
|
|
99
|
+
Iconv_EBCDIC = [
|
|
100
|
+
"\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05",
|
|
101
|
+
"%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13",
|
|
102
|
+
"<", "=", "2", "&", "\x18", "\x19", "?", "'", "\x1C", "\x1D", "\x1E",
|
|
103
|
+
"\x1F", "@", "Z", "\x7F", "{", "[", "l", "P", "}", "M", "]", "\\",
|
|
104
|
+
"N", "k", "`", "K", "a", "\xF0", "\xF1", "\xF2", "\xF3", "\xF4",
|
|
105
|
+
"\xF5", "\xF6", "\xF7", "\xF8", "\xF9", "z", "^", "L", "~", "n", "o",
|
|
106
|
+
"|", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7", "\xC8",
|
|
107
|
+
"\xC9", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7",
|
|
108
|
+
"\xD8", "\xD9", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7",
|
|
109
|
+
"\xE8", "\xE9", nil, "\xE0", nil, nil, "m", "y", "\x81", "\x82",
|
|
110
|
+
"\x83", "\x84", "\x85", "\x86", "\x87", "\x88", "\x89", "\x91",
|
|
111
|
+
"\x92", "\x93", "\x94", "\x95", "\x96", "\x97", "\x98", "\x99",
|
|
112
|
+
"\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7", "\xA8", "\xA9",
|
|
113
|
+
"\xC0", "O", "\xD0", "\xA1", "\a", nil, nil, nil, nil, nil, nil,
|
|
114
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
115
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
116
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
117
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
118
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
119
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
120
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
121
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
122
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
123
|
+
nil, nil, nil, nil, nil
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
Iconv_ASCII = [
|
|
127
|
+
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\a", "\b",
|
|
128
|
+
"\t", "\n", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12",
|
|
129
|
+
"\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1A", "\e",
|
|
130
|
+
"\x1C", "\x1D", "\x1E", "\x1F", " ", "!", "\"", "#", "$", "%", "&",
|
|
131
|
+
"'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4",
|
|
132
|
+
"5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B",
|
|
133
|
+
"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
|
|
134
|
+
"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", nil, "\\", nil,
|
|
135
|
+
nil, "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
|
|
136
|
+
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
|
|
137
|
+
"z", "{", "|", "}", "~", "\x7F", nil, nil, nil, nil, nil, nil, nil,
|
|
138
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
139
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
140
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
141
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
142
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
143
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
144
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
145
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
146
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
# A native implementation of the ASCII to EBCDIC conversion table, since
|
|
150
|
+
# EBCDIC isn't available to String#encode as of Ruby 2.1
|
|
151
|
+
#
|
|
152
|
+
# @param str [String] An encodable ASCII string
|
|
153
|
+
# @return [String] an EBCDIC encoded string
|
|
154
|
+
# @note This method will raise in the event of invalid characters
|
|
155
|
+
def self.to_ebcdic(str)
|
|
156
|
+
new_str = []
|
|
157
|
+
str.each_byte do |x|
|
|
158
|
+
if Iconv_ASCII.index(x.chr)
|
|
159
|
+
new_str << Iconv_EBCDIC[Iconv_ASCII.index(x.chr)]
|
|
160
|
+
else
|
|
161
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
new_str.join
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# A native implementation of the EBCDIC to ASCII conversion table, since
|
|
168
|
+
# EBCDIC isn't available to String#encode as of Ruby 2.1
|
|
169
|
+
#
|
|
170
|
+
# @param str [String] an EBCDIC encoded string
|
|
171
|
+
# @return [String] An encodable ASCII string
|
|
172
|
+
# @note This method will raise in the event of invalid characters
|
|
173
|
+
def self.from_ebcdic(str)
|
|
174
|
+
new_str = []
|
|
175
|
+
str.each_byte do |x|
|
|
176
|
+
if Iconv_EBCDIC.index(x.chr)
|
|
177
|
+
new_str << Iconv_ASCII[Iconv_EBCDIC.index(x.chr)]
|
|
178
|
+
else
|
|
179
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
new_str.join
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
#
|
|
186
|
+
# The next two are the same as the above, except strictly for z/os
|
|
187
|
+
# conversions
|
|
188
|
+
# strictly for IBM1047 -> ISO8859-1
|
|
189
|
+
# A native implementation of the IBM1047(EBCDIC) -> ISO8859-1(ASCII)
|
|
190
|
+
# conversion table, since EBCDIC isn't available to String#encode as of Ruby 2.1
|
|
191
|
+
# all 256 bytes are defined
|
|
192
|
+
#
|
|
193
|
+
def self.to_ibm1047(str)
|
|
194
|
+
return str if str.nil?
|
|
195
|
+
new_str = []
|
|
196
|
+
str.each_byte do |x|
|
|
197
|
+
new_str << Iconv_IBM1047[x.ord]
|
|
198
|
+
end
|
|
199
|
+
new_str.join
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#
|
|
203
|
+
# The next two are the same as the above, except strictly for z/os
|
|
204
|
+
# conversions
|
|
205
|
+
# strictly for ISO8859-1 -> IBM1047
|
|
206
|
+
# A native implementation of the ISO8859-1(ASCII) -> IBM1047(EBCDIC)
|
|
207
|
+
# conversion table, since EBCDIC isn't available to String#encode as of Ruby 2.1
|
|
208
|
+
#
|
|
209
|
+
def self.from_ibm1047(str)
|
|
210
|
+
return str if str.nil?
|
|
211
|
+
new_str = []
|
|
212
|
+
str.each_byte do |x|
|
|
213
|
+
new_str << Iconv_ISO8859_1[x.ord]
|
|
214
|
+
end
|
|
215
|
+
new_str.join
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
#
|
|
12
|
+
# Encode a string in a manor useful for HTTP URIs and URI Parameters.
|
|
13
|
+
#
|
|
14
|
+
def self.uri_encode(str, mode = 'hex-normal')
|
|
15
|
+
return "" if str == nil
|
|
16
|
+
|
|
17
|
+
return str if mode == 'none' # fast track no encoding
|
|
18
|
+
|
|
19
|
+
all = /./
|
|
20
|
+
noslashes = /[^\/\\]+/
|
|
21
|
+
# http://tools.ietf.org/html/rfc3986#section-2.3
|
|
22
|
+
normal = /[^a-zA-Z0-9\/\\\.\-_~]+/
|
|
23
|
+
|
|
24
|
+
case mode
|
|
25
|
+
when 'hex-all'
|
|
26
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
|
|
27
|
+
when 'hex-normal'
|
|
28
|
+
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
|
|
29
|
+
when 'hex-noslashes'
|
|
30
|
+
return str.gsub(noslashes) { |s| Rex::Text.to_hex(s, '%') }
|
|
31
|
+
when 'hex-random'
|
|
32
|
+
res = ''
|
|
33
|
+
str.each_byte do |c|
|
|
34
|
+
b = c.chr
|
|
35
|
+
res << ((rand(2) == 0) ?
|
|
36
|
+
b.gsub(all) { |s| Rex::Text.to_hex(s, '%') } :
|
|
37
|
+
b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
|
|
38
|
+
end
|
|
39
|
+
return res
|
|
40
|
+
when 'u-all'
|
|
41
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
|
42
|
+
when 'u-normal'
|
|
43
|
+
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
|
44
|
+
when 'u-noslashes'
|
|
45
|
+
return str.gsub(noslashes) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
|
46
|
+
when 'u-random'
|
|
47
|
+
res = ''
|
|
48
|
+
str.each_byte do |c|
|
|
49
|
+
b = c.chr
|
|
50
|
+
res << ((rand(2) == 0) ?
|
|
51
|
+
b.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } :
|
|
52
|
+
b.gsub(normal){ |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } )
|
|
53
|
+
end
|
|
54
|
+
return res
|
|
55
|
+
when 'u-half'
|
|
56
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms-half'), '%u', 2) }
|
|
57
|
+
else
|
|
58
|
+
raise TypeError, "invalid mode #{mode.inspect}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# Encode a string in a manner useful for HTTP URIs and URI Parameters.
|
|
64
|
+
#
|
|
65
|
+
# @param str [String] The string to be encoded
|
|
66
|
+
# @param mode ["hex","int","int-wide"]
|
|
67
|
+
# @return [String]
|
|
68
|
+
# @raise [TypeError] if +mode+ is not one of the three available modes
|
|
69
|
+
def self.html_encode(str, mode = 'hex')
|
|
70
|
+
case mode
|
|
71
|
+
when 'hex'
|
|
72
|
+
return str.unpack('C*').collect{ |i| "&#x" + ("%.2x" % i) + ";"}.join
|
|
73
|
+
when 'int'
|
|
74
|
+
return str.unpack('C*').collect{ |i| "&#" + i.to_s + ";"}.join
|
|
75
|
+
when 'int-wide'
|
|
76
|
+
return str.unpack('C*').collect{ |i| "&#" + ("0" * (7 - i.to_s.length)) + i.to_s + ";" }.join
|
|
77
|
+
else
|
|
78
|
+
raise TypeError, 'invalid mode'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
# Decode a string that's html encoded
|
|
84
|
+
#
|
|
85
|
+
def self.html_decode(str)
|
|
86
|
+
decoded_str = CGI.unescapeHTML(str)
|
|
87
|
+
return decoded_str
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#
|
|
91
|
+
# Encode an ASCII string so it's safe for XML. It's a wrapper for to_hex_ascii.
|
|
92
|
+
#
|
|
93
|
+
def self.xml_char_encode(str)
|
|
94
|
+
self.to_hex_ascii(str, "&#x", 1, ";")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# Decode a URI encoded string
|
|
99
|
+
#
|
|
100
|
+
def self.uri_decode(str)
|
|
101
|
+
str.gsub(/(%[a-z0-9]{2})/i){ |c| [c[1,2]].pack("H*") }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
# Raw MD5 digest of the supplied string
|
|
11
|
+
#
|
|
12
|
+
def self.md5_raw(str)
|
|
13
|
+
Digest::MD5.digest(str)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# Hexidecimal MD5 digest of the supplied string
|
|
18
|
+
#
|
|
19
|
+
def self.md5(str)
|
|
20
|
+
Digest::MD5.hexdigest(str)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Raw SHA1 digest of the supplied string
|
|
25
|
+
#
|
|
26
|
+
def self.sha1_raw(str)
|
|
27
|
+
Digest::SHA1.digest(str)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
# Hexidecimal SHA1 digest of the supplied string
|
|
32
|
+
#
|
|
33
|
+
def self.sha1(str)
|
|
34
|
+
Digest::SHA1.hexdigest(str)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/rex/text/hex.rb
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
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
|
+
# Returns the escaped hex version of the supplied string
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# Rex::Text.to_hex("asdf") # => "\\x61\\x73\\x64\\x66"
|
|
14
|
+
#
|
|
15
|
+
# @param str (see to_octal)
|
|
16
|
+
# @param prefix (see to_octal)
|
|
17
|
+
# @param count [Fixnum] Number of bytes to put in each escape chunk
|
|
18
|
+
# @return [String] The escaped hex version of +str+
|
|
19
|
+
def self.to_hex(str, prefix = "\\x", count = 1)
|
|
20
|
+
raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
|
|
21
|
+
|
|
22
|
+
# XXX: Regexp.new is used here since using /.{#{count}}/o would compile
|
|
23
|
+
# the regex the first time it is used and never check again. Since we
|
|
24
|
+
# want to know how many to capture on every instance, we do it this
|
|
25
|
+
# way.
|
|
26
|
+
return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Returns the string with nonprintable hex characters sanitized to ascii.
|
|
31
|
+
# Similiar to {.to_hex}, but regular ASCII is not translated if +count+ is 1.
|
|
32
|
+
#
|
|
33
|
+
# @example
|
|
34
|
+
# Rex::Text.to_hex_ascii("\x7fABC\0") # => "\\x7fABC\\x00"
|
|
35
|
+
#
|
|
36
|
+
# @param str (see to_hex)
|
|
37
|
+
# @param prefix (see to_hex)
|
|
38
|
+
# @param count (see to_hex)
|
|
39
|
+
# @param suffix [String,nil] A string to append to the converted bytes
|
|
40
|
+
# @return [String] The original string with non-printables converted to
|
|
41
|
+
# their escaped hex representation
|
|
42
|
+
def self.to_hex_ascii(str, prefix = "\\x", count = 1, suffix=nil)
|
|
43
|
+
raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
|
|
44
|
+
return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s|
|
|
45
|
+
(0x20..0x7e) === s.to_i(16) ? s.to_i(16).chr : prefix + s + suffix.to_s
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# Converts a string to a nicely formatted hex dump
|
|
51
|
+
#
|
|
52
|
+
# @param str [String] The string to convert
|
|
53
|
+
# @param width [Fixnum] Number of bytes to convert before adding a newline
|
|
54
|
+
# @param base [Fixnum] The base address of the dump
|
|
55
|
+
def self.to_hex_dump(str, width=16, base=nil)
|
|
56
|
+
buf = ''
|
|
57
|
+
idx = 0
|
|
58
|
+
cnt = 0
|
|
59
|
+
snl = false
|
|
60
|
+
lst = 0
|
|
61
|
+
lft_col_len = (base.to_i+str.length).to_s(16).length
|
|
62
|
+
lft_col_len = 8 if lft_col_len < 8
|
|
63
|
+
|
|
64
|
+
while (idx < str.length)
|
|
65
|
+
chunk = str[idx, width]
|
|
66
|
+
addr = base ? "%0#{lft_col_len}x " %(base.to_i + idx) : ''
|
|
67
|
+
line = chunk.unpack("H*")[0].scan(/../).join(" ")
|
|
68
|
+
buf << addr + line
|
|
69
|
+
|
|
70
|
+
if (lst == 0)
|
|
71
|
+
lst = line.length
|
|
72
|
+
buf << " " * 4
|
|
73
|
+
else
|
|
74
|
+
buf << " " * ((lst - line.length) + 4).abs
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
buf << "|"
|
|
78
|
+
|
|
79
|
+
chunk.unpack("C*").each do |c|
|
|
80
|
+
if (c > 0x1f and c < 0x7f)
|
|
81
|
+
buf << c.chr
|
|
82
|
+
else
|
|
83
|
+
buf << "."
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
buf << "|\n"
|
|
88
|
+
|
|
89
|
+
idx += width
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
buf << "\n"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# Converts a hex string to a raw string
|
|
97
|
+
#
|
|
98
|
+
# @example
|
|
99
|
+
# Rex::Text.hex_to_raw("\\x41\\x7f\\x42") # => "A\x7fB"
|
|
100
|
+
#
|
|
101
|
+
def self.hex_to_raw(str)
|
|
102
|
+
[ str.downcase.gsub(/'/,'').gsub(/\\?x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
#
|
|
106
|
+
# Turn non-printable chars into hex representations, leaving others alone
|
|
107
|
+
#
|
|
108
|
+
# If +whitespace+ is true, converts whitespace (0x20, 0x09, etc) to hex as
|
|
109
|
+
# well.
|
|
110
|
+
#
|
|
111
|
+
# @see hexify
|
|
112
|
+
# @see to_hex Converts all the chars
|
|
113
|
+
#
|
|
114
|
+
def self.ascii_safe_hex(str, whitespace=false)
|
|
115
|
+
if whitespace
|
|
116
|
+
str.gsub(/([\x00-\x20\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
|
117
|
+
else
|
|
118
|
+
str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
#
|
|
123
|
+
# Converts a string to a hex version with wrapping support
|
|
124
|
+
#
|
|
125
|
+
def self.hexify(str, col = DefaultWrap, line_start = '', line_end = '', buf_start = '', buf_end = '')
|
|
126
|
+
output = buf_start
|
|
127
|
+
cur = 0
|
|
128
|
+
count = 0
|
|
129
|
+
new_line = true
|
|
130
|
+
|
|
131
|
+
# Go through each byte in the string
|
|
132
|
+
str.each_byte { |byte|
|
|
133
|
+
count += 1
|
|
134
|
+
append = ''
|
|
135
|
+
|
|
136
|
+
# If this is a new line, prepend with the
|
|
137
|
+
# line start text
|
|
138
|
+
if (new_line == true)
|
|
139
|
+
append << line_start
|
|
140
|
+
new_line = false
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Append the hexified version of the byte
|
|
144
|
+
append << sprintf("\\x%.2x", byte)
|
|
145
|
+
cur += append.length
|
|
146
|
+
|
|
147
|
+
# If we're about to hit the column or have gone past it,
|
|
148
|
+
# time to finish up this line
|
|
149
|
+
if ((cur + line_end.length >= col) or (cur + buf_end.length >= col))
|
|
150
|
+
new_line = true
|
|
151
|
+
cur = 0
|
|
152
|
+
|
|
153
|
+
# If this is the last byte, use the buf_end instead of
|
|
154
|
+
# line_end
|
|
155
|
+
if (count == str.length)
|
|
156
|
+
append << buf_end + "\n"
|
|
157
|
+
else
|
|
158
|
+
append << line_end + "\n"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
output << append
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
# If we were in the middle of a line, finish the buffer at this point
|
|
166
|
+
if (new_line == false)
|
|
167
|
+
output << buf_end + "\n"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
return output
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
#
|
|
174
|
+
# Convert hex-encoded characters to literals.
|
|
175
|
+
#
|
|
176
|
+
# @example
|
|
177
|
+
# Rex::Text.dehex("AA\\x42CC") # => "AABCC"
|
|
178
|
+
#
|
|
179
|
+
# @see hex_to_raw
|
|
180
|
+
# @param str [String]
|
|
181
|
+
def self.dehex(str)
|
|
182
|
+
return str unless str.respond_to? :match
|
|
183
|
+
return str unless str.respond_to? :gsub
|
|
184
|
+
regex = /\x5cx[0-9a-f]{2}/nmi
|
|
185
|
+
if str.match(regex)
|
|
186
|
+
str.gsub(regex) { |x| x[2,2].to_i(16).chr }
|
|
187
|
+
else
|
|
188
|
+
str
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# Convert and replace hex-encoded characters to literals.
|
|
194
|
+
#
|
|
195
|
+
# @param (see dehex)
|
|
196
|
+
def self.dehex!(str)
|
|
197
|
+
return str unless str.respond_to? :match
|
|
198
|
+
return str unless str.respond_to? :gsub
|
|
199
|
+
regex = /\x5cx[0-9a-f]{2}/nmi
|
|
200
|
+
str.gsub!(regex) { |x| x[2,2].to_i(16).chr }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
204
|
+
end
|