librex 0.0.1 → 0.0.3
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 +4 -0
- data/lib/rex/exploitation/cmdstager.rb +9 -133
- data/lib/rex/exploitation/cmdstager/base.rb +170 -0
- data/lib/rex/exploitation/cmdstager/debug_asm.rb +142 -0
- data/lib/rex/exploitation/cmdstager/debug_write.rb +136 -0
- data/lib/rex/exploitation/cmdstager/tftp.rb +63 -0
- data/lib/rex/exploitation/cmdstager/vbs.rb +128 -0
- data/lib/rex/io/stream.rb +2 -2
- data/lib/rex/io/stream_server.rb +1 -1
- data/lib/rex/job_container.rb +7 -6
- data/lib/rex/mime/header.rb +12 -10
- data/lib/rex/mime/message.rb +57 -26
- data/lib/rex/ole/directory.rb +5 -4
- data/lib/rex/ole/samples/create_ole.rb +0 -0
- data/lib/rex/ole/samples/dir.rb +0 -0
- data/lib/rex/ole/samples/dump_stream.rb +1 -1
- data/lib/rex/ole/samples/ole_info.rb +0 -0
- data/lib/rex/parser/nexpose_xml.rb +131 -0
- data/lib/rex/parser/nmap_xml.rb +1 -0
- data/lib/rex/peparsey/pe.rb +21 -3
- data/lib/rex/post/meterpreter/client.rb +6 -1
- data/lib/rex/post/meterpreter/client_core.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +19 -18
- data/lib/rex/post/meterpreter/packet.rb +68 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +2 -2
- data/lib/rex/post/meterpreter/packet_response_waiter.rb +5 -5
- data/lib/rex/post/meterpreter/ui/console.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +5 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +2 -2
- data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -0
- data/lib/rex/proto/http/client.rb +8 -3
- data/lib/rex/proto/http/packet.rb +11 -1
- data/lib/rex/proto/smb/client.rb +1 -1
- data/lib/rex/proto/smb/utils.rb +72 -24
- data/lib/rex/proto/tftp.rb +3 -0
- data/lib/rex/proto/tftp/constants.rb +37 -0
- data/lib/rex/proto/tftp/server.rb +249 -0
- data/lib/rex/proto/tftp/server.rb.ut.rb +28 -0
- data/lib/rex/script/meterpreter.rb +6 -0
- data/lib/rex/services/local_relay.rb +2 -2
- data/lib/rex/socket/ip.rb +9 -8
- data/lib/rex/socket/range_walker.rb +43 -5
- data/lib/rex/socket/udp.rb +11 -4
- data/lib/rex/text.rb +42 -19
- data/lib/rex/ui/interactive.rb +24 -22
- data/lib/rex/ui/text/irb_shell.rb +4 -2
- data/lib/rex/ui/text/output/file.rb +6 -0
- data/lib/rex/ui/text/shell.rb +14 -18
- data/lib/rex/zip/samples/comment.rb +0 -0
- data/lib/rex/zip/samples/mkwar.rb +0 -0
- data/lib/rex/zip/samples/mkzip.rb +0 -0
- data/lib/rex/zip/samples/recursive.rb +0 -0
- metadata +20 -5
data/lib/rex/mime/message.rb
CHANGED
@@ -4,47 +4,72 @@ class Message
|
|
4
4
|
|
5
5
|
require 'rex/mime/header'
|
6
6
|
require 'rex/mime/part'
|
7
|
-
require 'rex/text'
|
7
|
+
require 'rex/text'
|
8
8
|
|
9
9
|
attr_accessor :header, :parts, :bound, :content
|
10
10
|
|
11
|
-
def initialize
|
11
|
+
def initialize(data=nil)
|
12
12
|
self.header = Rex::MIME::Header.new
|
13
13
|
self.parts = []
|
14
14
|
self.bound = "_Part_#{rand(1024)}_#{rand(0xffffffff)}_#{rand(0xffffffff)}"
|
15
15
|
self.content = ''
|
16
|
+
if data
|
17
|
+
head,body = data.split(/\r?\n\r?\n/, 2)
|
18
|
+
|
19
|
+
self.header.parse(head)
|
20
|
+
ctype = self.header.find('Content-Type')
|
21
|
+
|
22
|
+
if ctype and ctype[1] and ctype[1] =~ /multipart\/mixed;\s*boundary=([^\s]+)/
|
23
|
+
self.bound = $1
|
24
|
+
|
25
|
+
chunks = body.to_s.split(/--#{self.bound}(--)?\r?\n/)
|
26
|
+
self.content = chunks.shift.to_s.gsub(/\s+$/, '')
|
27
|
+
self.content << "\r\n" if not self.content.empty?
|
28
|
+
|
29
|
+
chunks.each do |chunk|
|
30
|
+
break if chunk == "--"
|
31
|
+
head,body = chunk.split(/\r?\n\r?\n/, 2)
|
32
|
+
part = Rex::MIME::Part.new
|
33
|
+
part.header.parse(head)
|
34
|
+
part.content = body.gsub(/\s+$/, '')
|
35
|
+
self.parts << part
|
36
|
+
end
|
37
|
+
else
|
38
|
+
self.content = body.to_s.gsub(/\s+$/, '') + "\r\n"
|
39
|
+
end
|
40
|
+
end
|
16
41
|
end
|
17
42
|
|
18
43
|
def to
|
19
44
|
(self.header.find('To') || [nil, nil])[1]
|
20
45
|
end
|
21
|
-
|
46
|
+
|
22
47
|
def to=(val)
|
23
48
|
self.header.set("To", val)
|
24
49
|
end
|
25
|
-
|
50
|
+
|
26
51
|
def from=(val)
|
27
|
-
self.header.set("From", val)
|
52
|
+
self.header.set("From", val)
|
28
53
|
end
|
29
|
-
|
54
|
+
|
30
55
|
def from
|
31
56
|
(self.header.find('From') || [nil, nil])[1]
|
32
57
|
end
|
33
|
-
|
58
|
+
|
34
59
|
def subject=(val)
|
35
|
-
self.header.set("Subject", val)
|
60
|
+
self.header.set("Subject", val)
|
36
61
|
end
|
37
|
-
|
62
|
+
|
38
63
|
def subject
|
39
64
|
(self.header.find('Subject') || [nil, nil])[1]
|
40
65
|
end
|
41
|
-
|
66
|
+
|
42
67
|
def mime_defaults
|
43
68
|
self.header.set("MIME-Version", "1.0")
|
44
69
|
self.header.set("Content-Type", "multipart/mixed; boundary=\"#{self.bound}\"")
|
45
70
|
self.header.set("Subject", '') # placeholder
|
46
71
|
self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z"))
|
47
|
-
self.header.set("Message-ID",
|
72
|
+
self.header.set("Message-ID",
|
48
73
|
"<"+
|
49
74
|
Rex::Text.rand_text_alphanumeric(rand(20)+40)+
|
50
75
|
"@"+
|
@@ -55,24 +80,24 @@ class Message
|
|
55
80
|
self.header.set("To", '') # placeholder
|
56
81
|
end
|
57
82
|
|
58
|
-
|
83
|
+
|
59
84
|
def add_part(data='', content_type='text/plain', transfer_encoding="8bit", content_disposition=nil)
|
60
85
|
part = Rex::MIME::Part.new
|
61
86
|
part.header.set("Content-Type", content_type)
|
62
|
-
|
87
|
+
|
63
88
|
if (transfer_encoding)
|
64
89
|
part.header.set("Content-Transfer-Encoding", transfer_encoding)
|
65
90
|
end
|
66
|
-
|
91
|
+
|
67
92
|
if (content_disposition)
|
68
93
|
part.header.set("Content-Disposition", content_disposition)
|
69
94
|
end
|
70
|
-
|
95
|
+
|
71
96
|
part.content = data
|
72
97
|
self.parts << part
|
73
98
|
part
|
74
99
|
end
|
75
|
-
|
100
|
+
|
76
101
|
def add_part_attachment(data, name)
|
77
102
|
self.add_part(
|
78
103
|
Rex::Text.encode_base64(data, "\r\n"),
|
@@ -81,7 +106,7 @@ class Message
|
|
81
106
|
"attachment; filename=\"#{name}\""
|
82
107
|
)
|
83
108
|
end
|
84
|
-
|
109
|
+
|
85
110
|
|
86
111
|
def add_part_inline_attachment(data, name)
|
87
112
|
self.add_part(
|
@@ -91,22 +116,28 @@ class Message
|
|
91
116
|
"inline; filename=\"#{name}\""
|
92
117
|
)
|
93
118
|
end
|
94
|
-
|
119
|
+
|
95
120
|
def to_s
|
96
121
|
msg = self.header.to_s + "\r\n"
|
97
|
-
|
98
|
-
|
99
|
-
|
122
|
+
|
123
|
+
if self.content and not self.content.empty?
|
124
|
+
msg << self.content + "\r\n"
|
125
|
+
end
|
126
|
+
|
100
127
|
self.parts.each do |part|
|
101
128
|
msg << "--" + self.bound + "\r\n"
|
102
|
-
msg << part.to_s
|
129
|
+
msg << part.to_s + "\r\n"
|
130
|
+
end
|
131
|
+
|
132
|
+
if self.parts.length > 0
|
133
|
+
msg << "--" + self.bound + "--\r\n"
|
103
134
|
end
|
104
135
|
|
105
|
-
|
106
|
-
|
107
|
-
msg
|
136
|
+
# Force CRLF for SMTP compatibility
|
137
|
+
msg.gsub("\r", '').gsub("\n", "\r\n")
|
108
138
|
end
|
109
139
|
|
110
140
|
end
|
111
141
|
end
|
112
|
-
end
|
142
|
+
end
|
143
|
+
|
data/lib/rex/ole/directory.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
##
|
2
|
-
# $Id: directory.rb
|
3
|
-
# Version: $Revision:
|
2
|
+
# $Id: directory.rb 9287 2010-05-12 05:33:35Z jduck $
|
3
|
+
# Version: $Revision: 9287 $
|
4
4
|
##
|
5
5
|
|
6
6
|
##
|
@@ -51,7 +51,6 @@ class Directory < DirEntry
|
|
51
51
|
child.sid = @num_entries
|
52
52
|
@num_entries += 1
|
53
53
|
|
54
|
-
|
55
54
|
# link item to siblings and/or parent
|
56
55
|
if (parent._sidChild == DIR_NOSTREAM)
|
57
56
|
parent._sidChild = child.sid
|
@@ -72,7 +71,9 @@ class Directory < DirEntry
|
|
72
71
|
break
|
73
72
|
end
|
74
73
|
}
|
75
|
-
|
74
|
+
if (not sib)
|
75
|
+
raise RuntimeError, 'Unable to find a sibling to link to in the directory'
|
76
|
+
end
|
76
77
|
end
|
77
78
|
parent << child
|
78
79
|
end
|
File without changes
|
data/lib/rex/ole/samples/dir.rb
CHANGED
File without changes
|
@@ -23,7 +23,7 @@ if (stg = Rex::OLE::Storage.new(document))
|
|
23
23
|
data = stm.read(stm.length)
|
24
24
|
data ||= ""
|
25
25
|
$stderr.puts "Successfully opened the \"%s\" stream (%u bytes)" % [stream, data.length]
|
26
|
-
$stdout.
|
26
|
+
$stdout.print data
|
27
27
|
stm.close
|
28
28
|
else
|
29
29
|
$stderr.puts "Unable to open stream: #{stream}"
|
File without changes
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Rex
|
2
|
+
module Parser
|
3
|
+
|
4
|
+
# XXX doesn't tie services to vulns
|
5
|
+
class NexposeXMLStreamParser
|
6
|
+
|
7
|
+
attr_accessor :callback
|
8
|
+
|
9
|
+
def initialize(callback = nil)
|
10
|
+
reset_state
|
11
|
+
self.callback = callback if callback
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset_state
|
15
|
+
@state = :generic_state
|
16
|
+
@host = { "status" => nil, "endpoints" => [], "names" => [], "vulns" => {} }
|
17
|
+
@vuln = { "refs" => [] }
|
18
|
+
end
|
19
|
+
|
20
|
+
def tag_start(name, attributes)
|
21
|
+
case name
|
22
|
+
when "node"
|
23
|
+
@host["hardware-address"] = attributes["hardware-address"]
|
24
|
+
@host["addr"] = attributes["address"]
|
25
|
+
@host["status"] = attributes["status"]
|
26
|
+
when "os"
|
27
|
+
# Take only the highest certainty
|
28
|
+
if not @host["os_certainty"] or (@host["os_certainty"].to_f < attributes["certainty"].to_f)
|
29
|
+
@host["os_vendor"] = attributes["vendor"]
|
30
|
+
@host["os_family"] = attributes["family"]
|
31
|
+
@host["os_product"] = attributes["product"]
|
32
|
+
@host["arch"] = attributes["arch"]
|
33
|
+
@host["os_certainty"] = attributes["certainty"]
|
34
|
+
end
|
35
|
+
when "name"
|
36
|
+
#@host["names"].push attributes["name"]
|
37
|
+
@state = :in_name
|
38
|
+
when "endpoint"
|
39
|
+
# This is a port in NeXpose parlance
|
40
|
+
@host["endpoints"].push(attributes)
|
41
|
+
when "service"
|
42
|
+
@state = :in_service
|
43
|
+
# Store any service info with the associated port. There shouldn't
|
44
|
+
# be any collisions on attribute names here, so just merge them.
|
45
|
+
@host["endpoints"].last.merge!(attributes)
|
46
|
+
when "fingerprint"
|
47
|
+
if @state == :in_service
|
48
|
+
@host["endpoints"].last.merge!(attributes)
|
49
|
+
end
|
50
|
+
when "test"
|
51
|
+
if attributes["status"] == "vulnerable-exploited" or attributes["status"] == "vulnerable-version"
|
52
|
+
@host["vulns"][attributes["id"]] = attributes.dup
|
53
|
+
end
|
54
|
+
when "vulnerability"
|
55
|
+
@vuln.merge! attributes
|
56
|
+
when "reference"
|
57
|
+
@state = :in_reference
|
58
|
+
@vuln["refs"].push attributes
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def text(str)
|
63
|
+
case @state
|
64
|
+
when :in_name
|
65
|
+
@host["names"].push str
|
66
|
+
when :in_reference
|
67
|
+
@vuln["refs"].last["value"] = str
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def tag_end(name)
|
72
|
+
case name
|
73
|
+
when "node"
|
74
|
+
callback.call(:host, @host) if callback
|
75
|
+
reset_state
|
76
|
+
when "vulnerability"
|
77
|
+
callback.call(:vuln, @vuln) if callback
|
78
|
+
reset_state
|
79
|
+
when "service","reference"
|
80
|
+
@state = :generic_state
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# We don't need these methods, but they're necessary to keep REXML happy
|
85
|
+
def xmldecl(version, encoding, standalone); end
|
86
|
+
def cdata; end
|
87
|
+
def comment(str); end
|
88
|
+
def instruction(name, instruction); end
|
89
|
+
def attlist; end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
__END__
|
95
|
+
|
96
|
+
<node address="10.1.1.10" status="alive" hardware-address="0007371F3BE8">
|
97
|
+
<names>
|
98
|
+
<name>NETBIOSNAME</name>
|
99
|
+
<name>hostname.example.com</name>
|
100
|
+
</names>
|
101
|
+
<fingerprints>
|
102
|
+
<os certainty="1.00" device-class="Domain controller" vendor="Microsoft" family="Windows" product="Windows Server 2003, Standard Edition" version="SP2" arch="x86"/>
|
103
|
+
<os certainty="0.85" device-class="General" vendor="Microsoft" family="Windows" product="Windows Server 2003"/>
|
104
|
+
<os certainty="0.70" vendor="Microsoft" family="Windows" product="Windows Server 2003"/>
|
105
|
+
</fingerprints>
|
106
|
+
<software>
|
107
|
+
<fingerprint certainty="1.00" vendor="Acronis" product="Acronis True Image Echo Server" version="9.5.8163"/>
|
108
|
+
<fingerprint certainty="1.00" vendor="Acronis" product="Acronis Universal Restore for Acronis True Image Echo Server" version="9.5.8076"/>
|
109
|
+
<fingerprint certainty="1.00" software-class="Internet Client" vendor="Microsoft" family="Internet Explorer" product="Internet Explorer" version="7.0.5730.11"/>
|
110
|
+
<fingerprint certainty="1.00" software-class="Database Client" vendor="Microsoft" family="MDAC" product="MDAC" version="2.8"/>
|
111
|
+
<fingerprint certainty="1.00" software-class="Media Client" vendor="Microsoft" family="Windows Media Player" product="Windows Media Player" version="10.0.0.3997"/>
|
112
|
+
<fingerprint certainty="1.00" vendor="MySolutions NORDIC" product="NSClient++ (Win32)" version="0.3.4.0"/>
|
113
|
+
<fingerprint certainty="1.00" vendor="Symantec Corporation" product="LiveUpdate 3.1 (Symantec Corporation)" version="3.1.0.99"/>
|
114
|
+
<fingerprint certainty="1.00" vendor="Symantec Corporation" product="Symantec AntiVirus" version="10.1.5000.5"/>
|
115
|
+
</software>
|
116
|
+
<tests>
|
117
|
+
<test status="not-vulnerable" id="backdoor-ckb.cfaae1e6">
|
118
|
+
|
119
|
+
<endpoint protocol="tcp" port="139" status="open">
|
120
|
+
<services>
|
121
|
+
<service name="CIFS">
|
122
|
+
<fingerprints>
|
123
|
+
<fingerprint certainty="1.00" product="Windows Server 2003 R2 5.2"/>
|
124
|
+
</fingerprints>
|
125
|
+
<tests>
|
126
|
+
</tests>
|
127
|
+
</service>
|
128
|
+
</services>
|
129
|
+
</endpoint>
|
130
|
+
</node>
|
131
|
+
|
data/lib/rex/parser/nmap_xml.rb
CHANGED
@@ -77,6 +77,7 @@ class NmapXMLStreamParser
|
|
77
77
|
when "status"
|
78
78
|
# <status> refers to the liveness of the host; values are "up" or "down"
|
79
79
|
@host["status"] = attributes["state"]
|
80
|
+
@host["status_reason"] = attributes["reason"]
|
80
81
|
when "port"
|
81
82
|
@host["ports"].push(attributes)
|
82
83
|
when "state"
|
data/lib/rex/peparsey/pe.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# $Id: pe.rb
|
3
|
+
# $Id: pe.rb 9272 2010-05-10 16:18:19Z jduck $
|
4
4
|
|
5
5
|
require 'rex/image_source'
|
6
6
|
require 'rex/peparsey/exceptions'
|
@@ -143,7 +143,7 @@ class Pe < PeBase
|
|
143
143
|
self.hdr.config = self._config_header
|
144
144
|
self.hdr.tls = self._tls_header
|
145
145
|
self.hdr.exceptions = self._exception_header
|
146
|
-
|
146
|
+
|
147
147
|
# We load the exception directory last as it relies on hdr.file to be created above.
|
148
148
|
self._exception_header = _load_exception_directory()
|
149
149
|
end
|
@@ -184,5 +184,23 @@ class Pe < PeBase
|
|
184
184
|
(ptr_32?) ? ("0x%.8x" % va) : ("0x%.16x" % va)
|
185
185
|
end
|
186
186
|
|
187
|
-
|
187
|
+
#
|
188
|
+
# Converts a file offset into a virtual address
|
189
|
+
#
|
190
|
+
def file_offset_to_va(offset)
|
191
|
+
image_base + file_offset_to_rva(offset)
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# Read raw bytes from the specified offset in the underlying file
|
196
|
+
#
|
197
|
+
# NOTE: You should pass raw file offsets into this, not offsets from
|
198
|
+
# the beginning of the section. If you need to read from within a
|
199
|
+
# section, add section.file_offset prior to passing the offset in.
|
200
|
+
#
|
201
|
+
def read(offset, len)
|
202
|
+
_isource.read(offset, len)
|
203
|
+
end
|
204
|
+
|
188
205
|
|
206
|
+
end end end
|
@@ -81,13 +81,14 @@ class Client
|
|
81
81
|
self.ext_aliases = ObjectAliases.new
|
82
82
|
self.alive = true
|
83
83
|
self.target_id = opts[:target_id]
|
84
|
+
self.capabilities= opts[:capabilities] || {}
|
84
85
|
|
85
86
|
self.response_timeout = opts[:timeout] || self.class.default_timeout
|
86
87
|
self.send_keepalives = true
|
87
88
|
|
88
89
|
|
89
90
|
# Switch the socket to SSL mode and receive the hello if needed
|
90
|
-
if not opts[:skip_ssl]
|
91
|
+
if capabilities[:ssl] and not opts[:skip_ssl]
|
91
92
|
swap_sock_plain_to_ssl()
|
92
93
|
end
|
93
94
|
|
@@ -325,6 +326,10 @@ class Client
|
|
325
326
|
# The unique target identifier for this payload
|
326
327
|
#
|
327
328
|
attr_accessor :target_id
|
329
|
+
#
|
330
|
+
# The libraries available to this meterpreter server
|
331
|
+
#
|
332
|
+
attr_accessor :capabilities
|
328
333
|
|
329
334
|
protected
|
330
335
|
attr_accessor :parser, :ext_aliases # :nodoc:
|
@@ -89,7 +89,7 @@ class ClientCore < Extension
|
|
89
89
|
}
|
90
90
|
|
91
91
|
if (image != nil)
|
92
|
-
request.add_tlv(TLV_TYPE_DATA, image, false,
|
92
|
+
request.add_tlv(TLV_TYPE_DATA, image, false, client.capabilities[:zlib])
|
93
93
|
else
|
94
94
|
raise RuntimeError, "Failed to serialize library #{library_path}.", caller
|
95
95
|
end
|
@@ -222,7 +222,7 @@ class ClientCore < Extension
|
|
222
222
|
request = Packet.create_request( 'core_migrate' )
|
223
223
|
request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
|
224
224
|
request.add_tlv( TLV_TYPE_MIGRATE_LEN, payload.length )
|
225
|
-
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, payload, false,
|
225
|
+
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, payload, false, client.capabilities[:zlib])
|
226
226
|
if( process['arch'] == ARCH_X86_64 )
|
227
227
|
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
|
228
228
|
else
|
@@ -24,10 +24,10 @@ class Priv < Extension
|
|
24
24
|
#
|
25
25
|
def initialize(client)
|
26
26
|
super(client, 'priv')
|
27
|
-
|
27
|
+
|
28
28
|
client.register_extension_aliases(
|
29
29
|
[
|
30
|
-
{
|
30
|
+
{
|
31
31
|
'name' => 'priv',
|
32
32
|
'ext' => self
|
33
33
|
},
|
@@ -36,25 +36,25 @@ class Priv < Extension
|
|
36
36
|
# Initialize sub-classes
|
37
37
|
self.fs = Fs.new(client)
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
#
|
41
41
|
# Attempt to elevate the meterpreter to Local SYSTEM
|
42
42
|
#
|
43
43
|
def getsystem( technique=0 )
|
44
44
|
request = Packet.create_request( 'priv_elevate_getsystem' )
|
45
|
-
|
46
|
-
elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
|
47
|
-
|
45
|
+
|
46
|
+
elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
|
47
|
+
|
48
48
|
if( client.platform == 'x64/win64' )
|
49
49
|
elevator_path = ::File.join( Msf::Config.install_root, "data", "meterpreter", "elevator.x64.dll" )
|
50
50
|
else
|
51
51
|
elevator_path = ::File.join( Msf::Config.install_root, "data", "meterpreter", "elevator.dll" )
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
elevator_path = ::File.expand_path( elevator_path )
|
55
|
-
|
55
|
+
|
56
56
|
elevator_data = ""
|
57
|
-
|
57
|
+
|
58
58
|
::File.open( elevator_path, "rb" ) { |f|
|
59
59
|
elevator_data += f.read( f.stat.size )
|
60
60
|
}
|
@@ -63,29 +63,29 @@ class Priv < Extension
|
|
63
63
|
request.add_tlv( TLV_TYPE_ELEVATE_SERVICE_NAME, elevator_name )
|
64
64
|
request.add_tlv( TLV_TYPE_ELEVATE_SERVICE_DLL, elevator_data )
|
65
65
|
request.add_tlv( TLV_TYPE_ELEVATE_SERVICE_LENGTH, elevator_data.length )
|
66
|
-
|
66
|
+
|
67
67
|
# as some service routines can be slow we bump up the timeout to 90 seconds
|
68
68
|
response = client.send_request( request, 90 )
|
69
|
-
|
69
|
+
|
70
70
|
technique = response.get_tlv_value( TLV_TYPE_ELEVATE_TECHNIQUE )
|
71
|
-
|
71
|
+
|
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
75
|
return [ true, technique ]
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
return [ false, 0 ]
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
#
|
82
82
|
# Returns an array of SAM hashes from the remote machine.
|
83
83
|
#
|
84
84
|
def sam_hashes
|
85
|
-
|
86
|
-
|
85
|
+
# This can take a long long time for large domain controls, bump the timeout to one hour
|
86
|
+
response = client.send_request(Packet.create_request('priv_passwd_get_sam_hashes'), 3600)
|
87
87
|
|
88
|
-
response.get_tlv_value(TLV_TYPE_SAM_HASHES).split(/\n/).map { |hash|
|
88
|
+
response.get_tlv_value(TLV_TYPE_SAM_HASHES).split(/\n/).map { |hash|
|
89
89
|
SamUser.new(hash)
|
90
90
|
}
|
91
91
|
end
|
@@ -101,4 +101,5 @@ protected
|
|
101
101
|
|
102
102
|
end
|
103
103
|
|
104
|
-
end; end; end; end; end
|
104
|
+
end; end; end; end; end
|
105
|
+
|