librex 0.0.29 → 0.0.30
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.
- data/README.markdown +1 -1
- data/lib/rex/io/ring_buffer.rb +3 -3
- data/lib/rex/io/stream.rb +12 -8
- data/lib/rex/io/stream_abstraction.rb +10 -7
- data/lib/rex/job_container.rb +12 -0
- data/lib/rex/parser/apple_backup_manifestdb.rb +131 -0
- data/lib/rex/parser/nexpose_xml.rb +4 -0
- data/lib/rex/post/meterpreter/client.rb +26 -1
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +8 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb +175 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +3 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +21 -11
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +15 -1
- data/lib/rex/proto/dhcp/constants.rb +2 -1
- data/lib/rex/proto/dhcp/server.rb +34 -2
- data/lib/rex/proto/http/header.rb +12 -0
- data/lib/rex/proto/proxy/socks4a.rb +1 -2
- data/lib/rex/proto/smb/constants.rb +0 -1
- data/lib/rex/service_manager.rb +13 -1
- data/lib/rex/socket/comm/local.rb +1 -1
- data/lib/rex/socket/ssl_tcp.rb +129 -13
- data/lib/rex/socket/ssl_tcp_server.rb +31 -2
- data/lib/rex/socket/switch_board.rb +6 -0
- metadata +5 -3
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
A non-official re-packaging of the Rex library as a gem for easy of usage of the Metasploit REX framework in a non Metasploit application. I received permission from HDM to create this package.
|
4
4
|
|
5
5
|
Currently based on:
|
6
|
-
SVN Revision:
|
6
|
+
SVN Revision: 12516
|
7
7
|
|
8
8
|
# Credits
|
9
9
|
The Metasploit development team <http://www.metasploit.com>
|
data/lib/rex/io/ring_buffer.rb
CHANGED
@@ -54,7 +54,7 @@ class RingBuffer
|
|
54
54
|
end
|
55
55
|
|
56
56
|
#
|
57
|
-
# The built-in monitor thread
|
57
|
+
# The built-in monitor thread (normally unused with Metasploit)
|
58
58
|
#
|
59
59
|
def monitor_thread
|
60
60
|
Thread.new do
|
@@ -74,8 +74,8 @@ class RingBuffer
|
|
74
74
|
# Push data back into the associated stream socket. Logging must occur
|
75
75
|
# elsewhere, this function is simply a passthrough.
|
76
76
|
#
|
77
|
-
def put(data)
|
78
|
-
self.fd.put(data)
|
77
|
+
def put(data, opts={})
|
78
|
+
self.fd.put(data, opts={})
|
79
79
|
end
|
80
80
|
|
81
81
|
#
|
data/lib/rex/io/stream.rb
CHANGED
@@ -35,20 +35,20 @@ module Stream
|
|
35
35
|
total_sent = 0
|
36
36
|
total_length = buf.length
|
37
37
|
block_size = 32768
|
38
|
+
|
38
39
|
begin
|
39
40
|
while( total_sent < total_length )
|
40
41
|
s = Rex::ThreadSafe.select( nil, [ fd ], nil, 0.2 )
|
41
42
|
if( s == nil || s[0] == nil )
|
42
43
|
next
|
43
44
|
end
|
44
|
-
data = buf[
|
45
|
+
data = buf[total_sent, block_size]
|
45
46
|
sent = fd.write_nonblock( data )
|
46
47
|
if sent > 0
|
47
48
|
total_sent += sent
|
48
|
-
buf[0, sent] = ""
|
49
49
|
end
|
50
50
|
end
|
51
|
-
rescue ::Errno::EAGAIN
|
51
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
52
52
|
# Sleep for a half a second, or until we can write again
|
53
53
|
Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 )
|
54
54
|
# Decrement the block size to handle full sendQs better
|
@@ -57,8 +57,8 @@ module Stream
|
|
57
57
|
retry
|
58
58
|
rescue ::IOError, ::Errno::EPIPE
|
59
59
|
return nil if (fd.abortive_close == true)
|
60
|
-
raise $!
|
61
60
|
end
|
61
|
+
|
62
62
|
total_sent
|
63
63
|
end
|
64
64
|
|
@@ -66,12 +66,16 @@ module Stream
|
|
66
66
|
# This method reads data of the supplied length from the stream.
|
67
67
|
#
|
68
68
|
def read(length = nil, opts = {})
|
69
|
-
|
69
|
+
|
70
70
|
begin
|
71
|
-
fd.
|
72
|
-
rescue ::
|
71
|
+
return fd.read_nonblock( length )
|
72
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
73
|
+
# Sleep for a half a second, or until we can read again
|
74
|
+
Rex::ThreadSafe.select( [ fd ], nil, nil, 0.5 )
|
75
|
+
# Decrement the block size to handle full sendQs better
|
76
|
+
retry
|
77
|
+
rescue ::IOError, ::Errno::EPIPE
|
73
78
|
return nil if (fd.abortive_close == true)
|
74
|
-
raise $!
|
75
79
|
end
|
76
80
|
end
|
77
81
|
|
@@ -68,19 +68,19 @@ module StreamAbstraction
|
|
68
68
|
end
|
69
69
|
|
70
70
|
#
|
71
|
-
#
|
71
|
+
# Low-level write to the local side.
|
72
72
|
#
|
73
73
|
def syswrite(buffer)
|
74
74
|
lsock.syswrite(buffer)
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
#
|
78
|
-
#
|
78
|
+
# Low-level read from the local side.
|
79
79
|
#
|
80
80
|
def sysread(length)
|
81
81
|
lsock.sysread(length)
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
#
|
85
85
|
# Shuts down the local side of the stream abstraction.
|
86
86
|
#
|
@@ -160,15 +160,18 @@ protected
|
|
160
160
|
total_length = buf.length
|
161
161
|
while( total_sent < total_length )
|
162
162
|
begin
|
163
|
-
data = buf[
|
163
|
+
data = buf[total_sent, buf.length]
|
164
|
+
|
165
|
+
# Note that this must be write() NOT syswrite() or put() or anything like it.
|
166
|
+
# Using syswrite() breaks SSL streams.
|
164
167
|
sent = self.write( data )
|
165
|
-
|
168
|
+
|
169
|
+
# sf: Only remove the data off the queue is write was successfull.
|
166
170
|
# This way we naturally perform a resend if a failure occured.
|
167
171
|
# Catches an edge case with meterpreter TCP channels where remote send
|
168
172
|
# failes gracefully and a resend is required.
|
169
173
|
if( sent > 0 )
|
170
174
|
total_sent += sent
|
171
|
-
buf[0, sent] = ""
|
172
175
|
end
|
173
176
|
rescue ::IOError => e
|
174
177
|
closed = true
|
data/lib/rex/job_container.rb
CHANGED
@@ -177,6 +177,18 @@ class JobContainer < Hash
|
|
177
177
|
self.delete(inst.jid.to_s)
|
178
178
|
end
|
179
179
|
|
180
|
+
#
|
181
|
+
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
|
182
|
+
# "can't add a new key into hash during iteration"
|
183
|
+
#
|
184
|
+
def each(&block)
|
185
|
+
list = []
|
186
|
+
self.keys.sort.each do |sidx|
|
187
|
+
list << [sidx, self[sidx]]
|
188
|
+
end
|
189
|
+
list.each(&block)
|
190
|
+
end
|
191
|
+
|
180
192
|
protected
|
181
193
|
|
182
194
|
attr_accessor :job_id_pool # :nodoc:
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#
|
2
|
+
# This is a Ruby port of the Python manifest parsing code posted to:
|
3
|
+
# http://stackoverflow.com/questions/3085153/how-to-parse-the-manifest-mbdb-file-in-an-ios-4-0-itunes-backup/3130860#3130860
|
4
|
+
#
|
5
|
+
|
6
|
+
module Rex
|
7
|
+
module Parser
|
8
|
+
class AppleBackupManifestDB
|
9
|
+
|
10
|
+
attr_accessor :entry_offsets
|
11
|
+
attr_accessor :entries
|
12
|
+
attr_accessor :mbdb, :mbdx
|
13
|
+
attr_accessor :mbdb_data, :mbdx_data
|
14
|
+
attr_accessor :mbdb_offset, :mbdx_offset
|
15
|
+
|
16
|
+
def initialize(mbdb_data, mbdx_data)
|
17
|
+
self.entries = {}
|
18
|
+
self.entry_offsets = {}
|
19
|
+
self.mbdb_data = mbdb_data
|
20
|
+
self.mbdx_data = mbdx_data
|
21
|
+
parse_mbdb
|
22
|
+
parse_mbdx
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_files(mbdb_file, mbdx_file)
|
26
|
+
mbdb_data = ""
|
27
|
+
::File.open(mbdb_file, "rb") {|fd| mbdb_data = fd.read(fd.stat.size) }
|
28
|
+
mbdx_data = ""
|
29
|
+
::File.open(mbdx_file, "rb") {|fd| mbdx_data = fd.read(fd.stat.size) }
|
30
|
+
|
31
|
+
self.new(mbdb_data, mbdx_data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_mbdb
|
35
|
+
raise ArgumentError, "Not valid MBDB data" if self.mbdb_data[0,4] != "mbdb"
|
36
|
+
self.mbdb_offset = 4
|
37
|
+
self.mbdb_offset = self.mbdb_offset + 2 # Maps to \x05 \x00 (unknown)
|
38
|
+
|
39
|
+
while self.mbdb_offset < self.mbdb_data.length
|
40
|
+
info = {}
|
41
|
+
info[:start_offset] = self.mbdb_offset
|
42
|
+
info[:domain] = mbdb_read_string
|
43
|
+
info[:filename] = mbdb_read_string
|
44
|
+
info[:linktarget] = mbdb_read_string
|
45
|
+
info[:datahash] = mbdb_read_string
|
46
|
+
info[:unknown1] = mbdb_read_string
|
47
|
+
info[:mode] = mbdb_read_int(2)
|
48
|
+
info[:unknown2] = mbdb_read_int(4)
|
49
|
+
info[:unknown3] = mbdb_read_int(4)
|
50
|
+
info[:uid] = mbdb_read_int(4)
|
51
|
+
info[:gid] = mbdb_read_int(4)
|
52
|
+
info[:mtime] = Time.at(mbdb_read_int(4))
|
53
|
+
info[:atime] = Time.at(mbdb_read_int(4))
|
54
|
+
info[:ctime] = Time.at(mbdb_read_int(4))
|
55
|
+
info[:length] = mbdb_read_int(8)
|
56
|
+
info[:flag] = mbdb_read_int(1)
|
57
|
+
property_count = mbdb_read_int(1)
|
58
|
+
info[:properties] = {}
|
59
|
+
1.upto(property_count) do |i|
|
60
|
+
k = mbdb_read_string
|
61
|
+
v = mbdb_read_string
|
62
|
+
info[:properties][k] = v
|
63
|
+
end
|
64
|
+
self.entry_offsets[ info[:start_offset] ] = info
|
65
|
+
end
|
66
|
+
self.mbdb_data = ""
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_mbdx
|
70
|
+
raise ArgumentError, "Not a valid MBDX file" if self.mbdx_data[0,4] != "mbdx"
|
71
|
+
|
72
|
+
self.mbdx_offset = 4
|
73
|
+
self.mbdx_offset = self.mbdx_offset + 2 # Maps to \x02 \x00 (unknown)
|
74
|
+
|
75
|
+
file_count = mbdx_read_int(4)
|
76
|
+
|
77
|
+
while self.mbdx_offset < self.mbdx_data.length
|
78
|
+
file_id = self.mbdx_data[self.mbdx_offset, 20].unpack("C*").map{|c| "%02x" % c}.join
|
79
|
+
self.mbdx_offset += 20
|
80
|
+
entry_offset = mbdx_read_int(4) + 6
|
81
|
+
mode = mbdx_read_int(2)
|
82
|
+
entry = entry_offsets[ entry_offset ]
|
83
|
+
# May be corrupted if there is no matching entry, but what to do about it?
|
84
|
+
next if not entry
|
85
|
+
self.entries[file_id] = entry.merge({:mbdx_mode => mode, :file_id => file_id})
|
86
|
+
end
|
87
|
+
self.mbdx_data = ""
|
88
|
+
end
|
89
|
+
|
90
|
+
def mbdb_read_string
|
91
|
+
raise RuntimeError, "Corrupted MBDB file" if self.mbdb_offset > self.mbdb_data.length
|
92
|
+
len = self.mbdb_data[self.mbdb_offset, 2].unpack("n")[0]
|
93
|
+
self.mbdb_offset += 2
|
94
|
+
return '' if len == 65535
|
95
|
+
val = self.mbdb_data[self.mbdb_offset, len]
|
96
|
+
self.mbdb_offset += len
|
97
|
+
return val
|
98
|
+
end
|
99
|
+
|
100
|
+
def mbdb_read_int(size)
|
101
|
+
val = 0
|
102
|
+
size.downto(1) do |i|
|
103
|
+
val = (val << 8) + self.mbdb_data[self.mbdb_offset, 1].unpack("C")[0]
|
104
|
+
self.mbdb_offset += 1
|
105
|
+
end
|
106
|
+
val
|
107
|
+
end
|
108
|
+
|
109
|
+
def mbdx_read_string
|
110
|
+
raise RuntimeError, "Corrupted MBDX file" if self.mbdx_offset > self.mbdx_data.length
|
111
|
+
len = self.mbdx_data[self.mbdx_offset, 2].unpack("n")[0]
|
112
|
+
self.mbdx_offset += 2
|
113
|
+
return '' if len == 65535
|
114
|
+
val = self.mbdx_data[self.mbdx_offset, len]
|
115
|
+
self.mbdx_offset += len
|
116
|
+
return val
|
117
|
+
end
|
118
|
+
|
119
|
+
def mbdx_read_int(size)
|
120
|
+
val = 0
|
121
|
+
size.downto(1) do |i|
|
122
|
+
val = (val << 8) + self.mbdx_data[self.mbdx_offset, 1].unpack("C")[0]
|
123
|
+
self.mbdx_offset += 1
|
124
|
+
end
|
125
|
+
val
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
@@ -51,6 +51,10 @@ class NexposeXMLStreamParser
|
|
51
51
|
when "test"
|
52
52
|
if attributes["status"] == "vulnerable-exploited" or attributes["status"] == "vulnerable-version"
|
53
53
|
@host["vulns"][attributes["id"]] = attributes.dup
|
54
|
+
if attributes["key"]
|
55
|
+
@host["notes"] ||= []
|
56
|
+
@host["notes"] << [attributes["id"], attributes["key"]]
|
57
|
+
end
|
54
58
|
end
|
55
59
|
when "vulnerability"
|
56
60
|
@vuln.merge! attributes
|
@@ -128,7 +128,32 @@ class Client
|
|
128
128
|
ctx = generate_ssl_context()
|
129
129
|
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
|
130
130
|
|
131
|
-
ssl.
|
131
|
+
if not ssl.respond_to?(:accept_nonblock)
|
132
|
+
ssl.accept
|
133
|
+
else
|
134
|
+
begin
|
135
|
+
ssl.accept_nonblock
|
136
|
+
|
137
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
138
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
139
|
+
IO::select(nil, nil, nil, 0.10)
|
140
|
+
retry
|
141
|
+
|
142
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
143
|
+
rescue ::Exception => e
|
144
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
145
|
+
IO::select( [ ssl ], nil, nil, 0.10 )
|
146
|
+
retry
|
147
|
+
end
|
148
|
+
|
149
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
150
|
+
IO::select( nil, [ ssl ], nil, 0.10 )
|
151
|
+
retry
|
152
|
+
end
|
153
|
+
|
154
|
+
raise e
|
155
|
+
end
|
156
|
+
end
|
132
157
|
|
133
158
|
self.sock.extend(Rex::Socket::SslTcp)
|
134
159
|
self.sock.sslsock = ssl
|
@@ -72,12 +72,14 @@ class Priv < Extension
|
|
72
72
|
if( response.result == 0 and technique != nil )
|
73
73
|
client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" )
|
74
74
|
client.sys.config.getprivs
|
75
|
-
client.framework.db.
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
if client.framework.db and client.framework.db.active
|
76
|
+
client.framework.db.report_note(
|
77
|
+
:host => client.sock.peerhost,
|
78
|
+
:workspace => client.framework.db.workspace,
|
79
|
+
:type => "meterpreter.getsystem",
|
80
|
+
:data => {:technique => technique}
|
81
|
+
) rescue nil
|
82
|
+
end
|
81
83
|
return [ true, technique ]
|
82
84
|
end
|
83
85
|
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..','..','..','..','..', 'lib'))
|
4
|
+
|
5
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
module Rex
|
9
|
+
module Post
|
10
|
+
module Meterpreter
|
11
|
+
module Extensions
|
12
|
+
module Stdapi
|
13
|
+
module Railgun
|
14
|
+
class DLL::UnitTest < Test::Unit::TestCase
|
15
|
+
|
16
|
+
TLV_TYPE_NAMES = {
|
17
|
+
TLV_TYPE_RAILGUN_SIZE_OUT => "TLV_TYPE_RAILGUN_SIZE_OUT",
|
18
|
+
TLV_TYPE_RAILGUN_STACKBLOB => "TLV_TYPE_RAILGUN_STACKBLOB",
|
19
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "TLV_TYPE_RAILGUN_BUFFERBLOB_IN",
|
20
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT",
|
21
|
+
TLV_TYPE_RAILGUN_DLLNAME => "TLV_TYPE_RAILGUN_DLLNAME",
|
22
|
+
TLV_TYPE_RAILGUN_FUNCNAME => "TLV_TYPE_RAILGUN_FUNCNAME",
|
23
|
+
}
|
24
|
+
|
25
|
+
class MockRailgunClient
|
26
|
+
attr_reader :platform, :check_request, :response_tlvs
|
27
|
+
|
28
|
+
def initialize(platform, response_tlvs, check_request)
|
29
|
+
@check_request = check_request
|
30
|
+
@response_tlvs = response_tlvs
|
31
|
+
@platform = platform
|
32
|
+
end
|
33
|
+
|
34
|
+
def send_request(request)
|
35
|
+
check_request.call(request)
|
36
|
+
|
37
|
+
(Class.new do
|
38
|
+
def initialize(response_tlvs)
|
39
|
+
@response_tlvs = response_tlvs
|
40
|
+
end
|
41
|
+
def get_tlv_value(type)
|
42
|
+
return @response_tlvs[type]
|
43
|
+
end
|
44
|
+
end).new(@response_tlvs)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def make_mock_client(platform = "x86/win32", target_request_tlvs = [], response_tlvs = [])
|
49
|
+
check_request = lambda do |request|
|
50
|
+
target_request_tlvs.each_pair do |type, target_value|
|
51
|
+
assert_equal(target_value, request.get_tlv_value(type),
|
52
|
+
"process_function_call should send to client appropriate #{TLV_TYPE_NAMES[type]}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
return MockRailgunClient.new(platform, response_tlvs, check_request)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_add_function
|
60
|
+
function_descriptions.each do |func|
|
61
|
+
dll = DLL.new(func[:dll_name], make_mock_client(func[:platform]), nil)
|
62
|
+
dll.add_function(func[:name], func[:return_type], func[:params])
|
63
|
+
|
64
|
+
assert(dll.functions.has_key?(func[:name]),
|
65
|
+
"add_function should expand the list of available functions")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_method_missing
|
70
|
+
function_descriptions.each do |func|
|
71
|
+
client = make_mock_client(func[:platform], func[:request_to_client], func[:response_from_client])
|
72
|
+
dll = DLL.new(func[:dll_name], client, nil)
|
73
|
+
|
74
|
+
dll.add_function(func[:name], func[:return_type], func[:params])
|
75
|
+
|
76
|
+
actual_returned_hash = dll.send(:method_missing, func[:name].to_sym, *func[:ruby_args])
|
77
|
+
|
78
|
+
assert(func[:returned_hash].has_key?('GetLastError'),
|
79
|
+
"process_function_call should add the result of GetLastError to the key GetLastError")
|
80
|
+
|
81
|
+
assert_equal(func[:returned_hash], actual_returned_hash,
|
82
|
+
"process_function_call convert function result to a ruby hash")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# These are sample descriptions of functions to use for testing.
|
87
|
+
def function_descriptions
|
88
|
+
[
|
89
|
+
{
|
90
|
+
:platform => "x86/win32",
|
91
|
+
:name => "LookupAccountSidA",
|
92
|
+
:params => [
|
93
|
+
["PCHAR","lpSystemName","in"],
|
94
|
+
["LPVOID","Sid","in"],
|
95
|
+
["PCHAR","Name","out"],
|
96
|
+
["PDWORD","cchName","inout"],
|
97
|
+
["PCHAR","ReferencedDomainName","out"],
|
98
|
+
["PDWORD","cchReferencedDomainName","inout"],
|
99
|
+
["PBLOB","peUse","out"],
|
100
|
+
],
|
101
|
+
:return_type => "BOOL",
|
102
|
+
:dll_name => "advapi32",
|
103
|
+
:ruby_args => [nil, 1371864, 100, 100, 100, 100, 1],
|
104
|
+
:request_to_client => {
|
105
|
+
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
106
|
+
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD8\xEE\x14\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00d\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00\x02\x00\x00\x00\xC8\x00\x00\x00",
|
107
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
108
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
109
|
+
TLV_TYPE_RAILGUN_DLLNAME => "advapi32",
|
110
|
+
TLV_TYPE_RAILGUN_FUNCNAME => "LookupAccountSidA"
|
111
|
+
},
|
112
|
+
:response_from_client => {
|
113
|
+
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
114
|
+
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
115
|
+
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
116
|
+
TLV_TYPE_RAILGUN_BACK_ERR => 997
|
117
|
+
},
|
118
|
+
:returned_hash => {
|
119
|
+
"GetLastError" => 997,
|
120
|
+
"return" => true,
|
121
|
+
"Name" => "SYSTEM",
|
122
|
+
"ReferencedDomainName" => "NT AUTHORITY",
|
123
|
+
"peUse" => "\x05",
|
124
|
+
"cchName" => 6,
|
125
|
+
"cchReferencedDomainName" => 12
|
126
|
+
},
|
127
|
+
},
|
128
|
+
{
|
129
|
+
:platform => 'x64/win64',
|
130
|
+
:name => 'LookupAccountSidA',
|
131
|
+
:params => [
|
132
|
+
["PCHAR", "lpSystemName", "in"],
|
133
|
+
["LPVOID", "Sid", "in"],
|
134
|
+
["PCHAR", "Name", "out"],
|
135
|
+
["PDWORD", "cchName", "inout"],
|
136
|
+
["PCHAR", "ReferencedDomainName", "out"],
|
137
|
+
["PDWORD", "cchReferencedDomainName", "inout"],
|
138
|
+
["PBLOB", "peUse", "out"]
|
139
|
+
],
|
140
|
+
:return_type => 'BOOL',
|
141
|
+
:dll_name => 'advapi32',
|
142
|
+
:ruby_args => [nil, 1631552, 100, 100, 100, 100, 1],
|
143
|
+
:request_to_client => {
|
144
|
+
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
145
|
+
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xE5\x18\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xC8\x00\x00\x00\x00\x00\x00\x00",
|
146
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
147
|
+
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
148
|
+
TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
|
149
|
+
TLV_TYPE_RAILGUN_FUNCNAME => 'LookupAccountSidA',
|
150
|
+
},
|
151
|
+
:response_from_client => {
|
152
|
+
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
153
|
+
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
154
|
+
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
155
|
+
TLV_TYPE_RAILGUN_BACK_ERR => 0,
|
156
|
+
},
|
157
|
+
:returned_hash => {
|
158
|
+
"GetLastError"=>0,
|
159
|
+
"return"=>true,
|
160
|
+
"Name"=>"SYSTEM",
|
161
|
+
"ReferencedDomainName"=>"NT AUTHORITY",
|
162
|
+
"peUse"=>"\x05",
|
163
|
+
"cchName"=>6,
|
164
|
+
"cchReferencedDomainName"=>12
|
165
|
+
},
|
166
|
+
},
|
167
|
+
]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -555,7 +555,9 @@ class Console::CommandDispatcher::Core
|
|
555
555
|
end
|
556
556
|
|
557
557
|
if (mod)
|
558
|
-
print_line
|
558
|
+
print_line(::Msf::Serializer::ReadableText.dump_module(mod))
|
559
|
+
mod_opt = ::Msf::Serializer::ReadableText.dump_options(mod, ' ')
|
560
|
+
print_line("\nModule options (#{mod.fullname}):\n\n#{mod_opt}") if (mod_opt and mod_opt.length > 0)
|
559
561
|
end
|
560
562
|
end
|
561
563
|
|
@@ -21,11 +21,13 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
21
21
|
# Options for the download command.
|
22
22
|
#
|
23
23
|
@@download_opts = Rex::Parser::Arguments.new(
|
24
|
+
"-h" => [ false, "Help banner." ],
|
24
25
|
"-r" => [ false, "Download recursively." ])
|
25
26
|
#
|
26
27
|
# Options for the upload command.
|
27
28
|
#
|
28
29
|
@@upload_opts = Rex::Parser::Arguments.new(
|
30
|
+
"-h" => [ false, "Help banner." ],
|
29
31
|
"-r" => [ false, "Upload recursively." ])
|
30
32
|
|
31
33
|
#
|
@@ -179,17 +181,21 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
179
181
|
end
|
180
182
|
|
181
183
|
alias :cmd_del :cmd_rm
|
184
|
+
|
185
|
+
def cmd_download_help
|
186
|
+
print_line "Usage: download [options] src1 src2 src3 ... destination"
|
187
|
+
print_line
|
188
|
+
print_line "Downloads remote files and directories to the local machine."
|
189
|
+
print_line @@download_opts.usage
|
190
|
+
end
|
182
191
|
|
183
192
|
#
|
184
193
|
# Downloads a file or directory from the remote machine to the local
|
185
194
|
# machine.
|
186
195
|
#
|
187
196
|
def cmd_download(*args)
|
188
|
-
if (args.empty?)
|
189
|
-
|
190
|
-
"Usage: download [options] src1 src2 src3 ... destination\n\n" +
|
191
|
-
"Downloads remote files and directories to the local machine.\n" +
|
192
|
-
@@download_opts.usage)
|
197
|
+
if (args.empty? or args.include? "-h")
|
198
|
+
cmd_download_help
|
193
199
|
return true
|
194
200
|
end
|
195
201
|
|
@@ -361,7 +367,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
361
367
|
# Removes one or more directory if it's empty.
|
362
368
|
#
|
363
369
|
def cmd_rmdir(*args)
|
364
|
-
if (args.length == 0)
|
370
|
+
if (args.length == 0 or args.include?("-h"))
|
365
371
|
print_line("Usage: rmdir dir1 dir2 dir3 ...")
|
366
372
|
return true
|
367
373
|
end
|
@@ -374,16 +380,20 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|
374
380
|
return true
|
375
381
|
end
|
376
382
|
|
383
|
+
def cmd_upload_help
|
384
|
+
print_line "Usage: upload [options] src1 src2 src3 ... destination"
|
385
|
+
print_line
|
386
|
+
print_line "Uploads local files and directories to the remote machine."
|
387
|
+
print_line @@upload_opts.usage
|
388
|
+
end
|
389
|
+
|
377
390
|
#
|
378
391
|
# Uploads a file or directory to the remote machine from the local
|
379
392
|
# machine.
|
380
393
|
#
|
381
394
|
def cmd_upload(*args)
|
382
|
-
if (args.empty?)
|
383
|
-
|
384
|
-
"Usage: upload [options] src1 src2 src3 ... destination\n\n" +
|
385
|
-
"Uploads local files and directories to the remote machine.\n" +
|
386
|
-
@@upload_opts.usage)
|
395
|
+
if (args.empty? or args.include?("-h"))
|
396
|
+
cmd_upload_help
|
387
397
|
return true
|
388
398
|
end
|
389
399
|
|
@@ -51,7 +51,7 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
51
51
|
"execute" => "Execute a command",
|
52
52
|
"getpid" => "Get the current process identifier",
|
53
53
|
"getuid" => "Get the user that the server is running as",
|
54
|
-
"getprivs" => "
|
54
|
+
"getprivs" => "Attempt to enable all privileges available to the current process",
|
55
55
|
"kill" => "Terminate a process",
|
56
56
|
"ps" => "List running processes",
|
57
57
|
"reboot" => "Reboots the remote computer",
|
@@ -421,10 +421,24 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|
421
421
|
client.sys.config.revert_to_self
|
422
422
|
end
|
423
423
|
|
424
|
+
def cmd_getprivs_help
|
425
|
+
print_line "Usage: getprivs"
|
426
|
+
print_line
|
427
|
+
print_line "Attempt to enable all privileges, such as SeDebugPrivilege, available to the"
|
428
|
+
print_line "current process. Note that this only enables existing privs and does not change"
|
429
|
+
print_line "users or tokens."
|
430
|
+
print_line
|
431
|
+
print_line "See also: steal_token, getsystem"
|
432
|
+
print_line
|
433
|
+
end
|
434
|
+
|
424
435
|
#
|
425
436
|
# Obtains as many privileges as possible on the target machine.
|
426
437
|
#
|
427
438
|
def cmd_getprivs(*args)
|
439
|
+
if args.include? "-h"
|
440
|
+
cmd_getprivs_help
|
441
|
+
end
|
428
442
|
print_line("=" * 60)
|
429
443
|
print_line("Enabled Process Privileges")
|
430
444
|
print_line("=" * 60)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: constants.rb
|
1
|
+
# $Id: constants.rb 12375 2011-04-20 14:21:36Z jduck $
|
2
2
|
require 'rex/proto/dhcp'
|
3
3
|
|
4
4
|
module Rex
|
@@ -20,6 +20,7 @@ OpLeaseTime = 0x33
|
|
20
20
|
OpSubnetMask = 1
|
21
21
|
OpRouter = 3
|
22
22
|
OpDns = 6
|
23
|
+
OpHostname = 0x0c
|
23
24
|
OpEnd = 0xff
|
24
25
|
|
25
26
|
PXEMagic = "\xF1\x00\x74\x7E"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: server.rb
|
1
|
+
# $Id: server.rb 12471 2011-04-29 22:58:55Z scriptjunkie $
|
2
2
|
|
3
3
|
require 'rex/socket'
|
4
4
|
require 'rex/proto/dhcp'
|
@@ -12,6 +12,9 @@ module DHCP
|
|
12
12
|
# DHCP Server class
|
13
13
|
# not completely configurable - written specifically for a PXE server
|
14
14
|
# - scriptjunkie
|
15
|
+
#
|
16
|
+
# extended to support testing/exploiting CVE-2011-0997
|
17
|
+
# - apconole@yahoo.com
|
15
18
|
##
|
16
19
|
|
17
20
|
class Server
|
@@ -82,6 +85,17 @@ class Server
|
|
82
85
|
else
|
83
86
|
self.servePXE = false
|
84
87
|
end
|
88
|
+
|
89
|
+
# Always assume we don't give out hostnames ...
|
90
|
+
self.give_hostname = false
|
91
|
+
self.served_over = 0
|
92
|
+
if (hash['HOSTNAME'])
|
93
|
+
self.give_hostname = true
|
94
|
+
self.served_hostname = hash['HOSTNAME']
|
95
|
+
if ( hash['HOSTSTART'] )
|
96
|
+
self.served_over = hash['HOSTSTART'].to_i
|
97
|
+
end
|
98
|
+
end
|
85
99
|
|
86
100
|
self.leasetime = 600
|
87
101
|
self.relayip = "\x00\x00\x00\x00" # relay ip - not currently suported
|
@@ -116,7 +130,8 @@ class Server
|
|
116
130
|
def set_option(opts)
|
117
131
|
allowed_options = [
|
118
132
|
:serveOnce, :servePXE, :relayip, :leasetime, :dnsserv,
|
119
|
-
:pxeconfigfile, :pxepathprefix, :pxereboottime, :router
|
133
|
+
:pxeconfigfile, :pxepathprefix, :pxereboottime, :router,
|
134
|
+
:give_hostname, :served_hostname, :served_over
|
120
135
|
]
|
121
136
|
|
122
137
|
opts.each_pair { |k,v|
|
@@ -144,6 +159,7 @@ class Server
|
|
144
159
|
attr_accessor :sock, :thread, :myfilename, :ipstring, :served, :serveOnce
|
145
160
|
attr_accessor :current_ip, :start_ip, :end_ip, :broadcasta, :netmaskn
|
146
161
|
attr_accessor :servePXE, :pxeconfigfile, :pxepathprefix, :pxereboottime
|
162
|
+
attr_accessor :give_hostname, :served_hostname, :served_over
|
147
163
|
|
148
164
|
protected
|
149
165
|
|
@@ -263,6 +279,12 @@ protected
|
|
263
279
|
pkt << [DHCPAck].pack('C')
|
264
280
|
# now we ignore their discovers (but we'll respond to requests in case a packet was lost)
|
265
281
|
self.served.merge!( buf[28..43] => true )
|
282
|
+
if ( self.served_over != 0 )
|
283
|
+
# NOTE: this is sufficient for low-traffic net
|
284
|
+
# for high-traffic, this will probably lead to
|
285
|
+
# hostname collision
|
286
|
+
self.served_over += 1
|
287
|
+
end
|
266
288
|
else
|
267
289
|
#dlog("ignoring unknown DHCP request - type #{messageType}")
|
268
290
|
return
|
@@ -278,6 +300,16 @@ protected
|
|
278
300
|
pkt << dhcpoption(OpPXEConfigFile, self.pxeconfigfile)
|
279
301
|
pkt << dhcpoption(OpPXEPathPrefix, self.pxepathprefix)
|
280
302
|
pkt << dhcpoption(OpPXERebootTime, [self.pxereboottime].pack('N'))
|
303
|
+
if ( self.give_hostname == true )
|
304
|
+
send_hostname = self.served_hostname
|
305
|
+
if ( self.served_over != 0 )
|
306
|
+
# NOTE : see above comments for the 'uniqueness'
|
307
|
+
# of this value
|
308
|
+
send_hostname += self.served_over.to_s
|
309
|
+
end
|
310
|
+
pkt << dhcpoption(OpHostname, send_hostname)
|
311
|
+
end
|
312
|
+
|
281
313
|
pkt << dhcpoption(OpEnd)
|
282
314
|
|
283
315
|
pkt << ("\x00" * 32) #padding
|
@@ -141,6 +141,18 @@ class Packet::Header < Hash
|
|
141
141
|
self.dcase_hash.clear
|
142
142
|
end
|
143
143
|
|
144
|
+
#
|
145
|
+
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
|
146
|
+
# "can't add a new key into hash during iteration"
|
147
|
+
#
|
148
|
+
def each(&block)
|
149
|
+
list = []
|
150
|
+
self.keys.sort.each do |sidx|
|
151
|
+
list << [sidx, self[sidx]]
|
152
|
+
end
|
153
|
+
list.each(&block)
|
154
|
+
end
|
155
|
+
|
144
156
|
#
|
145
157
|
# The raw command string associated with the header which will vary between
|
146
158
|
# requests and responses.
|
@@ -193,11 +193,10 @@ class Socks4a
|
|
193
193
|
total_length = buf.length
|
194
194
|
while( total_sent < total_length )
|
195
195
|
begin
|
196
|
-
data = buf[
|
196
|
+
data = buf[total_sent, buf.length]
|
197
197
|
sent = self.write( data )
|
198
198
|
if( sent > 0 )
|
199
199
|
total_sent += sent
|
200
|
-
buf[0, sent] = ""
|
201
200
|
end
|
202
201
|
rescue
|
203
202
|
closed = true
|
data/lib/rex/service_manager.rb
CHANGED
@@ -127,6 +127,18 @@ class ServiceManager < Hash
|
|
127
127
|
return false
|
128
128
|
end
|
129
129
|
|
130
|
+
#
|
131
|
+
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
|
132
|
+
# "can't add a new key into hash during iteration"
|
133
|
+
#
|
134
|
+
def each(&block)
|
135
|
+
list = []
|
136
|
+
self.keys.sort.each do |sidx|
|
137
|
+
list << [sidx, self[sidx]]
|
138
|
+
end
|
139
|
+
list.each(&block)
|
140
|
+
end
|
141
|
+
|
130
142
|
protected
|
131
143
|
|
132
144
|
#
|
@@ -138,4 +150,4 @@ protected
|
|
138
150
|
|
139
151
|
end
|
140
152
|
|
141
|
-
end
|
153
|
+
end
|
data/lib/rex/socket/ssl_tcp.rb
CHANGED
@@ -14,9 +14,10 @@ begin
|
|
14
14
|
begin
|
15
15
|
require 'openssl'
|
16
16
|
@@loaded_openssl = true
|
17
|
+
require 'openssl/nonblock'
|
17
18
|
rescue ::Exception
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
|
21
22
|
include Rex::Socket::Tcp
|
22
23
|
|
@@ -55,12 +56,13 @@ begin
|
|
55
56
|
def initsock(params = nil)
|
56
57
|
super
|
57
58
|
|
58
|
-
|
59
59
|
version = :SSLv3
|
60
60
|
if(params)
|
61
61
|
case params.ssl_version
|
62
62
|
when 'SSL2'
|
63
63
|
version = :SSLv2
|
64
|
+
when 'SSL23'
|
65
|
+
version = :SSLv23
|
64
66
|
when 'TLS1'
|
65
67
|
version = :TLSv1
|
66
68
|
end
|
@@ -87,15 +89,40 @@ begin
|
|
87
89
|
|
88
90
|
# Tie the context to a socket
|
89
91
|
self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
|
90
|
-
|
92
|
+
|
91
93
|
# XXX - enabling this causes infinite recursion, so disable for now
|
92
94
|
# self.sslsock.sync_close = true
|
93
95
|
|
96
|
+
|
94
97
|
# Force a negotiation timeout
|
95
98
|
begin
|
96
99
|
Timeout.timeout(params.timeout) do
|
97
|
-
|
98
|
-
|
100
|
+
if not self.sslsock.respond_to?(:connect_nonblock)
|
101
|
+
self.sslsock.connect
|
102
|
+
else
|
103
|
+
begin
|
104
|
+
self.sslsock.connect_nonblock
|
105
|
+
|
106
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
107
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
108
|
+
IO::select(nil, nil, nil, 0.10)
|
109
|
+
retry
|
110
|
+
|
111
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
112
|
+
rescue ::Exception => e
|
113
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
114
|
+
IO::select( [ self.sslsock ], nil, nil, 0.10 )
|
115
|
+
retry
|
116
|
+
end
|
117
|
+
|
118
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
119
|
+
IO::select( nil, [ self.sslsock ], nil, 0.10 )
|
120
|
+
retry
|
121
|
+
end
|
122
|
+
|
123
|
+
raise e
|
124
|
+
end
|
125
|
+
end
|
99
126
|
end
|
100
127
|
|
101
128
|
rescue ::Timeout::Error
|
@@ -113,22 +140,111 @@ begin
|
|
113
140
|
# Writes data over the SSL socket.
|
114
141
|
#
|
115
142
|
def write(buf, opts = {})
|
116
|
-
return sslsock.write(buf)
|
143
|
+
return sslsock.write(buf) if not self.sslsock.respond_to?(:write_nonblock)
|
144
|
+
|
145
|
+
total_sent = 0
|
146
|
+
total_length = buf.length
|
147
|
+
block_size = 32768
|
148
|
+
|
149
|
+
begin
|
150
|
+
while( total_sent < total_length )
|
151
|
+
s = Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, 0.25 )
|
152
|
+
if( s == nil || s[0] == nil )
|
153
|
+
next
|
154
|
+
end
|
155
|
+
data = buf[total_sent, block_size]
|
156
|
+
sent = sslsock.write_nonblock( data )
|
157
|
+
if sent > 0
|
158
|
+
total_sent += sent
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
rescue ::IOError, ::Errno::EPIPE
|
163
|
+
return nil if (fd.abortive_close == true)
|
164
|
+
|
165
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
166
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
167
|
+
# Sleep for a half a second, or until we can write again
|
168
|
+
Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, 0.5 )
|
169
|
+
# Decrement the block size to handle full sendQs better
|
170
|
+
block_size = 1024
|
171
|
+
# Try to write the data again
|
172
|
+
retry
|
173
|
+
|
174
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
175
|
+
rescue ::Exception => e
|
176
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
177
|
+
IO::select( [ self.sslsock ], nil, nil, 0.5 )
|
178
|
+
retry
|
179
|
+
end
|
180
|
+
|
181
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
182
|
+
IO::select( nil, [ self.sslsock ], nil, 0.5 )
|
183
|
+
retry
|
184
|
+
end
|
185
|
+
|
186
|
+
raise e
|
187
|
+
end
|
188
|
+
|
189
|
+
total_sent
|
117
190
|
end
|
118
191
|
|
119
192
|
#
|
120
193
|
# Reads data from the SSL socket.
|
121
194
|
#
|
122
|
-
def read(length = nil, opts = {})
|
123
|
-
|
195
|
+
def read(length = nil, opts = {})
|
196
|
+
if not self.sslsock.respond_to?(:read_nonblock)
|
197
|
+
length = 16384 unless length
|
198
|
+
begin
|
199
|
+
return sslsock.sysread(length)
|
200
|
+
rescue EOFError, ::Errno::EPIPE
|
201
|
+
raise EOFError
|
202
|
+
end
|
203
|
+
return
|
204
|
+
end
|
205
|
+
|
124
206
|
|
125
207
|
begin
|
126
|
-
|
127
|
-
|
128
|
-
|
208
|
+
while true
|
209
|
+
s = Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
|
210
|
+
if( s == nil || s[0] == nil )
|
211
|
+
next
|
212
|
+
end
|
213
|
+
buf = sslsock.read_nonblock( length )
|
214
|
+
return buf if buf
|
215
|
+
raise ::EOFError
|
216
|
+
end
|
217
|
+
|
218
|
+
rescue ::IOError, ::Errno::EPIPE
|
219
|
+
return nil if (fd.abortive_close == true)
|
220
|
+
|
221
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
222
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
223
|
+
# Sleep for a tenth a second, or until we can read again
|
224
|
+
Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
|
225
|
+
# Decrement the block size to handle full sendQs better
|
226
|
+
block_size = 1024
|
227
|
+
# Try to write the data again
|
228
|
+
retry
|
229
|
+
|
230
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
231
|
+
rescue ::Exception => e
|
232
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
233
|
+
IO::select( [ self.sslsock ], nil, nil, 0.5 )
|
234
|
+
retry
|
235
|
+
end
|
236
|
+
|
237
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
238
|
+
IO::select( nil, [ self.sslsock ], nil, 0.5 )
|
239
|
+
retry
|
240
|
+
end
|
241
|
+
|
242
|
+
raise e
|
129
243
|
end
|
244
|
+
|
130
245
|
end
|
131
246
|
|
247
|
+
|
132
248
|
#
|
133
249
|
# Closes the SSL socket.
|
134
250
|
#
|
@@ -166,14 +282,14 @@ begin
|
|
166
282
|
sslsock.cipher if sslsock
|
167
283
|
end
|
168
284
|
|
169
|
-
|
170
|
-
|
171
285
|
attr_reader :peer_verified # :nodoc:
|
172
286
|
attr_accessor :sslsock, :sslctx # :nodoc:
|
287
|
+
|
173
288
|
protected
|
174
289
|
|
175
290
|
attr_writer :peer_verified # :nodoc:
|
176
291
|
|
292
|
+
|
177
293
|
rescue LoadError
|
178
294
|
end
|
179
295
|
|
@@ -15,10 +15,10 @@ module Rex::Socket::SslTcpServer
|
|
15
15
|
begin
|
16
16
|
require 'openssl'
|
17
17
|
@@loaded_openssl = true
|
18
|
+
require 'openssl/nonblock'
|
18
19
|
rescue ::Exception
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
22
|
include Rex::Socket::TcpServer
|
23
23
|
|
24
24
|
##
|
@@ -57,10 +57,39 @@ module Rex::Socket::SslTcpServer
|
|
57
57
|
|
58
58
|
begin
|
59
59
|
ssl = OpenSSL::SSL::SSLSocket.new(sock, self.sslctx)
|
60
|
-
|
60
|
+
|
61
|
+
|
62
|
+
if not ssl.respond_to?(:accept_nonblock)
|
63
|
+
ssl.accept
|
64
|
+
else
|
65
|
+
begin
|
66
|
+
ssl.accept_nonblock
|
67
|
+
|
68
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
69
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
70
|
+
IO::select(nil, nil, nil, 0.10)
|
71
|
+
retry
|
72
|
+
|
73
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
74
|
+
rescue ::Exception => e
|
75
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
76
|
+
IO::select( [ ssl ], nil, nil, 0.10 )
|
77
|
+
retry
|
78
|
+
end
|
79
|
+
|
80
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
81
|
+
IO::select( nil, [ ssl ], nil, 0.10 )
|
82
|
+
retry
|
83
|
+
end
|
84
|
+
|
85
|
+
raise e
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
61
89
|
sock.extend(Rex::Socket::SslTcp)
|
62
90
|
sock.sslsock = ssl
|
63
91
|
sock.sslctx = self.sslctx
|
92
|
+
|
64
93
|
return sock
|
65
94
|
|
66
95
|
rescue ::OpenSSL::SSL::SSLError
|
@@ -190,6 +190,12 @@ class SwitchBoard
|
|
190
190
|
def flush_routes
|
191
191
|
_init
|
192
192
|
|
193
|
+
# Remove each of the individual routes so the comms don't think they're
|
194
|
+
# still routing after a flush.
|
195
|
+
self.routes.each { |r|
|
196
|
+
r.comm.routes.delete("#{r.subnet}/#{r.netmask}")
|
197
|
+
}
|
198
|
+
# Re-initialize to an empty array
|
193
199
|
self.routes = Array.new
|
194
200
|
end
|
195
201
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: librex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.30
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Metasploit Development Team
|
@@ -11,11 +11,11 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
14
|
+
date: 2011-05-02 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
18
|
-
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision
|
18
|
+
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision 12516
|
19
19
|
email:
|
20
20
|
- hdm@metasploit.com
|
21
21
|
- jacob.hammack@hammackj.com
|
@@ -149,6 +149,7 @@ files:
|
|
149
149
|
- lib/rex/ole/substorage.rb
|
150
150
|
- lib/rex/ole/util.rb
|
151
151
|
- lib/rex/ole.rb
|
152
|
+
- lib/rex/parser/apple_backup_manifestdb.rb
|
152
153
|
- lib/rex/parser/arguments.rb
|
153
154
|
- lib/rex/parser/arguments.rb.ut.rb
|
154
155
|
- lib/rex/parser/ini.rb
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb
|
237
238
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb
|
238
239
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb
|
240
|
+
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb
|
239
241
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb
|
240
242
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb
|
241
243
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb
|