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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDQwMjkwNWY0OTJlZGI3NDkyYjg2NWE0MzQ1ODE2MGU5NWFjNGRiYw==
5
- data.tar.gz: !binary |-
6
- NDQ2YzQwN2FiNzY1Y2M0YjY3YzE0NTU1NDc1OWZjZDNlZDc4MDliZA==
2
+ SHA1:
3
+ metadata.gz: 79a1308c4fbc5e37cc531c402b45228f0480314a
4
+ data.tar.gz: 55b5f247534fdac3322b929d4c46e4846c9ec9bb
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZTk4N2VhZWJlNzkyZjhmYTA2MWM0NTM0NzU2MTc1MjgzZTRjYzY5ZTJhNGZi
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-2010, Rapid7, Inc.
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,
@@ -48,7 +48,7 @@ module Arch
48
48
  case arch
49
49
  when ARCH_X86
50
50
  [addr].pack('V')
51
- when ARCH_X86_64
51
+ when ARCH_X86_64, ARCH_X64
52
52
  [addr].pack('Q<')
53
53
  when ARCH_MIPS # ambiguous
54
54
  [addr].pack('N')
@@ -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(val == 0)
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
- # break if val == 0
265
- return _check_badchars(clear(dst, badchars) + mov_byte(dst, val), badchars)
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
- # break if val == 0
284
- return _check_badchars(clear(dst, badchars) + mov_word(dst, val), badchars)
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
 
@@ -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 && base_addr == 0
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.
@@ -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 (tablelen > 255) or (block == 0x7B)
31
+ if tablelen > 255 || block == 0x7B
32
32
  raise RuntimeError, "BadChar"
33
33
  end
34
34
 
35
- if (block >= 0x41 and block <= 0x5A) or (block >= 0x61 and block <= 0x7A)
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, one of the Msf::OperatingSystems constants
19
- # os_flavor - OS flavor as a string (e.g.: "XP", "2000")
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 'rex/text'
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
- # Bad Example Javascript:
38
- # a = "asdf"; // this variable hasn't been declared and will not be randomized
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
- char = read(offset, 1)
33
- break if char == "\x00"
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
@@ -25,8 +25,9 @@ class Header
25
25
  next
26
26
  end
27
27
 
28
- var,val = line.split(':')
29
- next if not val
28
+ var, val = line.split(':', 2)
29
+ next if val.nil?
30
+
30
31
  self.headers << [ var.to_s.strip, val.to_s.strip ]
31
32
  prev = self.headers.length - 1
32
33
  end
@@ -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=([^\s]+)/
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]["os_prduct"]
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(:SSLv3)
251
+ ctx = OpenSSL::SSL::SSLContext.new
252
252
  ctx.key = key
253
253
  ctx.cert = cert
254
254
 
@@ -19,8 +19,10 @@ OpDHCPServer = 0x36
19
19
  OpLeaseTime = 0x33
20
20
  OpSubnetMask = 1
21
21
  OpRouter = 3
22
+ OpDomainName = 15
22
23
  OpDns = 6
23
24
  OpHostname = 0x0c
25
+ OpURL = 0x72
24
26
  OpEnd = 0xff
25
27
 
26
28
  PXEMagic = "\xF1\x00\x74\x7E"
@@ -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,w,e = ::IO.select(rds,wds,eds,1)
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
- hwtype = buf[1,1]
205
+ _hwtype = buf[1,1]
202
206
  hwlen = buf[2,1].unpack("C").first
203
- hops = buf[3,1]
204
- txid = buf[4..7]
205
- elapsed = buf[8..9]
206
- flags = buf[10..11]
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
- givenip = buf[16..19]
209
- nextip = buf[20..23]
210
- relayip = buf[24..27]
211
- clienthwaddr = buf[28..(27+hwlen)]
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
- filename = buf[108..235]
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)
@@ -32,7 +32,7 @@ class Packet
32
32
  Completed = 3
33
33
  end
34
34
 
35
- require 'rex/proto/http/header'
35
+ require 'rex/proto/http/packet/header'
36
36
 
37
37
  #
38
38
  # Initializes an instance of an HTTP packet.
@@ -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 (SSL3 is
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
 
@@ -56,18 +56,55 @@ begin
56
56
  def initsock(params = nil)
57
57
  super
58
58
 
59
- version = :SSLv3
60
- if(params)
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
- version = :SSLv2
66
+ versions = [:SSLv2]
64
67
  when 'SSL23', :SSLv23
65
- version = :SSLv23
68
+ versions = [:SSLv23]
69
+ when 'SSL3', :SSLv3
70
+ versions = [:SSLv3]
66
71
  when 'TLS1', :TLSv1
67
- version = :TLSv1
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
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  APP_NAME = "rex"
4
- VERSION = "2.0.3"
4
+ VERSION = "2.0.4"
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = APP_NAME
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.3
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-09-07 00:00:00.000000000 Z
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: []