Improve extapi ruby structure, add bins
The extapi project will get bigger over time so this change allows for the code to get bigger without becoming a headache before it starts. Added binaries to this commit as well.bug/bundler_fix
parent
cbaeebeff7
commit
b99af52279
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,8 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/meterpreter/extensions/extapi/tlv'
|
||||
require 'rex/post/meterpreter/extensions/extapi/window/window'
|
||||
require 'rex/post/meterpreter/extensions/extapi/service/service'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
|
@ -12,11 +14,7 @@ module Extapi
|
|||
###
|
||||
#
|
||||
# This meterpreter extension contains an extended API which will allow for more
|
||||
# advanced enumeration of the victim. This includes detail of:
|
||||
# * Active/open windows
|
||||
# * Services
|
||||
# * Clipboard
|
||||
# ... and more.
|
||||
# advanced enumeration of the victim.
|
||||
#
|
||||
###
|
||||
class Extapi < Extension
|
||||
|
@ -28,69 +26,15 @@ class Extapi < Extension
|
|||
[
|
||||
{
|
||||
'name' => 'extapi',
|
||||
'ext' => self
|
||||
'ext' => ObjectAliases.new(
|
||||
{
|
||||
'window' => Rex::Post::Meterpreter::Extensions::Extapi::Window::Window.new(client),
|
||||
'service' => Rex::Post::Meterpreter::Extensions::Extapi::Service::Service.new(client)
|
||||
})
|
||||
},
|
||||
])
|
||||
end
|
||||
|
||||
# Enumerate all the top-level windows on the target
|
||||
def window_enum()
|
||||
request = Packet.create_request('extapi_window_enum')
|
||||
response = client.send_request(request)
|
||||
|
||||
windows = []
|
||||
|
||||
response.each(TLV_TYPE_EXT_WINDOW_ENUM_GROUP) { |w|
|
||||
windows << {
|
||||
:pid => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_PID),
|
||||
:handle => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_HANDLE),
|
||||
:title => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_TITLE)
|
||||
}
|
||||
}
|
||||
|
||||
return windows.sort_by { |w| w[:pid] }
|
||||
end
|
||||
|
||||
# Enumerate all the services on the target.
|
||||
def service_enum()
|
||||
request = Packet.create_request('extapi_service_enum')
|
||||
response = client.send_request(request)
|
||||
|
||||
services = []
|
||||
|
||||
response.each(TLV_TYPE_EXT_SERVICE_ENUM_GROUP) { |s|
|
||||
services << {
|
||||
:name => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_NAME),
|
||||
:display => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME),
|
||||
:pid => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_PID),
|
||||
:status => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_STATUS),
|
||||
:interactive => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE)
|
||||
}
|
||||
}
|
||||
|
||||
return services.sort_by { |s| s[:name].upcase }
|
||||
end
|
||||
|
||||
# Query some detailed parameters about a particular service.
|
||||
def service_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)
|
||||
}
|
||||
|
||||
return detail
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Extapi
|
||||
module Service
|
||||
|
||||
###
|
||||
#
|
||||
# This meterpreter extension contains extended API functions for
|
||||
# querying and managing Windows services.
|
||||
#
|
||||
###
|
||||
class Service
|
||||
|
||||
def initialize(client)
|
||||
@client = client
|
||||
end
|
||||
|
||||
# Enumerate all the services on the target.
|
||||
def service_enum()
|
||||
request = Packet.create_request('extapi_service_enum')
|
||||
response = client.send_request(request)
|
||||
|
||||
services = []
|
||||
|
||||
response.each(TLV_TYPE_EXT_SERVICE_ENUM_GROUP) { |s|
|
||||
services << {
|
||||
:name => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_NAME),
|
||||
:display => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME),
|
||||
:pid => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_PID),
|
||||
:status => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_STATUS),
|
||||
:interactive => s.get_tlv_value(TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE)
|
||||
}
|
||||
}
|
||||
|
||||
return services.sort_by { |s| s[:name].upcase }
|
||||
end
|
||||
|
||||
# Query some detailed parameters about a particular service.
|
||||
def service_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)
|
||||
}
|
||||
|
||||
return detail
|
||||
end
|
||||
|
||||
attr_accessor :client
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Extapi
|
||||
module Window
|
||||
|
||||
###
|
||||
#
|
||||
# This meterpreter extension contains extended API functions for
|
||||
# querying and managing desktop windows.
|
||||
#
|
||||
###
|
||||
class Window
|
||||
|
||||
def initialize(client)
|
||||
@client = client
|
||||
end
|
||||
|
||||
# Enumerate all the top-level windows on the target
|
||||
def window_enum()
|
||||
request = Packet.create_request('extapi_window_enum')
|
||||
response = client.send_request(request)
|
||||
|
||||
windows = []
|
||||
|
||||
response.each(TLV_TYPE_EXT_WINDOW_ENUM_GROUP) { |w|
|
||||
windows << {
|
||||
:pid => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_PID),
|
||||
:handle => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_HANDLE),
|
||||
:title => w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_TITLE)
|
||||
}
|
||||
}
|
||||
|
||||
windows.sort_by { |w| w[:pid] }
|
||||
end
|
||||
|
||||
attr_accessor :client
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
|
@ -12,8 +13,17 @@ module Ui
|
|||
###
|
||||
class Console::CommandDispatcher::Extapi
|
||||
|
||||
require 'rex/post/meterpreter/ui/console/command_dispatcher/extapi/window'
|
||||
require 'rex/post/meterpreter/ui/console/command_dispatcher/extapi/service'
|
||||
|
||||
Klass = Console::CommandDispatcher::Extapi
|
||||
|
||||
Dispatchers =
|
||||
[
|
||||
Klass::Window,
|
||||
Klass::Service
|
||||
]
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
||||
#
|
||||
|
@ -21,162 +31,24 @@ class Console::CommandDispatcher::Extapi
|
|||
#
|
||||
def initialize(shell)
|
||||
super
|
||||
|
||||
Dispatchers.each { |d| shell.enstack_dispatcher(d) }
|
||||
end
|
||||
|
||||
#
|
||||
# Options for the window_enum command.
|
||||
#
|
||||
@@window_enum_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Options for the service_enum command.
|
||||
#
|
||||
@@service_enum_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Options for the service_query command.
|
||||
#
|
||||
@@service_query_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"window_enum" => "Enumerate all current open windows",
|
||||
"service_enum" => "Enumerate all registered Windows services",
|
||||
"service_query" => "Query more detail about a specific Windows service"
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def cmd_window_enum(*args)
|
||||
|
||||
@@window_enum_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: window_enum [-h]\n\n" +
|
||||
"Enumerate the top-level windows on the current desktop.\n\n" +
|
||||
"Enumeration returns the Process ID and Window Handle for each top-level\n" +
|
||||
"window found. The Window Handle can be used for further calls to the\n" +
|
||||
"railgun API.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
windows = client.extapi.window_enum()
|
||||
|
||||
print_line()
|
||||
print_line(" PID | Handle | Window title")
|
||||
print_line("-------------------------------------------------------------")
|
||||
|
||||
windows.each do |w|
|
||||
print_line(sprintf("%8d | %10d | %s", w[:pid], w[:handle], w[:title]))
|
||||
end
|
||||
|
||||
print_line()
|
||||
print_line("Total top-level Windows: #{windows.length}")
|
||||
print_line()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def cmd_service_enum(*args)
|
||||
@@service_enum_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: service_enum [-h]\n\n" +
|
||||
"Enumerate services installed on the target.\n\n" +
|
||||
"Enumeration returns the Process ID, Status, and name of each installed\n" +
|
||||
"service that is discovered. The 'Int?' value indicates if the service is\n" +
|
||||
"able to interact with the desktop.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
status_map = {
|
||||
1 => "STOPPED",
|
||||
2 => "STRT_PEN",
|
||||
3 => "STOP_PEN",
|
||||
4 => "RUNNING",
|
||||
5 => "CONT_PEN",
|
||||
6 => "PAUS_PEN",
|
||||
7 => "PAUSED"
|
||||
}
|
||||
|
||||
services = client.extapi.service_enum()
|
||||
|
||||
print_line()
|
||||
print_line(" Int? | PID | Status | Name (Display Name)")
|
||||
print_line("-------------------------------------------------------------")
|
||||
|
||||
services.each do |s|
|
||||
print_line(sprintf("%5s | %8d | %8s | %s (%s)",
|
||||
s[:interactive] ? "Yes" : "No",
|
||||
s[:pid], status_map[s[:status]],
|
||||
s[:name], s[:display]))
|
||||
end
|
||||
|
||||
print_line()
|
||||
print_line("Total services: #{services.length}")
|
||||
print_line()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def cmd_service_query(*args)
|
||||
args << "-h" if args.length == 0
|
||||
|
||||
@@service_query_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: service_query [-h] <servicename>\n" +
|
||||
" <servicename>: The name of the service to query.\n\n" +
|
||||
"Gets details information about a particular Windows service, including\n" +
|
||||
"binary path, DACL, load order group, start type and more.\n\n")
|
||||
return true
|
||||
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("Path : #{detail[:path]}")
|
||||
print_line("L.O. Group : #{detail[:logroup]}")
|
||||
print_line("Interactive : #{detail[:interactive] ? "Yes" : "No"}")
|
||||
print_line("DACL : #{detail[:dacl]}")
|
||||
print_line()
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
"Extapi"
|
||||
"Extended API Extension"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Ui
|
||||
|
||||
###
|
||||
#
|
||||
# Extended API window management user interface.
|
||||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Extapi::Service
|
||||
|
||||
Klass = Console::CommandDispatcher::Extapi::Service
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"service_enum" => "Enumerate all registered Windows services",
|
||||
"service_query" => "Query more detail about a specific Windows service"
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
"Extapi: Service Management"
|
||||
end
|
||||
#
|
||||
# Options for the service_enum command.
|
||||
#
|
||||
@@service_enum_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Query a single service for more detail.
|
||||
#
|
||||
def cmd_service_enum(*args)
|
||||
@@service_enum_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: service_enum [-h]\n\n" +
|
||||
"Enumerate services installed on the target.\n\n" +
|
||||
"Enumeration returns the Process ID, Status, and name of each installed\n" +
|
||||
"service that was enumerated. The 'Int' value indicates if the service is\n" +
|
||||
"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"
|
||||
}
|
||||
|
||||
services = client.extapi.service.service_enum()
|
||||
|
||||
print_line()
|
||||
print_line(" PID | Status | Int | Name (Display Name)")
|
||||
print_line("----------+------------+-----+-------------------------------")
|
||||
|
||||
services.each do |s|
|
||||
print_line(sprintf(" %8d | %-10s | %s | %s (%s)",
|
||||
s[:pid], status_map[s[:status]],
|
||||
s[:interactive] ? "Y" : "N",
|
||||
s[:name], s[:display]))
|
||||
end
|
||||
|
||||
print_line()
|
||||
print_line("Total services: #{services.length}")
|
||||
print_line()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#
|
||||
# Options for the service_query command.
|
||||
#
|
||||
@@service_query_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Query a single service for more detail.
|
||||
#
|
||||
def cmd_service_query(*args)
|
||||
args << "-h" if args.length == 0
|
||||
|
||||
@@service_query_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: service_query [-h] <servicename>\n" +
|
||||
" <servicename>: The name of the service to query.\n\n" +
|
||||
"Gets details information about a particular Windows service, including\n" +
|
||||
"binary path, DACL, load order group, start type and more.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
service_name = args.shift
|
||||
|
||||
start_type_map = {
|
||||
0 => "Boot",
|
||||
1 => "System",
|
||||
2 => "Automatic",
|
||||
3 => "Manual",
|
||||
4 => "Disabled"
|
||||
}
|
||||
|
||||
detail = client.extapi.service.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("Path : #{detail[:path]}")
|
||||
print_line("L.O. Group : #{detail[:logroup]}")
|
||||
print_line("Interactive : #{detail[:interactive] ? "Yes" : "No"}")
|
||||
print_line("DACL : #{detail[:dacl]}")
|
||||
print_line()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Ui
|
||||
|
||||
###
|
||||
#
|
||||
# Extended API window management user interface.
|
||||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Extapi::Window
|
||||
|
||||
Klass = Console::CommandDispatcher::Extapi::Window
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"window_enum" => "Enumerate all current open windows"
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
"Extapi: Window Management"
|
||||
end
|
||||
|
||||
#
|
||||
# Options for the window_enum command.
|
||||
#
|
||||
@@window_enum_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ]
|
||||
)
|
||||
|
||||
#
|
||||
# Enumerate top-level windows.
|
||||
#
|
||||
def cmd_window_enum(*args)
|
||||
|
||||
@@window_enum_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print(
|
||||
"\nUsage: window_enum [-h]\n\n" +
|
||||
"Enumerate the top-level windows on the current desktop.\n\n" +
|
||||
"Enumeration returns the Process ID and Window Handle for each top-level\n" +
|
||||
"window found. The Window Handle can be used for further calls to the\n" +
|
||||
"railgun API.\n\n")
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
windows = client.extapi.window.window_enum()
|
||||
|
||||
print_line()
|
||||
print_line(" PID | Handle | Window title")
|
||||
print_line("---------+------------+--------------------------------------")
|
||||
|
||||
windows.each do |w|
|
||||
print_line(sprintf("%8d | %10d | %s", w[:pid], w[:handle], w[:title]))
|
||||
end
|
||||
|
||||
print_line()
|
||||
print_line("Total top-level Windows: #{windows.length}")
|
||||
print_line()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue