Skip to content

Commit 4d3e353

Browse files
author
HD Moore
committed
Merge pull request #2 from agix/multipleStageEncoders
Unblock when invalid encoder is selected and allow multiple encoder
2 parents b8a1010 + 9cbc7e4 commit 4d3e353

File tree

2 files changed

+36
-22
lines changed

2 files changed

+36
-22
lines changed

lib/msf/core/encoded_payload.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def self.create(pinst, reqs = {})
2323
p = EncodedPayload.new(pinst.framework, pinst, reqs)
2424

2525
p.generate(reqs['Raw'])
26-
26+
2727
return p
2828
end
2929

@@ -59,7 +59,7 @@ def generate(raw = nil)
5959
if (priority == 0)
6060
Thread.current.priority = 1
6161
end
62-
62+
6363
begin
6464
# First, validate
6565
pinst.validate()
@@ -75,6 +75,8 @@ def generate(raw = nil)
7575

7676
# Finally, set the complete payload definition
7777
self.encoded = (self.nop_sled || '') + self.encoded
78+
rescue NoEncodersSucceededError
79+
self.encoded = nil
7880
ensure
7981
# Restore the thread priority
8082
Thread.current.priority = priority
@@ -236,12 +238,10 @@ def encode
236238
self.encoded = eout
237239
break
238240
}
239-
240241
# If the encoded payload is nil, raise an exception saying that we
241242
# suck at life.
242243
if (self.encoded == nil)
243-
self.encoder = nil
244-
244+
self.encoder = nil
245245
raise NoEncodersSucceededError,
246246
"#{pinst.refname}: All encoders failed to encode.",
247247
caller

lib/msf/core/payload/stager.rb

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +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", "" ])
19+
Msf::OptString.new("StageEncoderSaveRegisters", [ false, "Additional registers to preserve in the staged payload if EnableStageEncoding is set", "" ]),
20+
Msf::OptBool.new("StageEncodingNoFallBack", [ false, "If encoders choosen in StageEncoder are not compatible to stage encoding fallback to no encoding otherwise fallback to automatic selected one", true ])
2021
], Msf::Payload::Stager)
2122

2223
end
@@ -100,7 +101,7 @@ def stage_over_connection?
100101
# @return [Boolean]
101102
def encode_stage?
102103
# Convert to string in case it hasn't been normalized
103-
!!(datastore['EnableStageEncoding'].to_s == "true")
104+
!!(datastore['EnableStageEncoding'].to_s == "true" || datastore["StageEncoder"].to_s.length > 0)
104105
end
105106

106107
#
@@ -216,7 +217,7 @@ def encode_stage(stg)
216217
if datastore["StageEncoder"].nil? or datastore["StageEncoder"].empty?
217218
stage_enc_mod = nil
218219
else
219-
stage_enc_mod = datastore["StageEncoder"]
220+
stage_enc_mod = datastore["StageEncoder"].split(',').map(&:strip)
220221
end
221222

222223
# Allow the user to specify additional registers to preserve
@@ -225,20 +226,33 @@ def encode_stage(stg)
225226
encode_stage_preserved_registers
226227
).strip
227228

228-
# Generate an encoded version of the stage. We tell the encoding system
229-
# to save certain registers to ensure that it does not get clobbered.
230-
encp = Msf::EncodedPayload.create(
231-
self,
232-
'Raw' => stg,
233-
'Encoder' => stage_enc_mod,
234-
'EncoderOptions' => { 'SaveRegisters' => saved_registers },
235-
'ForceSaveRegisters' => true,
236-
'ForceEncode' => true)
237-
print_status("Encoded stage with #{encp.encoder.refname}")
238-
239-
# If the encoding succeeded, use the encoded buffer. Otherwise, fall
240-
# back to using the non-encoded stage
241-
encp.encoded || stg
229+
(stage_enc_mod || [nil]).each do |encoder_refname_from_user|
230+
# Generate an encoded version of the stage. We tell the encoding system
231+
# to save certain registers to ensure that it does not get clobbered.
232+
encp = Msf::EncodedPayload.create(
233+
self,
234+
'Raw' => stg,
235+
'Encoder' => encoder_refname_from_user,
236+
'EncoderOptions' => { 'SaveRegisters' => saved_registers },
237+
'ForceSaveRegisters' => true,
238+
'ForceEncode' => true)
239+
if (encp.encoder == nil)
240+
print_warning("Encoder #{encoder_refname_from_user} did not succeed")
241+
if !datastore['StageEncodingNoFallBack']
242+
print_warning("Fallback to automatic StageEncoder selection")
243+
encoder_refname_from_user = nil
244+
redo
245+
else
246+
print_warning("Fallback to no encoder")
247+
end
248+
else
249+
print_status("Encoded stage with #{encp.encoder.refname}")
250+
end
251+
# If the encoding succeeded, use the encoded buffer. Otherwise, fall
252+
# back to using the non-encoded stage
253+
stg = encp.encoded || stg
254+
end
255+
stg
242256
end
243257

244258
# Aliases

0 commit comments

Comments
 (0)