Land #3085, service_control support
This depends on rapid7/meterpreter#77 to functionbug/bundler_fix
commit
8e7f12e30e
|
@ -15,18 +15,26 @@ module Service
|
|||
###
|
||||
class Service
|
||||
|
||||
SERVICE_OP_START = 1
|
||||
SERVICE_OP_PAUSE = 2
|
||||
SERVICE_OP_RESUME = 3
|
||||
SERVICE_OP_STOP = 4
|
||||
SERVICE_OP_RESTART = 5
|
||||
|
||||
def initialize(client)
|
||||
@client = client
|
||||
end
|
||||
|
||||
#
|
||||
# Enumerate all the services on the target.
|
||||
#
|
||||
def enumerate
|
||||
request = Packet.create_request('extapi_service_enum')
|
||||
response = client.send_request(request)
|
||||
|
||||
services = []
|
||||
|
||||
response.each(TLV_TYPE_EXT_SERVICE_ENUM_GROUP) { |s|
|
||||
response.each(TLV_TYPE_EXT_SERVICE_ENUM_GROUP) do |s|
|
||||
services << {
|
||||
:name => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_NAME),
|
||||
:display => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME),
|
||||
|
@ -34,29 +42,59 @@ class Service
|
|||
:status => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_STATUS),
|
||||
:interactive => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
return services.sort_by { |s| s[:name].upcase }
|
||||
services.sort_by { |s| s[:name].upcase }
|
||||
end
|
||||
|
||||
#
|
||||
# Query some detailed parameters about a particular service.
|
||||
#
|
||||
def query(service_name)
|
||||
request = Packet.create_request('extapi_service_query')
|
||||
request.add_tlv(TLV_TYPE_EXT_SERVICE_ENUM_NAME, service_name)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
detail = {
|
||||
{
|
||||
:starttype => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE),
|
||||
:display => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME),
|
||||
:startname => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME),
|
||||
:path => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_PATH),
|
||||
:logroup => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP),
|
||||
:interactive => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE),
|
||||
:dacl => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_DACL)
|
||||
:dacl => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_DACL),
|
||||
:status => response.get_tlv_value(TLV_TYPE_EXT_SERVICE_QUERY_STATUS)
|
||||
}
|
||||
end
|
||||
|
||||
return detail
|
||||
#
|
||||
# Control a single service
|
||||
#
|
||||
def control(service_name, op)
|
||||
if op.is_a? String
|
||||
case op.strip.downcase
|
||||
when "start"
|
||||
op = SERVICE_OP_START
|
||||
when "pause"
|
||||
op = SERVICE_OP_PAUSE
|
||||
when "resume"
|
||||
op = SERVICE_OP_RESUME
|
||||
when "stop"
|
||||
op = SERVICE_OP_STOP
|
||||
when "restart"
|
||||
op = SERVICE_OP_RESTART
|
||||
end
|
||||
end
|
||||
|
||||
unless (op.is_a? Integer) && op >= SERVICE_OP_START && op <= SERVICE_OP_RESTART
|
||||
raise ArgumentError, "Invalid operation: #{op}"
|
||||
end
|
||||
|
||||
request = Packet.create_request('extapi_service_control')
|
||||
request.add_tlv(TLV_TYPE_EXT_SERVICE_CTRL_NAME, service_name)
|
||||
request.add_tlv(TLV_TYPE_EXT_SERVICE_CTRL_OP, op)
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
attr_accessor :client
|
||||
|
|
|
@ -27,6 +27,10 @@ TLV_TYPE_EXT_SERVICE_QUERY_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_E
|
|||
TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 24)
|
||||
TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 25)
|
||||
TLV_TYPE_EXT_SERVICE_QUERY_DACL = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 26)
|
||||
TLV_TYPE_EXT_SERVICE_QUERY_STATUS = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 27)
|
||||
|
||||
TLV_TYPE_EXT_SERVICE_CTRL_NAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 28)
|
||||
TLV_TYPE_EXT_SERVICE_CTRL_OP = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 29)
|
||||
|
||||
TLV_TYPE_EXT_CLIPBOARD_DOWNLOAD = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 35)
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
#
|
||||
def commands
|
||||
{
|
||||
"service_enum" => "Enumerate all registered Windows services",
|
||||
"service_query" => "Query more detail about a specific Windows service"
|
||||
"service_enum" => "Enumerate all registered Windows services",
|
||||
"service_query" => "Query more detail about a specific Windows service",
|
||||
"service_control" => "Control a single service (start/pause/resume/stop/restart)"
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -33,6 +34,32 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
def name
|
||||
"Extapi: Service Management"
|
||||
end
|
||||
|
||||
#
|
||||
# Initialize the instance
|
||||
#
|
||||
def initialize(shell)
|
||||
super
|
||||
|
||||
@status_map = {
|
||||
1 => "Stopped",
|
||||
2 => "Starting",
|
||||
3 => "Stopping",
|
||||
4 => "Running",
|
||||
5 => "Continuing",
|
||||
6 => "Pausing",
|
||||
7 => "Paused"
|
||||
}
|
||||
|
||||
@start_type_map = {
|
||||
0 => "Boot",
|
||||
1 => "System",
|
||||
2 => "Automatic",
|
||||
3 => "Manual",
|
||||
4 => "Disabled"
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Options for the service_enum command.
|
||||
#
|
||||
|
@ -44,7 +71,7 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
# Query a single service for more detail.
|
||||
#
|
||||
def cmd_service_enum(*args)
|
||||
@@service_enum_opts.parse(args) { |opt, idx, val|
|
||||
@@service_enum_opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
|
@ -55,17 +82,7 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
"able to interact with the desktop.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
status_map = {
|
||||
1 => "Stopped",
|
||||
2 => "Starting",
|
||||
3 => "Stopping",
|
||||
4 => "Running",
|
||||
5 => "Continuing",
|
||||
6 => "Pausing",
|
||||
7 => "Paused"
|
||||
}
|
||||
end
|
||||
|
||||
services = client.extapi.service.enumerate
|
||||
|
||||
|
@ -78,14 +95,14 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
]
|
||||
)
|
||||
|
||||
services.each { |s|
|
||||
services.each do |s|
|
||||
table << [
|
||||
s[:pid],
|
||||
status_map[s[:status]],
|
||||
@status_map[s[:status]],
|
||||
s[:interactive] ? "Y" : "N",
|
||||
"#{s[:name].downcase} (#{s[:display]})"
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line(table.to_s)
|
||||
|
@ -107,9 +124,9 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
# Query a single service for more detail.
|
||||
#
|
||||
def cmd_service_query(*args)
|
||||
args << "-h" if args.length == 0
|
||||
args.unshift("-h") if args.length != 1
|
||||
|
||||
@@service_query_opts.parse(args) { |opt, idx, val|
|
||||
@@service_query_opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
|
@ -119,25 +136,18 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
"binary path, DACL, load order group, start type and more.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
service_name = args.shift
|
||||
|
||||
start_type_map = {
|
||||
0 => "Boot",
|
||||
1 => "System",
|
||||
2 => "Automatic",
|
||||
3 => "Manual",
|
||||
4 => "Disabled"
|
||||
}
|
||||
|
||||
detail = client.extapi.service.query(service_name)
|
||||
|
||||
print_line
|
||||
print_line("Name : #{service_name}")
|
||||
print_line("Display : #{detail[:display]}")
|
||||
print_line("Account : #{detail[:startname]}")
|
||||
print_line("Start Type : #{start_type_map[detail[:starttype]]}")
|
||||
print_line("Status : #{@status_map[detail[:status]]}")
|
||||
print_line("Start Type : #{@start_type_map[detail[:starttype]]}")
|
||||
print_line("Path : #{detail[:path]}")
|
||||
print_line("L.O. Group : #{detail[:logroup]}")
|
||||
print_line("Interactive : #{detail[:interactive] ? "Yes" : "No"}")
|
||||
|
@ -146,6 +156,39 @@ class Console::CommandDispatcher::Extapi::Service
|
|||
|
||||
end
|
||||
|
||||
#
|
||||
# Options for the service_control command.
|
||||
#
|
||||
@@service_control_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Query a single service for more detail.
|
||||
#
|
||||
def cmd_service_control(*args)
|
||||
args.unshift("-h") if args.length != 2
|
||||
|
||||
@@service_control_opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: service_control [-h] <servicename> <op>\n" +
|
||||
" <servicename> : The name of the service to control.\n" +
|
||||
" <op> : The operation to perform on the service.\n" +
|
||||
" Valid ops: start pause resume stop restart.\n\n")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
service_name = args[0]
|
||||
op = args[1]
|
||||
|
||||
client.extapi.service.control(service_name, op)
|
||||
|
||||
print_good("Operation #{op} succeeded.")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue