4
4
5
5
module Msf
6
6
module Handler
7
-
8
7
###
9
8
#
10
9
# This module implements the reverse TCP handler. This means
@@ -16,7 +15,6 @@ module Handler
16
15
#
17
16
###
18
17
module ReverseTcp
19
-
20
18
include Msf ::Handler
21
19
include Msf ::Handler ::Reverse
22
20
include Msf ::Handler ::Reverse ::Comm
@@ -26,7 +24,7 @@ module ReverseTcp
26
24
# 'reverse_tcp'.
27
25
#
28
26
def self . handler_type
29
- return "reverse_tcp"
27
+ "reverse_tcp"
30
28
end
31
29
32
30
#
@@ -55,7 +53,6 @@ def initialize(info = {})
55
53
self . conn_threads = [ ]
56
54
end
57
55
58
-
59
56
#
60
57
# Closes the listener socket if one was created.
61
58
#
@@ -64,9 +61,13 @@ def cleanup_handler
64
61
65
62
# Kill any remaining handle_connection threads that might
66
63
# be hanging around
67
- conn_threads . each { |thr |
68
- thr . kill rescue nil
69
- }
64
+ conn_threads . each do |thr |
65
+ begin
66
+ thr . kill
67
+ rescue
68
+ nil
69
+ end
70
+ end
70
71
end
71
72
72
73
# A string suitable for displaying to the user
@@ -84,138 +85,135 @@ def start_handler
84
85
85
86
local_port = bind_port
86
87
87
- self . listener_thread = framework . threads . spawn ( "ReverseTcpHandlerListener-#{ local_port } " , false , queue ) { |lqueue |
88
+ handler_name = "ReverseTcpHandlerListener-#{ local_port } "
89
+ self . listener_thread = framework . threads . spawn ( handler_name , false , queue ) { |lqueue |
88
90
loop do
89
91
# Accept a client connection
90
92
begin
91
- client = self . listener_sock . accept
92
- if ! client
93
- wlog ( "ReverseTcpHandlerListener- #{ local_port } : No client received in call to accept, exiting..." )
94
- break
93
+ client = listener_sock . accept
94
+ if client
95
+ self . pending_connections += 1
96
+ lqueue . push ( client )
95
97
end
96
-
97
- self . pending_connections += 1
98
- lqueue . push ( client )
99
- rescue ::Exception
100
- wlog ( "ReverseTcpHandlerListener-#{ local_port } : Exception raised during listener accept: #{ $!} \n \n #{ $@. join ( "\n " ) } " )
101
- break
98
+ rescue Errno ::ENOTCONN
99
+ nil
100
+ rescue StandardError => e
101
+ wlog [
102
+ "#{ handler_name } : Exception raised during listener accept: #{ e . class } " ,
103
+ "#{ $ERROR_INFO} " ,
104
+ "#{ $ERROR_POSITION. join ( "\n " ) } "
105
+ ] . join ( "\n " )
102
106
end
103
107
end
104
108
}
105
109
106
- self . handler_thread = framework . threads . spawn ( "ReverseTcpHandlerWorker-#{ local_port } " , false , queue ) { |cqueue |
110
+ worker_name = "ReverseTcpHandlerWorker-#{ local_port } "
111
+ self . handler_thread = framework . threads . spawn ( worker_name , false , queue ) { |cqueue |
107
112
loop do
108
113
begin
109
114
client = cqueue . pop
110
115
111
- if ! client
112
- elog ( "ReverseTcpHandlerWorker-#{ local_port } : Queue returned an empty result, exiting..." )
113
- break
116
+ unless client
117
+ elog ( "#{ worker_name } : Queue returned an empty result, exiting..." )
114
118
end
115
119
116
120
# Timeout and datastore options need to be passed through to the client
117
121
opts = {
118
- : datastore => datastore ,
119
- : expiration => datastore [ 'SessionExpirationTimeout' ] . to_i ,
120
- : comm_timeout => datastore [ 'SessionCommunicationTimeout' ] . to_i ,
121
- : retry_total => datastore [ 'SessionRetryTotal' ] . to_i ,
122
- : retry_wait => datastore [ 'SessionRetryWait' ] . to_i
122
+ datastore : datastore ,
123
+ expiration : datastore [ 'SessionExpirationTimeout' ] . to_i ,
124
+ comm_timeout : datastore [ 'SessionCommunicationTimeout' ] . to_i ,
125
+ retry_total : datastore [ 'SessionRetryTotal' ] . to_i ,
126
+ retry_wait : datastore [ 'SessionRetryWait' ] . to_i
123
127
}
124
128
125
129
if datastore [ 'ReverseListenerThreaded' ]
126
- self . conn_threads << framework . threads . spawn ( "ReverseTcpHandlerSession-#{ local_port } -#{ client . peerhost } " , false , client ) { |client_copy |
130
+ thread_name = "#{ worker_name } -#{ client . peerhost } "
131
+ conn_threads << framework . threads . spawn ( thread_name , false , client ) do |client_copy |
127
132
handle_connection ( wrap_aes_socket ( client_copy ) , opts )
128
- }
133
+ end
129
134
else
130
135
handle_connection ( wrap_aes_socket ( client ) , opts )
131
136
end
132
- rescue :: Exception
133
- elog ( "Exception raised from handle_connection: #{ $! . class } : #{ $! } \n \n #{ $@ . join ( "\n " ) } " )
137
+ rescue StandardError
138
+ elog ( "Exception raised from handle_connection: #{ $ERROR_INFO . class } : #{ $ERROR_INFO } \n \n #{ $ERROR_POSITION . join ( "\n " ) } " )
134
139
end
135
140
end
136
141
}
137
-
138
142
end
139
143
140
144
def wrap_aes_socket ( sock )
141
- if datastore [ "PAYLOAD" ] !~ / java\/ / or ( datastore [ "AESPassword" ] || "" ) == ""
145
+ if datastore [ "PAYLOAD" ] !~ %r{ java/} || ( datastore [ "AESPassword" ] || "" ) == ""
142
146
return sock
143
147
end
144
148
145
- socks = Rex ::Socket :: tcp_socket_pair ( )
149
+ socks = Rex ::Socket . tcp_socket_pair
146
150
socks [ 0 ] . extend ( Rex ::Socket ::Tcp )
147
151
socks [ 1 ] . extend ( Rex ::Socket ::Tcp )
148
152
149
153
m = OpenSSL ::Digest . new ( 'md5' )
150
154
m . reset
151
155
key = m . digest ( datastore [ "AESPassword" ] || "" )
152
156
153
- Rex ::ThreadFactory . spawn ( 'Session-AESEncrypt' , false ) {
157
+ Rex ::ThreadFactory . spawn ( 'Session-AESEncrypt' , false ) do
154
158
c1 = OpenSSL ::Cipher . new ( 'aes-128-cfb8' )
155
159
c1 . encrypt
156
- c1 . key = key
160
+ c1 . key = key
157
161
sock . put ( [ 0 ] . pack ( 'N' ) )
158
- sock . put ( c1 . iv = c1 . random_iv )
162
+ sock . put ( ( c1 . iv = c1 . random_iv ) )
159
163
buf1 = socks [ 0 ] . read ( 4096 )
160
- while buf1 and buf1 != ""
164
+ while buf1 && buf1 != ""
161
165
sock . put ( c1 . update ( buf1 ) )
162
166
buf1 = socks [ 0 ] . read ( 4096 )
163
167
end
164
- sock . close ( )
165
- }
166
- Rex ::ThreadFactory . spawn ( 'Session-AESDecrypt' , false ) {
168
+ sock . close
169
+ end
170
+
171
+ Rex ::ThreadFactory . spawn ( 'Session-AESDecrypt' , false ) do
167
172
c2 = OpenSSL ::Cipher . new ( 'aes-128-cfb8' )
168
173
c2 . decrypt
169
- c2 . key = key
170
- iv = ""
171
- while iv . length < 16
172
- iv << sock . read ( 16 - iv . length )
173
- end
174
+ c2 . key = key
175
+
176
+ iv = ""
177
+ iv << sock . read ( 16 - iv . length ) while iv . length < 16
178
+
174
179
c2 . iv = iv
175
180
buf2 = sock . read ( 4096 )
176
- while buf2 and buf2 != ""
181
+ while buf2 && buf2 != ""
177
182
socks [ 0 ] . put ( c2 . update ( buf2 ) )
178
183
buf2 = sock . read ( 4096 )
179
184
end
180
- socks [ 0 ] . close ( )
181
- }
182
- return socks [ 1 ]
185
+ socks [ 0 ] . close
186
+ end
187
+
188
+ socks [ 1 ]
183
189
end
184
190
185
191
#
186
192
# Stops monitoring for an inbound connection.
187
193
#
188
194
def stop_handler
189
195
# Terminate the listener thread
190
- if ( self . listener_thread and self . listener_thread . alive? == true )
191
- self . listener_thread . kill
192
- self . listener_thread = nil
193
- end
196
+ listener_thread . kill if listener_thread && listener_thread . alive? == true
194
197
195
198
# Terminate the handler thread
196
- if ( self . handler_thread and self . handler_thread . alive? == true )
197
- self . handler_thread . kill
198
- self . handler_thread = nil
199
- end
199
+ handler_thread . kill if handler_thread && handler_thread . alive? == true
200
200
201
- if ( self . listener_sock )
201
+ if listener_sock
202
202
begin
203
- self . listener_sock . close
203
+ listener_sock . close
204
204
rescue IOError
205
205
# Ignore if it's listening on a dead session
206
206
dlog ( "IOError closing listener sock; listening on dead session?" , LEV_1 )
207
207
end
208
- self . listener_sock = nil
209
208
end
210
209
end
211
210
212
- protected
211
+ protected
213
212
214
213
attr_accessor :listener_sock # :nodoc:
215
214
attr_accessor :listener_thread # :nodoc:
216
215
attr_accessor :handler_thread # :nodoc:
217
216
attr_accessor :conn_threads # :nodoc:
218
217
end
219
-
220
218
end
221
219
end
0 commit comments