rex 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/lib/rex.rb +2 -1
- data/lib/rex/arch.rb +1 -1
- data/lib/rex/arch/x86.rb +7 -5
- data/lib/rex/elfparsey/elf.rb +1 -1
- data/lib/rex/elfparsey/elfbase.rb +9 -0
- data/lib/rex/encoder/nonalpha.rb +4 -4
- data/lib/rex/exploitation/js/detect.rb +4 -2
- data/lib/rex/exploitation/jsobfu.rb +5 -501
- data/lib/rex/image_source/image_source.rb +6 -2
- data/lib/rex/mime/header.rb +3 -2
- data/lib/rex/mime/message.rb +1 -2
- data/lib/rex/parser/nexpose_raw_nokogiri.rb +1 -1
- data/lib/rex/post/meterpreter/client.rb +1 -1
- data/lib/rex/proto/dhcp/constants.rb +2 -0
- data/lib/rex/proto/dhcp/server.rb +20 -13
- data/lib/rex/proto/http/handler/proc.rb +1 -1
- data/lib/rex/proto/http/packet.rb +1 -1
- data/lib/rex/proto/http/{header.rb → packet/header.rb} +0 -0
- data/lib/rex/socket/parameters.rb +3 -3
- data/lib/rex/socket/ssl_tcp.rb +46 -6
- data/rex.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NDQ2YzQwN2FiNzY1Y2M0YjY3YzE0NTU1NDc1OWZjZDNlZDc4MDliZA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 79a1308c4fbc5e37cc531c402b45228f0480314a
|
4
|
+
data.tar.gz: 55b5f247534fdac3322b929d4c46e4846c9ec9bb
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDFiOGIzNjIwZGQwZjVkYTk4MmU3YzEzYTA4MDgxNmFiY2YyYTFlNjA3M2U1
|
11
|
-
ZGI3YmY0MjRiMjc2ODk1MzAxYTRkNTIzYjFjNGVlOGJjYjc2NzI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NDM1MjdjM2MyNjZjMWM3MmQ4M2JmMWJlZmU0Nzg5MDdmYjc1NDIzZmJjZTcx
|
14
|
-
NjI3MjUzOTY1NWZkNmMwYzNiN2JjZDRhODU5MDBhMWM0Nzk3ZjhkMDY5M2M3
|
15
|
-
MWY3MWM3YTcwM2Y2ZDQ0NWMxMDg0Mjc2N2RhZjg0ZWQ5MWJjNTA=
|
6
|
+
metadata.gz: 49e7741c0bc14e27943de1291b38e69300173bdffd3a1598372d5db5d1338040201ef011e67680bf42ba611948dd18cc5ad0627388a80d1079ef58c80088bd3e
|
7
|
+
data.tar.gz: 10161b1c288d4c7aab84399ad7f66048ef276d7225b4a701b8ac8eac784ada87786499137dad1fed0f652c4dea529b65c7678f7e2b0b958be5e29dc232da480b
|
data/lib/rex.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
=begin
|
2
3
|
|
3
4
|
The Metasploit Rex library is provided under the 3-clause BSD license.
|
4
5
|
|
5
|
-
Copyright (c) 2005-
|
6
|
+
Copyright (c) 2005-2014, Rapid7, Inc.
|
6
7
|
All rights reserved.
|
7
8
|
|
8
9
|
Redistribution and use in source and binary forms, with or without modification,
|
data/lib/rex/arch.rb
CHANGED
data/lib/rex/arch/x86.rb
CHANGED
@@ -244,7 +244,7 @@ module X86
|
|
244
244
|
_check_reg(dst)
|
245
245
|
|
246
246
|
# If the value is 0 try xor/sub dst, dst (2 bytes)
|
247
|
-
if
|
247
|
+
if val == 0
|
248
248
|
opcodes = Rex::Text.remove_badchars("\x29\x2b\x31\x33", badchars)
|
249
249
|
if !opcodes.empty?
|
250
250
|
return opcodes[rand(opcodes.length)].chr + encode_modrm(dst, dst)
|
@@ -261,8 +261,9 @@ module X86
|
|
261
261
|
|
262
262
|
# try clear dst, mov BYTE dst (4 bytes)
|
263
263
|
begin
|
264
|
-
#
|
265
|
-
|
264
|
+
unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion
|
265
|
+
return _check_badchars(clear(dst, badchars) + mov_byte(dst, val), badchars)
|
266
|
+
end
|
266
267
|
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
267
268
|
end
|
268
269
|
|
@@ -280,8 +281,9 @@ module X86
|
|
280
281
|
|
281
282
|
# try clear dst, mov WORD dst (6 bytes)
|
282
283
|
begin
|
283
|
-
#
|
284
|
-
|
284
|
+
unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion
|
285
|
+
return _check_badchars(clear(dst, badchars) + mov_word(dst, val), badchars)
|
286
|
+
end
|
285
287
|
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
286
288
|
end
|
287
289
|
|
data/lib/rex/elfparsey/elf.rb
CHANGED
@@ -34,7 +34,7 @@ class Elf < ElfBase
|
|
34
34
|
isource.read(offset, PROGRAM_HEADER_SIZE), ei_data
|
35
35
|
)
|
36
36
|
|
37
|
-
if program_header[-1].p_type == PT_LOAD &&
|
37
|
+
if program_header[-1].p_type == PT_LOAD && program_header[-1].p_flags & PF_EXEC > 0
|
38
38
|
base_addr = program_header[-1].p_vaddr
|
39
39
|
end
|
40
40
|
|
@@ -214,6 +214,15 @@ class ElfBase
|
|
214
214
|
[ 'uint32n', 'p_align', 0 ]
|
215
215
|
)
|
216
216
|
|
217
|
+
# p_flags This member tells which permissions should have the segment
|
218
|
+
|
219
|
+
# Flags
|
220
|
+
|
221
|
+
PF_EXEC = 1
|
222
|
+
PF_WRITE = 2
|
223
|
+
PF_READ = 4
|
224
|
+
|
225
|
+
|
217
226
|
#
|
218
227
|
# p_type This member tells what kind of segment this array element
|
219
228
|
# describes or how to interpret the array element's information.
|
data/lib/rex/encoder/nonalpha.rb
CHANGED
@@ -7,7 +7,7 @@ module Encoder
|
|
7
7
|
|
8
8
|
class NonAlpha
|
9
9
|
|
10
|
-
def NonAlpha.gen_decoder
|
10
|
+
def NonAlpha.gen_decoder
|
11
11
|
decoder =
|
12
12
|
"\x66\xB9\xFF\xFF" +
|
13
13
|
"\xEB\x19" + # Jmp to table
|
@@ -28,13 +28,13 @@ class NonAlpha
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def NonAlpha.encode_byte(block, table, tablelen)
|
31
|
-
if
|
31
|
+
if tablelen > 255 || block == 0x7B
|
32
32
|
raise RuntimeError, "BadChar"
|
33
33
|
end
|
34
34
|
|
35
|
-
if (block >= 0x41
|
35
|
+
if (block >= 0x41 && block <= 0x5A) || (block >= 0x61 && block <= 0x7A)
|
36
36
|
# gen offset, return magic
|
37
|
-
offset = 0x7b - block
|
37
|
+
offset = 0x7b - block
|
38
38
|
table += offset.chr
|
39
39
|
tablelen = tablelen + 1
|
40
40
|
block = 0x7B
|
@@ -15,10 +15,12 @@ class Detect
|
|
15
15
|
# Provides several javascript functions for determining the OS and browser versions of a client.
|
16
16
|
#
|
17
17
|
# getVersion(): returns an object with the following properties
|
18
|
-
# os_name - OS name,
|
19
|
-
# os_flavor - OS flavor as a string
|
18
|
+
# os_name - OS name such as "Windows 8", "Linux", "Mac OS X"
|
19
|
+
# os_flavor - OS flavor as a string such as "Home", "Enterprise", etc
|
20
20
|
# os_sp - OS service pack (e.g.: "SP2", will be empty on non-Windows)
|
21
21
|
# os_lang - OS language (e.g.: "en-us")
|
22
|
+
# os_vendor - A company or organization name such as Microsoft, Ubuntu, Apple, etc
|
23
|
+
# os_device - A specific piece of hardware such as iPad, iPhone, etc
|
22
24
|
# ua_name - Client name, one of the Msf::HttpClients constants
|
23
25
|
# ua_version - Client version as a string (e.g.: "3.5.1", "6.0;SP2")
|
24
26
|
# arch - Architecture, one of the ARCH_* constants
|
@@ -1,513 +1,17 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'rex/random_identifier_generator'
|
5
|
-
require 'rkelly'
|
3
|
+
require 'jsobfu'
|
6
4
|
|
7
5
|
module Rex
|
8
6
|
module Exploitation
|
9
7
|
|
10
|
-
|
11
|
-
#
|
12
|
-
# Obfuscate JavaScript by randomizing as much as possible and removing
|
13
|
-
# easily-signaturable string constants.
|
14
|
-
#
|
15
|
-
# Example:
|
16
|
-
# js = ::Rex::Exploitation::JSObfu.new %Q|
|
17
|
-
# var a = "0\\612\\063\\x34\\x35\\x36\\x37\\x38\\u0039";
|
18
|
-
# var b = { foo : "foo", bar : "bar" }
|
19
|
-
# alert(a);
|
20
|
-
# alert(b.foo);
|
21
|
-
# |
|
22
|
-
# js.obfuscate
|
23
|
-
# puts js
|
24
|
-
# Example Output:
|
25
|
-
# var VwxvESbCgv = String.fromCharCode(0x30,0x31,062,063,064,53,0x36,067,070,0x39);
|
26
|
-
# var ToWZPn = {
|
27
|
-
# "\146\157\x6f": (function () { var yDyv="o",YnCL="o",Qcsa="f"; return Qcsa+YnCL+yDyv })(),
|
28
|
-
# "\142ar": String.fromCharCode(0142,97,0162)
|
29
|
-
# };
|
30
|
-
# alert(VwxvESbCgv);
|
31
|
-
# alert(ToWZPn.foo);
|
32
|
-
#
|
33
|
-
# NOTE: Variables MUST be declared with a 'var' statement BEFORE first use (or
|
34
|
-
# not at all) for this to generate correct code! If variables are not declared
|
35
|
-
# they will not be randomized but the generated code will be correct.
|
36
8
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# var a;
|
40
|
-
# alert(a); // real js engines will alert "asdf" here
|
41
|
-
# Bad Example Obfuscated:
|
42
|
-
# a = (function () { var hpHu="f",oyTm="asd"; return oyTm+hpHu })();
|
43
|
-
# var zSrnHpEfJZtg;
|
44
|
-
# alert(zSrnHpEfJZtg);
|
45
|
-
# Notice that the first usage of +a+ (before it was declared) is not
|
46
|
-
# randomized. Thus, the obfuscated version will alert 'undefined' instead of
|
47
|
-
# "asdf".
|
9
|
+
# Simple wrapper class that makes the JSObfu functionality
|
10
|
+
# from the gem available under the Rex namespace.
|
48
11
|
#
|
49
|
-
class JSObfu
|
50
|
-
|
51
|
-
# these keywords should never be used as a random var name
|
52
|
-
# source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words
|
53
|
-
RESERVED_KEYWORDS = %w(
|
54
|
-
break case catch continue debugger default delete do else finally
|
55
|
-
for function if in instanceof new return switch this throw try
|
56
|
-
typeof var void while with class enum export extends import super
|
57
|
-
implements interface let package private protected public static yield
|
58
|
-
)
|
59
|
-
|
60
|
-
#
|
61
|
-
# Abstract Syntax Tree generated by RKelly::Parser#parse
|
62
|
-
#
|
63
|
-
attr_reader :ast
|
64
|
-
|
65
|
-
#
|
66
|
-
# Saves +code+ for later obfuscation with #obfuscate
|
67
|
-
#
|
68
|
-
def initialize(code)
|
69
|
-
@code = code
|
70
|
-
@funcs = {}
|
71
|
-
@vars = {}
|
72
|
-
@debug = false
|
73
|
-
@rand_gen = Rex::RandomIdentifierGenerator.new(
|
74
|
-
:max_length => 15,
|
75
|
-
:first_char_set => Rex::Text::Alpha+"_$",
|
76
|
-
:char_set => Rex::Text::AlphaNumeric+"_$"
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# Add +str+ to the un-obfuscated code.
|
82
|
-
#
|
83
|
-
# Calling this method after #obfuscate is undefined
|
84
|
-
#
|
85
|
-
def <<(str)
|
86
|
-
@code << str
|
87
|
-
end
|
88
|
-
|
89
|
-
#
|
90
|
-
# Return the (possibly obfuscated) code as a string.
|
91
|
-
#
|
92
|
-
# If #obfuscate has not been called before this, returns the parsed,
|
93
|
-
# unobfuscated code. This can be useful for example to remove comments and
|
94
|
-
# standardize spacing.
|
95
|
-
#
|
96
|
-
def to_s
|
97
|
-
parse if not @ast
|
98
|
-
@ast.to_ecma
|
99
|
-
end
|
100
|
-
|
101
|
-
#
|
102
|
-
# Return the obfuscated name of a symbol
|
103
|
-
#
|
104
|
-
# You MUST call #obfuscate before this method!
|
105
|
-
#
|
106
|
-
def sym(lookup)
|
107
|
-
if @vars[lookup]
|
108
|
-
ret = @vars[lookup]
|
109
|
-
elsif @funcs[lookup]
|
110
|
-
ret = @funcs[lookup]
|
111
|
-
else
|
112
|
-
ret = lookup
|
113
|
-
end
|
114
|
-
ret
|
115
|
-
end
|
116
|
-
|
117
|
-
#
|
118
|
-
# Parse and obfuscate
|
119
|
-
#
|
120
|
-
def obfuscate
|
121
|
-
parse
|
122
|
-
obfuscate_r(@ast)
|
123
|
-
end
|
124
|
-
|
125
|
-
# @return [String] a unique random var name that is not a reserved keyword
|
126
|
-
def random_var_name
|
127
|
-
loop do
|
128
|
-
text = random_string
|
129
|
-
unless @vars.has_value?(text) or RESERVED_KEYWORDS.include?(text)
|
130
|
-
return text
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
protected
|
136
|
-
|
137
|
-
# @return [String] a random string
|
138
|
-
def random_string
|
139
|
-
@rand_gen.generate
|
140
|
-
end
|
141
|
-
|
142
|
-
#
|
143
|
-
# Recursive method to obfuscate the given +ast+.
|
144
|
-
#
|
145
|
-
# +ast+ should be the result of RKelly::Parser#parse
|
146
|
-
#
|
147
|
-
def obfuscate_r(ast)
|
148
|
-
ast.each do |node|
|
149
|
-
#if node.respond_to? :value and node.value.kind_of? String and node.value =~ /bodyOnLoad/i
|
150
|
-
# $stdout.puts("bodyOnLoad: #{node.class}: #{node.value}")
|
151
|
-
#end
|
152
|
-
|
153
|
-
case node
|
154
|
-
when nil
|
155
|
-
nil
|
156
|
-
|
157
|
-
when ::RKelly::Nodes::SourceElementsNode
|
158
|
-
# Recurse
|
159
|
-
obfuscate_r(node.value)
|
160
|
-
|
161
|
-
#when ::RKelly::Nodes::ObjectLiteralNode
|
162
|
-
# TODO
|
163
|
-
#$stdout.puts(node.methods - Object.new.methods)
|
164
|
-
#$stdout.puts(node.value.inspect)
|
165
|
-
|
166
|
-
when ::RKelly::Nodes::PropertyNode
|
167
|
-
# Property names must be bare words or string literals NOT
|
168
|
-
# expressions! Can't use transform_string() here
|
169
|
-
if node.name =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/
|
170
|
-
n = '"'
|
171
|
-
node.name.unpack("C*") { |c|
|
172
|
-
case rand(3)
|
173
|
-
when 0; n << "\\x%02x"%(c)
|
174
|
-
when 1; n << "\\#{c.to_s 8}"
|
175
|
-
when 2; n << [c].pack("C")
|
176
|
-
end
|
177
|
-
}
|
178
|
-
n << '"'
|
179
|
-
node.instance_variable_set(:@name, n)
|
180
|
-
end
|
181
|
-
|
182
|
-
# Variables
|
183
|
-
when ::RKelly::Nodes::VarDeclNode
|
184
|
-
if @vars[node.name].nil?
|
185
|
-
@vars[node.name] = random_var_name
|
186
|
-
end
|
187
|
-
node.name = @vars[node.name]
|
188
|
-
when ::RKelly::Nodes::ParameterNode
|
189
|
-
if @vars[node.value].nil?
|
190
|
-
@vars[node.value] = random_var_name
|
191
|
-
end
|
192
|
-
node.value = @vars[node.value]
|
193
|
-
when ::RKelly::Nodes::ResolveNode
|
194
|
-
#$stdout.puts("Resolve bodyOnload: #{@vars[node.value]}") if "bodyOnLoad" == node.value
|
195
|
-
node.value = @vars[node.value] if @vars[node.value]
|
196
|
-
when ::RKelly::Nodes::DotAccessorNode
|
197
|
-
case node.value
|
198
|
-
when ::RKelly::Nodes::ResolveNode
|
199
|
-
if @vars[node.value.value]
|
200
|
-
node.value.value = @vars[node.value.value]
|
201
|
-
end
|
202
|
-
#else
|
203
|
-
# $stderr.puts("Non-resolve node as target of dotaccessor: #{node.value.class}")
|
204
|
-
end
|
205
|
-
|
206
|
-
# Functions
|
207
|
-
when ::RKelly::Nodes::FunctionDeclNode
|
208
|
-
#$stdout.puts("FunctionDecl: #{node.value}")
|
209
|
-
# Functions can also act as objects, so store them in the vars
|
210
|
-
# and the functions list so we can replace them in both places
|
211
|
-
if @funcs[node.value].nil? and not @funcs.values.include?(node.value)
|
212
|
-
@funcs[node.value] = random_var_name
|
213
|
-
if @vars[node.value].nil?
|
214
|
-
@vars[node.value] = @funcs[node.value]
|
215
|
-
end
|
216
|
-
node.value = @funcs[node.value]
|
217
|
-
end
|
218
|
-
when ::RKelly::Nodes::FunctionCallNode
|
219
|
-
# The value of a FunctionCallNode is some sort of accessor node or a ResolveNode
|
220
|
-
# so this is basically useless
|
221
|
-
#$stdout.puts("Function call: #{node.name} => #{@funcs[node.name]}")
|
222
|
-
#node.value = @funcs[node.value] if @funcs[node.value]
|
223
|
-
|
224
|
-
# Transformers
|
225
|
-
when ::RKelly::Nodes::NumberNode
|
226
|
-
node.value = transform_number(node.value)
|
227
|
-
when ::RKelly::Nodes::StringNode
|
228
|
-
node.value = transform_string(node.value)
|
229
|
-
else
|
230
|
-
#$stderr.puts "#{node.class}: #{node.value}"
|
231
|
-
#$stderr.puts "#{node.class}"
|
232
|
-
end
|
233
|
-
|
234
|
-
#unless node.kind_of? ::RKelly::Nodes::SourceElementsNode
|
235
|
-
# $stderr.puts "#{node.class}: #{node.value}"
|
236
|
-
#end
|
237
|
-
end
|
238
|
-
|
239
|
-
nil
|
240
|
-
end
|
241
|
-
|
242
|
-
#
|
243
|
-
# Generate an Abstract Syntax Tree (#ast) for later obfuscation
|
244
|
-
#
|
245
|
-
def parse
|
246
|
-
parser = RKelly::Parser.new
|
247
|
-
@ast = parser.parse(@code)
|
248
|
-
end
|
249
|
-
|
250
|
-
#
|
251
|
-
# Convert a number to a random base (decimal, octal, or hexedecimal).
|
252
|
-
#
|
253
|
-
# Given 10 as input, the possible return values are:
|
254
|
-
# "10"
|
255
|
-
# "0xa"
|
256
|
-
# "012"
|
257
|
-
#
|
258
|
-
def rand_base(num)
|
259
|
-
case rand(3)
|
260
|
-
when 0; num.to_s
|
261
|
-
when 1; "0%o" % num
|
262
|
-
when 2; "0x%x" % num
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
#
|
267
|
-
# Return a mathematical expression that will evaluate to the given number
|
268
|
-
# +num+.
|
269
|
-
#
|
270
|
-
# +num+ can be a float or an int, but should never be negative.
|
271
|
-
#
|
272
|
-
def transform_number(num)
|
273
|
-
case num
|
274
|
-
when Fixnum
|
275
|
-
if num == 0
|
276
|
-
r = rand(10) + 1
|
277
|
-
transformed = "('#{Rex::Text.rand_text_alpha(r)}'.length - #{r})"
|
278
|
-
elsif num > 0 and num < 10
|
279
|
-
# use a random string.length for small numbers
|
280
|
-
transformed = "'#{Rex::Text.rand_text_alpha(num)}'.length"
|
281
|
-
else
|
282
|
-
transformed = "("
|
283
|
-
divisor = rand(num) + 1
|
284
|
-
a = num / divisor.to_i
|
285
|
-
b = num - (a * divisor)
|
286
|
-
# recurse half the time for a
|
287
|
-
a = (rand(2) == 0) ? transform_number(a) : rand_base(a)
|
288
|
-
# recurse half the time for divisor
|
289
|
-
divisor = (rand(2) == 0) ? transform_number(divisor) : rand_base(divisor)
|
290
|
-
transformed << "#{a}*#{divisor}"
|
291
|
-
transformed << "+#{b}"
|
292
|
-
transformed << ")"
|
293
|
-
end
|
294
|
-
when Float
|
295
|
-
transformed = "(#{num - num.floor} + #{rand_base(num.floor)})"
|
296
|
-
end
|
297
|
-
|
298
|
-
#puts("#{num} == #{transformed}")
|
299
|
-
|
300
|
-
transformed
|
301
|
-
end
|
302
|
-
|
303
|
-
#
|
304
|
-
# Convert a javascript string into something that will generate that string.
|
305
|
-
#
|
306
|
-
# Randomly calls one of the +transform_string_*+ methods
|
307
|
-
#
|
308
|
-
def transform_string(str)
|
309
|
-
quote = str[0,1]
|
310
|
-
# pull off the quotes
|
311
|
-
str = str[1,str.length - 2]
|
312
|
-
return quote*2 if str.length == 0
|
313
|
-
|
314
|
-
case rand(2)
|
315
|
-
when 0
|
316
|
-
transformed = transform_string_split_concat(str, quote)
|
317
|
-
when 1
|
318
|
-
transformed = transform_string_fromCharCode(str)
|
319
|
-
#when 2
|
320
|
-
# # Currently no-op
|
321
|
-
# transformed = transform_string_unescape(str)
|
322
|
-
end
|
323
|
-
|
324
|
-
#$stderr.puts "Obfuscating str: #{str.ljust 30} #{transformed}"
|
325
|
-
transformed
|
326
|
-
end
|
327
|
-
|
328
|
-
#
|
329
|
-
# Split a javascript string, +str+, without breaking escape sequences.
|
330
|
-
#
|
331
|
-
# The maximum length of each piece of the string is half the total length
|
332
|
-
# of the string, ensuring we (almost) always split into at least two
|
333
|
-
# pieces. This won't always be true when given a string like "AA\x41",
|
334
|
-
# where escape sequences artificially increase the total length (escape
|
335
|
-
# sequences are considered a single character).
|
336
|
-
#
|
337
|
-
# Returns an array of two-element arrays. The zeroeth element is a
|
338
|
-
# randomly generated variable name, the first is a piece of the string
|
339
|
-
# contained in +quote+s.
|
340
|
-
#
|
341
|
-
# See #escape_length
|
342
|
-
#
|
343
|
-
def safe_split(str, quote)
|
344
|
-
parts = []
|
345
|
-
max_len = str.length / 2
|
346
|
-
while str.length > 0
|
347
|
-
len = 0
|
348
|
-
loop do
|
349
|
-
e_len = escape_length(str[len..-1])
|
350
|
-
e_len = 1 if e_len.nil?
|
351
|
-
len += e_len
|
352
|
-
# if we've reached the end of the string, bail
|
353
|
-
break unless str[len]
|
354
|
-
break if len > max_len
|
355
|
-
# randomize the length of each part
|
356
|
-
break if (rand(4) == 0)
|
357
|
-
end
|
358
|
-
|
359
|
-
part = str.slice!(0, len)
|
360
|
-
|
361
|
-
var = Rex::Text.rand_text_alpha(4)
|
362
|
-
parts.push( [ var, "#{quote}#{part}#{quote}" ] )
|
363
|
-
end
|
364
|
-
|
365
|
-
parts
|
366
|
-
end
|
367
|
-
|
368
|
-
#
|
369
|
-
# Stolen from obfuscatejs.rb
|
370
|
-
#
|
371
|
-
# Determines the length of an escape sequence
|
372
|
-
#
|
373
|
-
def escape_length(str)
|
374
|
-
esc_len = nil
|
375
|
-
if str[0,1] == "\\"
|
376
|
-
case str[1,1]
|
377
|
-
when "u"; esc_len = 6 # unicode \u1234
|
378
|
-
when "x"; esc_len = 4 # hex, \x41
|
379
|
-
when /[0-7]/ # octal, \123, \0
|
380
|
-
str[1,3] =~ /([0-7]{1,3})/
|
381
|
-
if $1.to_i(8) > 255
|
382
|
-
str[1,3] =~ /([0-7]{1,2})/
|
383
|
-
end
|
384
|
-
esc_len = 1 + $1.length
|
385
|
-
else; esc_len = 2 # \" \n, etc.
|
386
|
-
end
|
387
|
-
end
|
388
|
-
esc_len
|
389
|
-
end
|
390
|
-
|
391
|
-
#
|
392
|
-
# Split a javascript string, +str+, into multiple randomly-ordered parts
|
393
|
-
# and return an anonymous javascript function that joins them in the
|
394
|
-
# correct order. This method can be called safely on strings containing
|
395
|
-
# escape sequences. See #safe_split.
|
396
|
-
#
|
397
|
-
def transform_string_split_concat(str, quote)
|
398
|
-
parts = safe_split(str, quote)
|
399
|
-
func = "(function () { var "
|
400
|
-
ret = "; return "
|
401
|
-
parts.sort { |a,b| rand }.each do |part|
|
402
|
-
func << "#{part[0]}=#{part[1]},"
|
403
|
-
end
|
404
|
-
func.chop!
|
405
|
-
|
406
|
-
ret << parts.map{|part| part[0]}.join("+")
|
407
|
-
final = func + ret + " })()"
|
408
|
-
|
409
|
-
final
|
410
|
-
end
|
411
|
-
|
412
|
-
|
413
|
-
# TODO
|
414
|
-
#def transform_string_unescape(str)
|
415
|
-
# str
|
416
|
-
#end
|
417
|
-
|
418
|
-
#
|
419
|
-
# Return a call to String.fromCharCode() with each char of the input as arguments
|
420
|
-
#
|
421
|
-
# Example:
|
422
|
-
# input : "A\n"
|
423
|
-
# output: String.fromCharCode(0x41, 10)
|
424
|
-
#
|
425
|
-
def transform_string_fromCharCode(str)
|
426
|
-
buf = "String.fromCharCode("
|
427
|
-
bytes = str.unpack("C*")
|
428
|
-
len = 0
|
429
|
-
while str.length > 0
|
430
|
-
if str[0,1] == "\\"
|
431
|
-
str.slice!(0,1)
|
432
|
-
# then this is an escape sequence and we need to deal with all
|
433
|
-
# the special cases
|
434
|
-
case str[0,1]
|
435
|
-
# For chars that contain their non-escaped selves, step past
|
436
|
-
# the backslash and let the rand_base() below decide how to
|
437
|
-
# represent the character.
|
438
|
-
when '"', "'", "\\", " "
|
439
|
-
char = str.slice!(0,1).unpack("C").first
|
440
|
-
# For symbolic escapes, use the known value
|
441
|
-
when "n"; char = 0x0a; str.slice!(0,1)
|
442
|
-
when "t"; char = 0x09; str.slice!(0,1)
|
443
|
-
# Lastly, if it's a hex, unicode, or octal escape, pull out the
|
444
|
-
# real value and use that
|
445
|
-
when "x"
|
446
|
-
# Strip the x
|
447
|
-
str.slice!(0,1)
|
448
|
-
char = str.slice!(0,2).to_i 16
|
449
|
-
when "u"
|
450
|
-
# This can potentially lose information in the case of
|
451
|
-
# characters like \u0041, but since regular ascii is stored
|
452
|
-
# as unicode internally, String.fromCharCode(0x41) will be
|
453
|
-
# represented as 00 41 in memory anyway, so it shouldn't
|
454
|
-
# matter.
|
455
|
-
str.slice!(0,1)
|
456
|
-
char = str.slice!(0,4).to_i 16
|
457
|
-
when /[0-7]/
|
458
|
-
# Octals are a bit harder since they are variable width and
|
459
|
-
# don't necessarily mean what you might think. For example,
|
460
|
-
# "\61" == "1" and "\610" == "10". 610 is a valid octal
|
461
|
-
# number, but not a valid ascii character. Javascript will
|
462
|
-
# interpreter as much as it can as a char and use the rest
|
463
|
-
# as a literal. Boo.
|
464
|
-
str =~ /([0-7]{1,3})/
|
465
|
-
char = $1.to_i 8
|
466
|
-
if char > 255
|
467
|
-
str =~ /([0-7]{1,2})/
|
468
|
-
char = $1.to_i 8
|
469
|
-
end
|
470
|
-
str.slice!(0,$1.length)
|
471
|
-
end
|
472
|
-
else
|
473
|
-
char = str.slice!(0,1).unpack("C").first
|
474
|
-
end
|
475
|
-
buf << "#{rand_base(char)},"
|
476
|
-
end
|
477
|
-
# Strip off the last comma
|
478
|
-
buf = buf[0,buf.length-1] + ")"
|
479
|
-
transformed = buf
|
480
|
-
|
481
|
-
transformed
|
482
|
-
end
|
483
|
-
|
12
|
+
class JSObfu < ::JSObfu
|
484
13
|
|
485
14
|
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
|
490
|
-
=begin
|
491
|
-
if __FILE__ == $0
|
492
|
-
if ARGV[0]
|
493
|
-
code = File.read(ARGV[0])
|
494
|
-
else
|
495
|
-
#require 'rex/exploitation/javascriptosdetect'
|
496
|
-
#code = Rex::Exploitation::JavascriptOSDetect.new.to_s
|
497
|
-
code = <<-EOS
|
498
|
-
// Should alert "0123456789"
|
499
|
-
var a = "0\\612\\063\\x34\\x35\\x36\\x37\\x38\\u0039";
|
500
|
-
var a,b=2,c=3;
|
501
|
-
alert(a);
|
502
|
-
// should alert "asdfjkl;"
|
503
|
-
var d = (function() { var foo = "jkl;", blah = "asdf"; return blah + foo; })();
|
504
|
-
alert(d);
|
505
|
-
EOS
|
506
|
-
end
|
507
|
-
js = Rex::Exploitation::JSObfu.new(code)
|
508
|
-
js.obfuscate
|
509
|
-
puts js.to_s
|
510
15
|
|
511
16
|
end
|
512
|
-
|
513
|
-
=end
|
17
|
+
end
|
@@ -29,8 +29,12 @@ class ImageSource
|
|
29
29
|
# FIXME, make me better
|
30
30
|
string = ''
|
31
31
|
loop do
|
32
|
-
|
33
|
-
|
32
|
+
begin
|
33
|
+
char = read(offset, 1)
|
34
|
+
rescue RangeError
|
35
|
+
break
|
36
|
+
end
|
37
|
+
break if char.nil? || char == "\x00"
|
34
38
|
offset += 1
|
35
39
|
string << char
|
36
40
|
end
|
data/lib/rex/mime/header.rb
CHANGED
data/lib/rex/mime/message.rb
CHANGED
@@ -24,9 +24,8 @@ class Message
|
|
24
24
|
self.header.parse(head)
|
25
25
|
ctype = self.header.find('Content-Type')
|
26
26
|
|
27
|
-
if ctype and ctype[1] and ctype[1] =~ /multipart\/mixed;\s*boundary=([
|
27
|
+
if ctype and ctype[1] and ctype[1] =~ /multipart\/mixed;\s*boundary="?([A-Za-z0-9'\(\)\+\_,\-\.\/:=\?^\s]+)"?/
|
28
28
|
self.bound = $1
|
29
|
-
|
30
29
|
chunks = body.to_s.split(/--#{self.bound}(--)?\r?\n/)
|
31
30
|
self.content = chunks.shift.to_s.gsub(/\s+$/, '')
|
32
31
|
self.content << "\r\n" if not self.content.empty?
|
@@ -504,7 +504,7 @@ module Rex
|
|
504
504
|
}
|
505
505
|
}
|
506
506
|
note[:data][:vendor] = @report_data[:os]["os_vendor"] if @report_data[:os]["os_vendor"]
|
507
|
-
note[:data][:product] = @report_data[:os]["os_product"] if @report_data[:os]["
|
507
|
+
note[:data][:product] = @report_data[:os]["os_product"] if @report_data[:os]["os_product"]
|
508
508
|
note[:data][:version] = @report_data[:os]["os_version"] if @report_data[:os]["os_version"]
|
509
509
|
note[:data][:arch] = @report_data[:os]["os_arch"] if @report_data[:os]["os_arch"]
|
510
510
|
db_report(:note, note)
|
@@ -248,7 +248,7 @@ class Client
|
|
248
248
|
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
|
249
249
|
cert.sign(key, OpenSSL::Digest::SHA1.new)
|
250
250
|
|
251
|
-
ctx = OpenSSL::SSL::SSLContext.new
|
251
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
252
252
|
ctx.key = key
|
253
253
|
ctx.cert = cert
|
254
254
|
|
@@ -94,6 +94,9 @@ class Server
|
|
94
94
|
self.pxealtconfigfile = "update0"
|
95
95
|
self.pxepathprefix = ""
|
96
96
|
self.pxereboottime = 2000
|
97
|
+
|
98
|
+
self.domain_name = hash['DOMAINNAME'] || nil
|
99
|
+
self.url = hash['URL'] if hash.include?('URL')
|
97
100
|
end
|
98
101
|
|
99
102
|
def report(&block)
|
@@ -126,7 +129,7 @@ class Server
|
|
126
129
|
allowed_options = [
|
127
130
|
:serveOnce, :pxealtconfigfile, :servePXE, :relayip, :leasetime, :dnsserv,
|
128
131
|
:pxeconfigfile, :pxepathprefix, :pxereboottime, :router,
|
129
|
-
:give_hostname, :served_hostname, :served_over, :serveOnlyPXE
|
132
|
+
:give_hostname, :served_hostname, :served_over, :serveOnlyPXE, :domain_name, :url
|
130
133
|
]
|
131
134
|
|
132
135
|
opts.each_pair { |k,v|
|
@@ -151,10 +154,11 @@ class Server
|
|
151
154
|
end
|
152
155
|
|
153
156
|
attr_accessor :listen_host, :listen_port, :context, :leasetime, :relayip, :router, :dnsserv
|
157
|
+
attr_accessor :domain_name
|
154
158
|
attr_accessor :sock, :thread, :myfilename, :ipstring, :served, :serveOnce
|
155
159
|
attr_accessor :current_ip, :start_ip, :end_ip, :broadcasta, :netmaskn
|
156
160
|
attr_accessor :servePXE, :pxeconfigfile, :pxealtconfigfile, :pxepathprefix, :pxereboottime, :serveOnlyPXE
|
157
|
-
attr_accessor :give_hostname, :served_hostname, :served_over, :reporter
|
161
|
+
attr_accessor :give_hostname, :served_hostname, :served_over, :reporter, :url
|
158
162
|
|
159
163
|
protected
|
160
164
|
|
@@ -166,7 +170,7 @@ protected
|
|
166
170
|
wds = []
|
167
171
|
eds = [@sock]
|
168
172
|
|
169
|
-
r,
|
173
|
+
r,_,_ = ::IO.select(rds,wds,eds,1)
|
170
174
|
|
171
175
|
if (r != nil and r[0] == self.sock)
|
172
176
|
buf,host,port = self.sock.recvfrom(65535)
|
@@ -198,19 +202,19 @@ protected
|
|
198
202
|
end
|
199
203
|
|
200
204
|
# parse out the members
|
201
|
-
|
205
|
+
_hwtype = buf[1,1]
|
202
206
|
hwlen = buf[2,1].unpack("C").first
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
+
_hops = buf[3,1]
|
208
|
+
_txid = buf[4..7]
|
209
|
+
_elapsed = buf[8..9]
|
210
|
+
_flags = buf[10..11]
|
207
211
|
clientip = buf[12..15]
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
+
_givenip = buf[16..19]
|
213
|
+
_nextip = buf[20..23]
|
214
|
+
_relayip = buf[24..27]
|
215
|
+
_clienthwaddr = buf[28..(27+hwlen)]
|
212
216
|
servhostname = buf[44..107]
|
213
|
-
|
217
|
+
_filename = buf[108..235]
|
214
218
|
magic = buf[236..239]
|
215
219
|
|
216
220
|
if (magic != DHCPMagic)
|
@@ -293,6 +297,8 @@ protected
|
|
293
297
|
pkt << dhcpoption(OpSubnetMask, self.netmaskn)
|
294
298
|
pkt << dhcpoption(OpRouter, self.router)
|
295
299
|
pkt << dhcpoption(OpDns, self.dnsserv)
|
300
|
+
pkt << dhcpoption(OpDomainName, self.domain_name)
|
301
|
+
|
296
302
|
if self.servePXE # PXE options
|
297
303
|
pkt << dhcpoption(OpPXEMagic, PXEMagic)
|
298
304
|
# We already got this one, serve localboot file
|
@@ -317,6 +323,7 @@ protected
|
|
317
323
|
pkt << dhcpoption(OpHostname, send_hostname)
|
318
324
|
end
|
319
325
|
end
|
326
|
+
pkt << dhcpoption(OpURL, self.url) if self.url
|
320
327
|
pkt << dhcpoption(OpEnd)
|
321
328
|
|
322
329
|
pkt << ("\x00" * 32) #padding
|
@@ -36,7 +36,7 @@ class Handler::Proc < Handler
|
|
36
36
|
def on_request(cli, req)
|
37
37
|
begin
|
38
38
|
procedure.call(cli, req)
|
39
|
-
rescue Errno::EPIPE
|
39
|
+
rescue Errno::EPIPE, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED
|
40
40
|
elog("Proc::on_request: Client closed connection prematurely", LogSource)
|
41
41
|
rescue
|
42
42
|
elog("Proc::on_request: #{$!.class}: #{$!}\n\n#{$@.join("\n")}", LogSource)
|
File without changes
|
@@ -56,7 +56,7 @@ class Rex::Socket::Parameters
|
|
56
56
|
# @option hash [Bool] 'Bool' Create a bare socket
|
57
57
|
# @option hash [Bool] 'Server' Whether or not this should be a server
|
58
58
|
# @option hash [Bool] 'SSL' Whether or not SSL should be used
|
59
|
-
# @option hash [String] 'SSLVersion' Specify SSL2, SSL3, or TLS1 (
|
59
|
+
# @option hash [String] 'SSLVersion' Specify Auto, SSL2, SSL3, or TLS1 (Auto is
|
60
60
|
# default)
|
61
61
|
# @option hash [String] 'SSLCert' A file containing an SSL certificate (for
|
62
62
|
# server sockets)
|
@@ -117,7 +117,7 @@ class Rex::Socket::Parameters
|
|
117
117
|
self.ssl = false
|
118
118
|
end
|
119
119
|
|
120
|
-
supported_ssl_versions = ['SSL2', 'SSL23', 'TLS1', 'SSL3', :SSLv2, :SSLv3, :SSLv23, :TLSv1]
|
120
|
+
supported_ssl_versions = ['Auto', 'SSL2', 'SSL23', 'TLS1', 'SSL3', :Auto, :SSLv2, :SSLv3, :SSLv23, :TLSv1]
|
121
121
|
if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion'])
|
122
122
|
self.ssl_version = hash['SSLVersion']
|
123
123
|
end
|
@@ -324,7 +324,7 @@ class Rex::Socket::Parameters
|
|
324
324
|
# @return [Bool]
|
325
325
|
attr_accessor :ssl
|
326
326
|
|
327
|
-
# What version of SSL to use (SSL2, SSL3, SSL23, TLS1)
|
327
|
+
# What version of SSL to use (Auto, SSL2, SSL3, SSL23, TLS1)
|
328
328
|
# @return [String,Symbol]
|
329
329
|
attr_accessor :ssl_version
|
330
330
|
|
data/lib/rex/socket/ssl_tcp.rb
CHANGED
@@ -56,18 +56,55 @@ begin
|
|
56
56
|
def initsock(params = nil)
|
57
57
|
super
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
# The autonegotiation preference for SSL/TLS versions
|
60
|
+
versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2]
|
61
|
+
|
62
|
+
# Limit this to a specific SSL/TLS version if specified
|
63
|
+
if params
|
61
64
|
case params.ssl_version
|
62
65
|
when 'SSL2', :SSLv2
|
63
|
-
|
66
|
+
versions = [:SSLv2]
|
64
67
|
when 'SSL23', :SSLv23
|
65
|
-
|
68
|
+
versions = [:SSLv23]
|
69
|
+
when 'SSL3', :SSLv3
|
70
|
+
versions = [:SSLv3]
|
66
71
|
when 'TLS1', :TLSv1
|
67
|
-
|
72
|
+
versions = [:TLSv1]
|
73
|
+
else
|
74
|
+
# Leave the version list as-is (Auto)
|
68
75
|
end
|
69
76
|
end
|
70
77
|
|
78
|
+
# Limit our versions to those supported by the linked OpenSSL library
|
79
|
+
versions = versions.select {|v| OpenSSL::SSL::SSLContext::METHODS.include? v }
|
80
|
+
|
81
|
+
# Raise an error if no selected versions are supported
|
82
|
+
if versions.length == 0
|
83
|
+
raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
|
84
|
+
end
|
85
|
+
|
86
|
+
last_error = nil
|
87
|
+
|
88
|
+
# Iterate through SSL/TLS versions until we successfully negotiate
|
89
|
+
versions.each do |version|
|
90
|
+
begin
|
91
|
+
# Try intializing the socket with this SSL/TLS version
|
92
|
+
# This will throw an exception if it fails
|
93
|
+
initsock_with_ssl_version(params, version)
|
94
|
+
|
95
|
+
# Success! Record what method was used and return
|
96
|
+
self.ssl_negotiated_version = version
|
97
|
+
return
|
98
|
+
rescue OpenSSL::SSL::SSLError => e
|
99
|
+
last_error = e
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# No SSL/TLS versions succeeded, raise the last error
|
104
|
+
raise last_error
|
105
|
+
end
|
106
|
+
|
107
|
+
def initsock_with_ssl_version(params, version)
|
71
108
|
# Build the SSL connection
|
72
109
|
self.sslctx = OpenSSL::SSL::SSLContext.new(version)
|
73
110
|
|
@@ -84,7 +121,9 @@ begin
|
|
84
121
|
# Could also do this as graceful faildown in case a passed verify_mode is not supported
|
85
122
|
self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
86
123
|
end
|
124
|
+
|
87
125
|
self.sslctx.options = OpenSSL::SSL::OP_ALL
|
126
|
+
|
88
127
|
if params.ssl_cipher
|
89
128
|
self.sslctx.ciphers = params.ssl_cipher
|
90
129
|
end
|
@@ -101,7 +140,6 @@ begin
|
|
101
140
|
# XXX - enabling this causes infinite recursion, so disable for now
|
102
141
|
# self.sslsock.sync_close = true
|
103
142
|
|
104
|
-
|
105
143
|
# Force a negotiation timeout
|
106
144
|
begin
|
107
145
|
Timeout.timeout(params.timeout) do
|
@@ -327,11 +365,13 @@ begin
|
|
327
365
|
end
|
328
366
|
|
329
367
|
attr_reader :peer_verified # :nodoc:
|
368
|
+
attr_reader :ssl_negotiated_version # :nodoc:
|
330
369
|
attr_accessor :sslsock, :sslctx # :nodoc:
|
331
370
|
|
332
371
|
protected
|
333
372
|
|
334
373
|
attr_writer :peer_verified # :nodoc:
|
374
|
+
attr_writer :ssl_negotiated_version # :nodoc:
|
335
375
|
|
336
376
|
|
337
377
|
rescue LoadError
|
data/rex.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HD Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-15 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Rex provides a variety of classes useful for security testing and exploit
|
15
15
|
development.
|
@@ -371,8 +371,8 @@ files:
|
|
371
371
|
- lib/rex/proto/http/handler.rb
|
372
372
|
- lib/rex/proto/http/handler/erb.rb
|
373
373
|
- lib/rex/proto/http/handler/proc.rb
|
374
|
-
- lib/rex/proto/http/header.rb
|
375
374
|
- lib/rex/proto/http/packet.rb
|
375
|
+
- lib/rex/proto/http/packet/header.rb
|
376
376
|
- lib/rex/proto/http/request.rb
|
377
377
|
- lib/rex/proto/http/response.rb
|
378
378
|
- lib/rex/proto/http/server.rb
|
@@ -521,12 +521,12 @@ require_paths:
|
|
521
521
|
- lib
|
522
522
|
required_ruby_version: !ruby/object:Gem::Requirement
|
523
523
|
requirements:
|
524
|
-
- -
|
524
|
+
- - ">="
|
525
525
|
- !ruby/object:Gem::Version
|
526
526
|
version: 1.9.3
|
527
527
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
528
528
|
requirements:
|
529
|
-
- -
|
529
|
+
- - ">="
|
530
530
|
- !ruby/object:Gem::Version
|
531
531
|
version: '0'
|
532
532
|
requirements: []
|