@@ -16,6 +16,8 @@ def initialize(info={})
1616 [
1717 Msf ::OptBool . new ( "EnableStageEncoding" , [ false , "Encode the second stage payload" , false ] ) ,
1818 Msf ::OptString . new ( "StageEncoder" , [ false , "Encoder to use if EnableStageEncoding is set" , nil ] ) ,
19+ Msf ::OptString . new ( "StageEncoderSaveRegisters" , [ false , "Additional registers to preserve in the staged payload if EnableStageEncoding is set" , "" ] ) ,
20+ Msf ::OptBool . new ( "StageEncodingFallback" , [ false , "Fallback to default encoders or no encoding if the selected StageEncoder is not compatible" , true ] )
1921 ] , Msf ::Payload ::Stager )
2022
2123 end
@@ -92,14 +94,12 @@ def stage_over_connection?
9294 true
9395 end
9496
95-
9697 #
9798 # Whether to use an Encoder on the second stage
9899 #
99100 # @return [Boolean]
100101 def encode_stage?
101- # Convert to string in case it hasn't been normalized
102- !!( datastore [ 'EnableStageEncoding' ] . to_s == "true" )
102+ !!( datastore [ 'EnableStageEncoding' ] )
103103 end
104104
105105 #
@@ -134,7 +134,18 @@ def handle_connection(conn, opts={})
134134 p = generate_stage
135135
136136 # Encode the stage if stage encoding is enabled
137- p = encode_stage ( p )
137+ begin
138+ p = encode_stage ( p )
139+ rescue ::RuntimeError
140+ warning_msg = "Failed to stage"
141+ warning_msg << " (#{ conn . peerhost } )" if conn . respond_to? :peerhost
142+ warning_msg << ": #{ $!} "
143+ print_warning warning_msg
144+ if conn . respond_to? :close && !conn . closed?
145+ conn . close
146+ end
147+ return
148+ end
138149
139150 # Give derived classes an opportunity to an intermediate state before
140151 # the stage is sent. This gives derived classes an opportunity to
@@ -196,30 +207,75 @@ def handle_intermediate_stage(conn, payload)
196207 false
197208 end
198209
210+ #
211+ # Takes an educated guess at the list of registers an encoded stage
212+ # would need to preserve based on the Convention
213+ #
214+ def encode_stage_preserved_registers
215+ module_info [ 'Convention' ] . to_s . scan ( /\b sock([a-z]{3,}+)\b / ) .
216+ map { |reg | reg . first } .
217+ join ( " " )
218+ end
219+
199220 # Encodes the stage prior to transmission
200221 # @return [String] Encoded version of +stg+
201222 def encode_stage ( stg )
202223 return stg unless encode_stage?
224+ stage_enc_mod = [ ]
203225
204- if datastore [ "StageEncoder" ] . nil? or datastore [ "StageEncoder" ] . empty?
205- stage_enc_mod = nil
206- else
207- stage_enc_mod = datastore [ "StageEncoder" ]
226+ # Handle StageEncoder if specified by the user
227+ if datastore [ 'StageEncoder' ] . to_s . length > 0
228+ # Allow multiple encoders separated by commas
229+ stage_enc_mod = datastore [ "StageEncoder" ] . split ( ',' ) . map ( &:strip ) . select { |x | x . to_s . length > 0 } . uniq
230+ end
231+
232+ # Add automatic encoding as a fallback if needed
233+ if datastore [ 'StageEncodingFallback' ]
234+ stage_enc_mod << nil
235+ end
236+
237+ # If fallback has been disabled and no encoder was parsed, exit early and rop the session
238+ if stage_enc_mod . length == 0
239+ raise RuntimeError , "StageEncoder is invalid and StageEncodingFallback is disabled"
240+ end
241+
242+ # Allow the user to specify additional registers to preserve
243+ saved_registers = (
244+ datastore [ 'StageEncoderSaveRegisters' ] . to_s + " "
245+ encode_stage_preserved_registers
246+ ) . strip
247+
248+ estg = nil
249+
250+ stage_enc_mod . each do |encoder_refname_from_user |
251+
252+ # Generate an encoded version of the stage. We tell the encoding system
253+ # to save certain registers to ensure that it does not get clobbered.
254+ encp = Msf ::EncodedPayload . create (
255+ self ,
256+ 'Raw' => stg ,
257+ 'Encoder' => encoder_refname_from_user ,
258+ 'EncoderOptions' => { 'SaveRegisters' => saved_registers } ,
259+ 'ForceSaveRegisters' => true ,
260+ 'ForceEncode' => true )
261+
262+ if encp . encoder
263+ print_status ( "Encoded stage with #{ encp . encoder . refname } " )
264+ estg = encp . encoded
265+ break
266+ end
267+ end
268+
269+ if datastore [ 'StageEncodingFallback' ] && estg . nil?
270+ print_warning ( "StageEncoder failed, falling back to no encoding" )
271+ estg = stg
272+ end
273+
274+ unless estg
275+ raise RuntimeError , "Stage encoding failed and StageEncodingFallback is disabled"
208276 end
209277
210- # Generate an encoded version of the stage. We tell the encoding system
211- # to save edi to ensure that it does not get clobbered.
212- encp = Msf ::EncodedPayload . create (
213- self ,
214- 'Raw' => stg ,
215- 'Encoder' => stage_enc_mod ,
216- 'SaveRegisters' => [ 'edi' ] ,
217- 'ForceEncode' => true )
218- print_status ( "Encoded stage with #{ encp . encoder . refname } " )
219-
220- # If the encoding succeeded, use the encoded buffer. Otherwise, fall
221- # back to using the non-encoded stage
222- encp . encoded || stg
278+ estg
223279 end
224280
225281 # Aliases
0 commit comments