@@ -61,6 +61,9 @@ class PayloadGenerator
61
61
# @!attribute platform
62
62
# @return [String] The platform to build the payload for
63
63
attr_accessor :platform
64
+ # @!attribute smallest
65
+ # @return [Boolean] Whether or not to find the smallest possible output
66
+ attr_accessor :smallest
64
67
# @!attribute space
65
68
# @return [Fixnum] The maximum size in bytes of the payload
66
69
attr_accessor :space
@@ -95,6 +98,7 @@ class PayloadGenerator
95
98
# @option opts [Hash] :datastore (see #datastore)
96
99
# @option opts [Msf::Framework] :framework (see #framework)
97
100
# @option opts [Boolean] :cli (see #cli)
101
+ # @option opts [Boolean] :smallest (see #smallest)
98
102
# @raise [KeyError] if framework is not provided in the options hash
99
103
def initialize ( opts = { } )
100
104
@add_code = opts . fetch ( :add_code , '' )
@@ -113,12 +117,20 @@ def initialize(opts={})
113
117
@stdin = opts . fetch ( :stdin , nil )
114
118
@template = opts . fetch ( :template , '' )
115
119
@var_name = opts . fetch ( :var_name , 'buf' )
120
+ @smallest = opts . fetch ( :smallest , false )
116
121
@encoder_space = opts . fetch ( :encoder_space , @space )
117
122
118
123
@framework = opts . fetch ( :framework )
119
124
120
125
raise ArgumentError , "Invalid Payload Selected" unless payload_is_valid?
121
126
raise ArgumentError , "Invalid Format Selected" unless format_is_valid?
127
+
128
+ # In smallest mode, override the payload @space & @encoder_space settings
129
+ if @smallest
130
+ @space = 0
131
+ @encoder_space = 1 . gigabyte
132
+ end
133
+
122
134
end
123
135
124
136
# This method takes the shellcode generated so far and adds shellcode from
@@ -199,24 +211,36 @@ def encode_payload(shellcode)
199
211
encoder_list = get_encoders
200
212
if encoder_list . empty?
201
213
cli_print "No encoder or badchars specified, outputting raw payload"
202
- shellcode
203
- else
204
- cli_print "Found #{ encoder_list . count } compatible encoders"
205
- encoder_list . each do |encoder_mod |
206
- cli_print "Attempting to encode payload with #{ iterations } iterations of #{ encoder_mod . refname } "
207
- begin
208
- encoder_mod . available_space = @encoder_space
209
- return run_encoder ( encoder_mod , shellcode . dup )
210
- rescue ::Msf ::EncoderSpaceViolation => e
211
- cli_print "#{ encoder_mod . refname } failed with #{ e . message } "
212
- next
213
- rescue ::Msf ::EncodingError => e
214
- cli_print "#{ encoder_mod . refname } failed with #{ e . message } "
215
- next
216
- end
214
+ return shellcode
215
+ end
216
+
217
+ results = { }
218
+
219
+ cli_print "Found #{ encoder_list . count } compatible encoders"
220
+ encoder_list . each do |encoder_mod |
221
+ cli_print "Attempting to encode payload with #{ iterations } iterations of #{ encoder_mod . refname } "
222
+ begin
223
+ encoder_mod . available_space = @encoder_space unless @smallest
224
+ results [ encoder_mod . refname ] = run_encoder ( encoder_mod , shellcode . dup )
225
+ break unless @smallest
226
+ rescue ::Msf ::EncoderSpaceViolation => e
227
+ cli_print "#{ encoder_mod . refname } failed with #{ e . message } "
228
+ next
229
+ rescue ::Msf ::EncodingError => e
230
+ cli_print "#{ encoder_mod . refname } failed with #{ e . message } "
231
+ next
217
232
end
233
+ end
234
+
235
+ if results . keys . length == 0
218
236
raise ::Msf ::EncodingError , "No Encoder Succeeded"
219
237
end
238
+
239
+ # Return the shortest encoding of the payload
240
+ chosen_encoder = results . keys . sort { |a , b | results [ a ] . length <=> results [ b ] . length } . first
241
+ cli_print "#{ chosen_encoder } chosen with final size #{ results [ chosen_encoder ] . length } "
242
+
243
+ results [ chosen_encoder ]
220
244
end
221
245
222
246
# This returns a hash for the exe format generation of payloads
0 commit comments