2012-06-29 00:18:28 -05:00
|
|
|
# -*- coding: binary -*-
|
2011-05-12 20:03:55 +00:00
|
|
|
require 'rex/encoder/ndr'
|
2005-06-05 05:42:43 +00:00
|
|
|
module Msf
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
#
|
|
|
|
|
# This mixin provides utility methods for interacting with a DCERPC service on
|
|
|
|
|
# a remote machine. These methods may generally be useful in the context of
|
2010-07-09 18:03:48 +00:00
|
|
|
# exploitation. This mixin extends the Tcp exploit mixin. Only one DCERPC
|
2005-09-16 03:29:27 +00:00
|
|
|
# service can be accessed at a time using this class.
|
2005-06-05 05:42:43 +00:00
|
|
|
#
|
|
|
|
|
###
|
|
|
|
|
module Exploit::Remote::DCERPC
|
|
|
|
|
|
2005-09-16 03:29:27 +00:00
|
|
|
# Alias over the Rex DCERPC protocol modules
|
|
|
|
|
DCERPCPacket = Rex::Proto::DCERPC::Packet
|
|
|
|
|
DCERPCClient = Rex::Proto::DCERPC::Client
|
|
|
|
|
DCERPCResponse = Rex::Proto::DCERPC::Response
|
2013-02-19 12:55:06 -06:00
|
|
|
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
2006-06-13 21:27:01 +00:00
|
|
|
NDR = Rex::Encoder::NDR
|
2005-12-13 06:08:40 +00:00
|
|
|
|
2007-04-14 05:22:22 +00:00
|
|
|
|
|
|
|
|
# Support TCP-based RPC services
|
|
|
|
|
include Exploit::Remote::Tcp
|
2010-07-09 18:03:48 +00:00
|
|
|
|
|
|
|
|
# Helper methods for specific services
|
2007-04-14 05:22:22 +00:00
|
|
|
include Exploit::Remote::DCERPC_EPM
|
|
|
|
|
include Exploit::Remote::DCERPC_MGMT
|
2007-06-09 02:26:35 +00:00
|
|
|
include Exploit::Remote::DCERPC_LSA
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2005-06-05 06:07:18 +00:00
|
|
|
def initialize(info = {})
|
2005-06-05 23:45:58 +00:00
|
|
|
super
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
register_evasion_options(
|
2005-10-03 13:51:05 +00:00
|
|
|
[
|
2006-04-30 19:49:27 +00:00
|
|
|
OptInt.new('DCERPC::max_frag_size', [ true, 'Set the DCERPC packet fragmentation size', 4096]),
|
2011-07-23 13:47:41 +00:00
|
|
|
OptBool.new('DCERPC::fake_bind_multi', [ false, 'Use multi-context bind calls', true ]),
|
2006-05-03 05:53:37 +00:00
|
|
|
OptInt.new('DCERPC::fake_bind_multi_prepend', [ false, 'Set the number of UUIDs to prepend before the target', 0]),
|
|
|
|
|
OptInt.new('DCERPC::fake_bind_multi_append', [ false, 'Set the number of UUIDs to append the target', 0]),
|
|
|
|
|
OptEnum.new('DCERPC::smb_pipeio', [ false, 'Use a different delivery method for accessing named pipes', 'rw', ['rw', 'trans']] )
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2005-10-03 13:51:05 +00:00
|
|
|
], Msf::Exploit::Remote::DCERPC)
|
|
|
|
|
|
2005-06-05 23:45:58 +00:00
|
|
|
register_options(
|
|
|
|
|
[
|
|
|
|
|
Opt::RHOST,
|
2005-07-17 10:30:11 +00:00
|
|
|
Opt::RPORT(135),
|
2008-01-28 03:06:31 +00:00
|
|
|
], Msf::Exploit::Remote::DCERPC)
|
|
|
|
|
|
|
|
|
|
register_advanced_options(
|
|
|
|
|
[
|
2010-07-09 18:03:48 +00:00
|
|
|
OptInt.new('DCERPC::ReadTimeout', [ true, 'The number of seconds to wait for DCERPC responses', 10] )
|
|
|
|
|
], Msf::Exploit::Remote::DCERPC)
|
2008-01-28 03:06:31 +00:00
|
|
|
|
2005-06-05 05:42:43 +00:00
|
|
|
end
|
2005-06-05 08:38:24 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
def dcerpc_handle(uuid, version, protocol, opts)
|
2023-11-14 18:20:14 +00:00
|
|
|
dcerpc_handle_target(uuid, version, protocol, opts, rhost)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def dcerpc_handle_target(uuid, version, protocol, opts, target)
|
|
|
|
|
self.handle = Rex::Proto::DCERPC::Handle.new([uuid, version], protocol, target, opts)
|
2005-12-15 04:46:52 +00:00
|
|
|
end
|
|
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
def dcerpc_bind(h)
|
2005-12-15 04:46:52 +00:00
|
|
|
opts = { 'Msf' => framework, 'MsfExploit' => self }
|
2005-09-16 03:29:27 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
if datastore['DCERPC::max_frag_size']
|
|
|
|
|
opts['frag_size'] = datastore['DCERPC::max_frag_size']
|
2005-12-15 04:46:52 +00:00
|
|
|
end
|
2005-09-16 03:29:27 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
if datastore['DCERPC::fake_bind_multi']
|
2005-12-15 04:46:52 +00:00
|
|
|
opts['fake_multi_bind'] = 1
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2006-05-03 05:53:37 +00:00
|
|
|
if datastore['DCERPC::fake_bind_multi_prepend']
|
|
|
|
|
opts['fake_multi_bind_prepend'] = datastore['DCERPC::fake_bind_multi_prepend']
|
|
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2006-05-03 05:53:37 +00:00
|
|
|
if datastore['DCERPC::fake_bind_multi_append']
|
|
|
|
|
opts['fake_multi_bind_append'] = datastore['DCERPC::fake_bind_multi_append']
|
2010-07-09 18:03:48 +00:00
|
|
|
end
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
opts['connect_timeout'] = (datastore['ConnectTimeout'] || 10).to_i
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
opts['read_timeout'] = (datastore['DCERPC::ReadTimeout'] || 10).to_i
|
2010-07-09 18:03:48 +00:00
|
|
|
|
|
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
# Configure the SMB evasion options
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
if (datastore['SMBUser'])
|
2007-02-18 07:06:30 +00:00
|
|
|
opts['smb_user'] = datastore['SMBUser']
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
if (datastore['SMBPass'])
|
2007-02-18 07:06:30 +00:00
|
|
|
opts['smb_pass'] = datastore['SMBPass']
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2005-11-16 17:56:07 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
if (datastore['DCERPC::smb_pipeio'])
|
2006-05-03 05:53:37 +00:00
|
|
|
opts['smb_pipeio'] = datastore['DCERPC::smb_pipeio']
|
|
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2008-04-04 20:54:39 +00:00
|
|
|
if (datastore['SMB::pipe_write_min_size'])
|
|
|
|
|
opts['pipe_write_min_size'] = datastore['SMB::pipe_write_min_size']
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (datastore['SMB::pipe_write_max_size'])
|
|
|
|
|
opts['pipe_write_max_size'] = datastore['SMB::pipe_write_max_size']
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (datastore['SMB::pipe_read_min_size'])
|
|
|
|
|
opts['pipe_read_min_size'] = datastore['SMB::pipe_read_min_size']
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (datastore['SMB::pipe_read_max_size'])
|
|
|
|
|
opts['pipe_read_max_size'] = datastore['SMB::pipe_read_max_size']
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (self.respond_to?('simple') and self.simple)
|
2006-04-30 19:49:27 +00:00
|
|
|
opts['smb_client'] = self.simple
|
|
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
|
|
|
|
# Create the DCERPC client
|
2007-02-26 17:38:01 +00:00
|
|
|
self.dcerpc = Rex::Proto::DCERPC::Client.new(h, self.sock, opts)
|
2005-09-16 03:29:27 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
if (self.handle.protocol == 'ncacn_np' and not self.simple)
|
2005-12-15 04:46:52 +00:00
|
|
|
self.simple = self.dcerpc.smb # expose the simple client if we have access to it
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2011-01-11 17:56:27 +00:00
|
|
|
def dcerpc_call(function, stub = '', timeout=nil, do_recv=true)
|
2008-01-28 03:06:31 +00:00
|
|
|
otimeout = dcerpc.options['read_timeout']
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
begin
|
2008-01-28 03:06:31 +00:00
|
|
|
dcerpc.options['read_timeout'] = timeout if timeout
|
2011-01-11 17:56:27 +00:00
|
|
|
dcerpc.call(function, stub, do_recv)
|
2006-04-30 19:49:27 +00:00
|
|
|
rescue ::Rex::Proto::SMB::Exceptions::NoReply, Rex::Proto::DCERPC::Exceptions::NoResponse
|
|
|
|
|
print_status("The DCERPC service did not reply to our request")
|
|
|
|
|
return
|
2008-01-28 03:06:31 +00:00
|
|
|
ensure
|
|
|
|
|
dcerpc.options['read_timeout'] = otimeout
|
2006-04-30 19:49:27 +00:00
|
|
|
end
|
2005-12-15 04:46:52 +00:00
|
|
|
end
|
2005-09-16 03:29:27 +00:00
|
|
|
|
2017-12-13 22:39:15 -06:00
|
|
|
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
|
|
|
|
|
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
|
|
|
|
|
def dcerpc_getarch
|
|
|
|
|
ret = nil
|
|
|
|
|
|
|
|
|
|
connect_timeout = (datastore['ConnectTimeout'] || 10).to_i
|
|
|
|
|
read_timeout = (datastore['DCERPC::ReadTimeout'] || 10).to_i
|
|
|
|
|
|
|
|
|
|
pkt = Rex::Proto::DCERPC::Packet.make_bind(
|
|
|
|
|
# Abstract Syntax: EPMv4 V3.0
|
|
|
|
|
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
|
|
|
|
|
# Transfer Syntax[1]: 64bit NDR V1
|
|
|
|
|
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
|
|
|
|
|
).first
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
nsock = Rex::Socket::Tcp.create(
|
|
|
|
|
'PeerHost' => rhost,
|
|
|
|
|
'PeerPort' => 135,
|
|
|
|
|
'Proxies' => proxies,
|
|
|
|
|
'Timeout' => connect_timeout,
|
|
|
|
|
'Context' => {
|
|
|
|
|
'Msf' => framework,
|
|
|
|
|
'MsfExploit' => self
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
rescue Rex::ConnectionError => e
|
|
|
|
|
vprint_error(e.to_s)
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
nsock.put(pkt)
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
res = nsock.get_once(60, read_timeout)
|
|
|
|
|
rescue EOFError
|
|
|
|
|
vprint_error('DCE/RPC socket returned EOFError')
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
disconnect(nsock)
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
resp = Rex::Proto::DCERPC::Response.new(res)
|
|
|
|
|
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
|
|
|
|
|
vprint_error(e.to_s)
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Ack result: Acceptance (0)
|
|
|
|
|
if resp.ack_result.first == 0
|
|
|
|
|
ret = ARCH_X64
|
|
|
|
|
end
|
|
|
|
|
# Ack result: Provider rejection (2)
|
|
|
|
|
# Ack reason: Proposed transfer syntaxes not supported (2)
|
|
|
|
|
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
|
|
|
|
|
ret = ARCH_X86
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
end
|
|
|
|
|
|
2005-12-13 06:08:40 +00:00
|
|
|
# Convert a standard ASCII string to 16-bit Unicode
|
2006-04-30 19:49:27 +00:00
|
|
|
def unicode(str)
|
2005-12-13 06:08:40 +00:00
|
|
|
Rex::Text.to_unicode(str)
|
2005-09-16 03:29:27 +00:00
|
|
|
end
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2006-04-30 19:49:27 +00:00
|
|
|
# Useful accessors for tracking DCERPC state
|
2007-02-26 17:38:01 +00:00
|
|
|
attr_accessor :handle, :dcerpc
|
2010-07-09 18:03:48 +00:00
|
|
|
|
2005-06-05 05:42:43 +00:00
|
|
|
end
|
|
|
|
|
|
2008-11-03 09:17:08 +00:00
|
|
|
end
|