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
OJ 2013-10-11 09:52:23 +10:00
parent cbaeebeff7
commit b99af52279
8 changed files with 364 additions and 205 deletions

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,8 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'rex/post/meterpreter/extensions/extapi/tlv' 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 Rex
module Post module Post
@ -12,11 +14,7 @@ module Extapi
### ###
# #
# This meterpreter extension contains an extended API which will allow for more # This meterpreter extension contains an extended API which will allow for more
# advanced enumeration of the victim. This includes detail of: # advanced enumeration of the victim.
# * Active/open windows
# * Services
# * Clipboard
# ... and more.
# #
### ###
class Extapi < Extension class Extapi < Extension
@ -28,69 +26,15 @@ class Extapi < Extension
[ [
{ {
'name' => 'extapi', '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 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; end end; end; end; end; end

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,6 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'rex/post/meterpreter' require 'rex/post/meterpreter'
module Rex module Rex
module Post module Post
module Meterpreter module Meterpreter
@ -12,8 +13,17 @@ module Ui
### ###
class Console::CommandDispatcher::Extapi 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 Klass = Console::CommandDispatcher::Extapi
Dispatchers =
[
Klass::Window,
Klass::Service
]
include Console::CommandDispatcher include Console::CommandDispatcher
# #
@ -21,162 +31,24 @@ class Console::CommandDispatcher::Extapi
# #
def initialize(shell) def initialize(shell)
super super
Dispatchers.each { |d| shell.enstack_dispatcher(d) }
end 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. # List of supported commands.
# #
def 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 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 # Name for this dispatcher
# #
def name def name
"Extapi" "Extended API Extension"
end end
end end

View File

@ -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

View File

@ -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