Skip to content

Commit 2841624

Browse files
committed
Refactor spec and add more docs
1 parent 40a3da2 commit 2841624

File tree

2 files changed

+85
-32
lines changed

2 files changed

+85
-32
lines changed

msfvenom

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ require 'rex'
1616
require 'msf/ui'
1717
require 'msf/base'
1818

19+
# Mad payload generation
20+
#
21+
# @example
22+
# venom = MsfVenom.new
23+
# # ARGV will be parsed destructively!
24+
# venom.parse_args(ARGV)
25+
# $stdout.puts venom.generate
1926
class MsfVenom
2027
class MsfVenomError < StandardError; end
2128
class UsageError < MsfVenomError; end
@@ -34,13 +41,21 @@ class MsfVenom
3441
@framework = framework
3542
end
3643

44+
# Creates a new framework object.
45+
#
46+
# @note Ignores any previously cached value
47+
# @param (see ::Msf::Simple::Framework.create)
48+
# @return [Msf::Framework]
3749
def init_framework(create_opts={})
3850
create_opts[:module_types] ||= [
3951
::Msf::MODULE_PAYLOAD, ::Msf::MODULE_ENCODER, ::Msf::MODULE_NOP
4052
]
4153
@framework = ::Msf::Simple::Framework.create(create_opts.merge('DisableDatabase' => true))
4254
end
4355

56+
# Cached framework object
57+
#
58+
# @return [Msf::Framework]
4459
def framework
4560
return @framework if @framework
4661

@@ -49,6 +64,10 @@ class MsfVenom
4964
@framework
5065
end
5166

67+
# Initialize the options for this run from ARGV
68+
# @param args [Array] Usually ARGV. Parsed destructively.
69+
# @return [void]
70+
# @raise [UsageError] When given invalid options
5271
def parse_args(args)
5372
@opts = {}
5473
@datastore = {}
@@ -181,6 +200,10 @@ class MsfVenom
181200
encoders
182201
end
183202

203+
# Read a raw payload from stdin (or whatever IO object we're currently
204+
# using as stdin, see {#initialize})
205+
#
206+
# @return [String]
184207
def payload_stdin
185208
@in.binmode
186209
payload = @in.read
@@ -189,7 +212,7 @@ class MsfVenom
189212

190213
def generate_nops(arch, len, nop_mod=nil, nop_opts={})
191214
nop_opts['BadChars'] ||= ''
192-
nop_jpts['SaveRegisters'] ||= [ 'esp', 'ebp', 'esi', 'edi' ]
215+
nop_opts['SaveRegisters'] ||= [ 'esp', 'ebp', 'esi', 'edi' ]
193216

194217
if nop_mod
195218
nop = framework.nops.create(nop_mod)
@@ -267,7 +290,32 @@ class MsfVenom
267290
"\n" + tbl.to_s + "\n"
268291
end
269292

293+
# @return [String] A raw shellcode blob
294+
# @return [nil] When commandline options conspire to produce no output
270295
def generate_raw_payload
296+
if @opts[:list]
297+
@opts[:list].each do |mod|
298+
case mod.downcase
299+
when "payloads"
300+
@err.puts dump_payloads
301+
when "encoders"
302+
@err.puts dump_encoders(@opts[:arch])
303+
when "nops"
304+
@err.puts dump_nops
305+
when "all"
306+
# Init here so #dump_payloads doesn't create a framework with
307+
# only payloads, etc.
308+
init_framework
309+
@err.puts dump_payloads
310+
@err.puts dump_encoders
311+
@err.puts dump_nops
312+
else
313+
raise UsageError, "Invalid module type"
314+
end
315+
end
316+
return
317+
end
318+
271319
if @opts[:payload] == 'stdin'
272320
payload_raw = payload_stdin
273321
if @opts[:encode] and (@opts[:arch].nil? or @opts[:platform].nil?)
@@ -307,29 +355,8 @@ class MsfVenom
307355
end
308356

309357

358+
# Main dispatch method to do the right thing with the given options.
310359
def generate
311-
if @opts[:list]
312-
@opts[:list].each do |mod|
313-
case mod.downcase
314-
when "payloads"
315-
@err.puts dump_payloads
316-
when "encoders"
317-
@err.puts dump_encoders(@opts[:arch])
318-
when "nops"
319-
@err.puts dump_nops
320-
when "all"
321-
# Init here so #dump_payloads doesn't create a framework with
322-
# only payloads, etc.
323-
init_framework
324-
@err.puts dump_payloads
325-
@err.puts dump_encoders
326-
@err.puts dump_nops
327-
else
328-
print_error("Invalid module type")
329-
end
330-
end
331-
return
332-
end
333360

334361
# Normalize the options
335362
@opts[:platform] = ::Msf::Module::PlatformList.transform(@opts[:platform]) if @opts[:platform]

spec/msfvenom_spec.rb

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44
# doesn't end in .rb or .so, so have to load instead of require
55
load File.join(Msf::Config.install_root, 'msfvenom')
66

7+
shared_examples_for "nop dumper" do |block|
8+
it "should list known nops" do
9+
dump = block.call
10+
11+
%w!
12+
x86/opty2
13+
armle/simple
14+
!.each do |name|
15+
dump.should include(name)
16+
end
17+
end
18+
19+
end
20+
721
describe MsfVenom do
822

923
let(:stdin) { StringIO.new("", "rb") }
@@ -48,15 +62,8 @@
4862
end
4963

5064
describe "#dump_nops" do
51-
it "should list known nops" do
52-
dump = venom.dump_nops
53-
54-
%w!
55-
x86/opty2
56-
armle/simple
57-
!.each do |name|
58-
dump.should include(name)
59-
end
65+
it_behaves_like "nop dumper" do
66+
let(:nops) { venom.dump_nops }
6067
end
6168
end
6269

@@ -141,6 +148,25 @@
141148

142149
end
143150

151+
context "with --list" do
152+
context "with invalid module type" do
153+
let(:args) { %w!--list asdf! }
154+
it "should raise UsageError" do
155+
expect { venom.generate_raw_payload }.to raise_error(MsfVenom::UsageError)
156+
end
157+
end
158+
context "with nops" do
159+
let(:args) { %w!--list nops! }
160+
it_behaves_like "nop dumper" do
161+
let(:nops) do
162+
venom.generate_raw_payload
163+
@err.string
164+
end
165+
end
166+
end
167+
168+
end
169+
144170
[
145171
{ :format => "elf", :arch => "x86" },
146172
{ :format => "raw", :arch => "x86" },

0 commit comments

Comments
 (0)