Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Rubinius support for specs and travis-ci #3053

Closed
wants to merge 27 commits into from

4 participants

Luke Imhoff Matt Buck Tod Beardsley lsanchez-r7
Luke Imhoff
Collaborator

Get specs passing locally for rbx-2.2.5 (latest as of this time). Having issues on travis-ci because the build times out after 50 minutes. I don't have this issue when running specs locally: the build finishes in 275.81 seconds on my MacBook Pro running Mavericks. I'm not sure if the build time is related to hardware differences or OS difference on the travis-ci build servers. I'd appreciate developers using Linux and Windows to test this out locally to try to narrow down the performance issues.

If we can't figure out why travis-ci is slower, then I'll have to add rbx to the allowed failures part of the build matrix, but the changes in this PR are still useful for rbx compatibility for those users who are interested and because it fixes some thread leaks in the specs.

limhoff-r7 added some commits
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' 12a1e8a
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' c7c7653
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' a6cdad1
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' 69b04b4
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' cd0d7be
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' f7f3cb9
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' 6f59b34
Luke Imhoff limhoff-r7 And standard library gems for Rubinius b2aaf3d
Luke Imhoff limhoff-r7 Remove Iconv usage
MSP-9228

Iconv was deprecated in Ruby 1.9.3 and is gone in 2.0, so it doesn't
work at all with Rubinius 2.2, so replace with String#encode.
b302427
Luke Imhoff limhoff-r7 msfconsole booting under Rubinius
msfconsole boots and gets to a prompt, but prints warnings.
003f88b
Luke Imhoff limhoff-r7 Fix load warnings before rinda 79e5978
Luke Imhoff limhoff-r7 Fix rinda loading c8e4de2
Luke Imhoff limhoff-r7 Fix irb command b77adac
Luke Imhoff limhoff-r7 Add rubinius (rbx) to travis-ci builds fe69f6a
Luke Imhoff limhoff-r7 Add msfcli_spec dependencies 31fbf31
Luke Imhoff limhoff-r7 Add coverage libraries for simplecov 9410288
Luke Imhoff limhoff-r7 Make Msf::Module::Loader::Base spec platform independent
Rubinius reports the module-path in line 1 instead of 0, so just check
if the module_path is in any line of the backtrace.
7a367f0
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master' 528856d
Luke Imhoff limhoff-r7 Merge remote-tracking branch 'upstream/master'
Conflicts:
	external/source/exploits/make.bat
	lib/msf/core/payload_generator.rb
	lib/rex/zip/jar.rb
	modules/encoders/x86/opt_sub.rb
	modules/exploits/multi/http/dexter_casinoloader_exec.rb
	msfvenom
	spec/lib/msf/core/payload_generator_spec.rb
898e807
Luke Imhoff limhoff-r7 Fix merge error 89462d4
Luke Imhoff limhoff-r7 Merge branch 'master' into feature/rubinius 3d196cb
Luke Imhoff limhoff-r7 Rescue PrimiteFailure for Regexp.compile
On rubinius, Regexp.compile(<Integer>) raised PrimitiveFailure instead
of TypeError raised by MRI.
13972f8
Luke Imhoff limhoff-r7 Loosen message match on KeyError
Rubinius's wording is slightly different.
5afc145
Luke Imhoff limhoff-r7 Remove unreliable with_connection specs
should_receive(:with_connection) can report varying call counts
depending on the spec order and it's not possible to separate the
code-under-test calls from the test setup calls, so remove these
problematic specs completely since they're just causing random false
failures.
a11f072
Luke Imhoff limhoff-r7 Remove remainder of specs using should_receive(:with_connection)
Too unreliable: unpredicatble failures.
be79e6b
Luke Imhoff limhoff-r7 Detect and clean up Thread leaks
Threads spawned by Msf::Framework#initialize were not being cleaned up,
which could cause the tests to slow down, so explicitly kill to stop the
threads and then join them to ensure they aren't left as dead in the
Thread.list.  Added around(:each) to spec_helper.rb to monitor for
thread leaks in the future: if a thread is leaked, then the example that
leaked the thread will fail.
5bfa80e
Luke Imhoff
Collaborator

Verification Steps

  • Update rvm to get access to Rubinius 2.2.5: rvm get head
  • Install rbx-2.2.5: rvm install rbx-2.2.5
  • Create and use gemset: rvm use rbx@metasploit-framework --create
  • bundle exec rake spec
  • VERIFY no errors or failures in specs.
Matt Buck
Collaborator
Luke Imhoff limhoff-r7 Join killed threads to ensure clean up
MSP-9425

Call Thread#join after Thread#kill to ensure that the killed thread dies
completely and is removed from Thread.list.
23f49f5
Luke Imhoff
Collaborator

The ruby build is passing now, but I expect the rbx build to timeout. Can you check if the rbx build works locally for you @mbuck-r7? If it does, then I'll have to find a work-around for the timeout issue for rbx.

Luke Imhoff
Collaborator

Made it with 7 seconds to spare! The actual rspec run looks like it took only 32 minutes, so I'm inclined to see if I can use the travis_ci_bundle gem to speed up the pre-rspec time.

screen shot 2014-03-19 at 3 05 57 pm

lsanchez-r7
Collaborator

NameError: uninitialized constant Rubinius::ToolSets
rubinius/rubinius-processor#2

using Rubinius 2.2.6

lsanchez-r7
Collaborator

Finished in 25 minutes 46 seconds
1689 examples, 0 failures, 23 pending

lsanchez-r7
Collaborator

closing until we have time find the performance issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 18, 2013
  1. Luke Imhoff
Commits on Dec 6, 2013
  1. Luke Imhoff
Commits on Dec 12, 2013
  1. Luke Imhoff
Commits on Dec 14, 2013
  1. Luke Imhoff
Commits on Dec 21, 2013
  1. Luke Imhoff
Commits on Jan 16, 2014
  1. Luke Imhoff
Commits on Feb 9, 2014
  1. Luke Imhoff
  2. Luke Imhoff
  3. Luke Imhoff

    Remove Iconv usage

    limhoff-r7 authored
    MSP-9228
    
    Iconv was deprecated in Ruby 1.9.3 and is gone in 2.0, so it doesn't
    work at all with Rubinius 2.2, so replace with String#encode.
  4. Luke Imhoff

    msfconsole booting under Rubinius

    limhoff-r7 authored
    msfconsole boots and gets to a prompt, but prints warnings.
  5. Luke Imhoff
  6. Luke Imhoff

    Fix rinda loading

    limhoff-r7 authored
  7. Luke Imhoff

    Fix irb command

    limhoff-r7 authored
  8. Luke Imhoff
  9. Luke Imhoff
  10. Luke Imhoff
Commits on Feb 10, 2014
  1. Luke Imhoff

    Make Msf::Module::Loader::Base spec platform independent

    limhoff-r7 authored
    Rubinius reports the module-path in line 1 instead of 0, so just check
    if the module_path is in any line of the backtrace.
Commits on Feb 23, 2014
  1. Luke Imhoff
Commits on Mar 2, 2014
  1. Luke Imhoff

    Merge remote-tracking branch 'upstream/master'

    limhoff-r7 authored
    Conflicts:
    	external/source/exploits/make.bat
    	lib/msf/core/payload_generator.rb
    	lib/rex/zip/jar.rb
    	modules/encoders/x86/opt_sub.rb
    	modules/exploits/multi/http/dexter_casinoloader_exec.rb
    	msfvenom
    	spec/lib/msf/core/payload_generator_spec.rb
  2. Luke Imhoff

    Fix merge error

    limhoff-r7 authored
  3. Luke Imhoff
  4. Luke Imhoff

    Rescue PrimiteFailure for Regexp.compile

    limhoff-r7 authored
    On rubinius, Regexp.compile(<Integer>) raised PrimitiveFailure instead
    of TypeError raised by MRI.
  5. Luke Imhoff

    Loosen message match on KeyError

    limhoff-r7 authored
    Rubinius's wording is slightly different.
  6. Luke Imhoff

    Remove unreliable with_connection specs

    limhoff-r7 authored
    should_receive(:with_connection) can report varying call counts
    depending on the spec order and it's not possible to separate the
    code-under-test calls from the test setup calls, so remove these
    problematic specs completely since they're just causing random false
    failures.
  7. Luke Imhoff

    Remove remainder of specs using should_receive(:with_connection)

    limhoff-r7 authored
    Too unreliable: unpredicatble failures.
Commits on Mar 3, 2014
  1. Luke Imhoff

    Detect and clean up Thread leaks

    limhoff-r7 authored
    Threads spawned by Msf::Framework#initialize were not being cleaned up,
    which could cause the tests to slow down, so explicitly kill to stop the
    threads and then join them to ensure they aren't left as dead in the
    Thread.list.  Added around(:each) to spec_helper.rb to monitor for
    thread leaks in the future: if a thread is leaked, then the example that
    leaked the thread will fail.
Commits on Mar 19, 2014
  1. Luke Imhoff

    Join killed threads to ensure clean up

    limhoff-r7 authored
    MSP-9425
    
    Call Thread#join after Thread#kill to ensure that the killed thread dies
    completely and is removed from Thread.list.
This page is out of date. Refresh to see the latest.
1  .travis.yml
View
@@ -14,6 +14,7 @@ before_script:
rvm:
#- '1.8.7'
- '1.9.3'
+ - 'rbx'
notifications:
irc: "irc.freenode.org#msfnotify"
26 Gemfile
View
@@ -15,6 +15,32 @@ gem 'robots'
# Needed by db.rb and Msf::Exploit::Capture
gem 'packetfu', '1.1.9'
+platform :rbx do
+ gem 'minitest'
+ gem 'racc'
+ gem 'rubinius-coverage'
+ gem 'rubysl-abbrev'
+ gem 'rubysl-base64'
+ gem 'rubysl-benchmark'
+ gem 'rubysl-bigdecimal'
+ gem 'rubysl-coverage'
+ gem 'rubysl-csv'
+ gem 'rubysl-digest'
+ gem 'rubysl-drb'
+ gem 'rubysl-enumerator'
+ gem 'rubysl-find'
+ gem 'rubysl-ipaddr'
+ gem 'rubysl-irb'
+ gem 'rubysl-logger'
+ gem 'rubysl-mutex_m'
+ gem 'rubysl-observer'
+ gem 'rubysl-open3'
+ gem 'rubysl-rexml'
+ gem 'rubysl-rinda'
+ gem 'rubysl-singleton'
+ gem 'test-unit'
+end
+
group :db do
# Needed for Msf::DbManager
gem 'activerecord'
58 Gemfile.lock
View
@@ -21,12 +21,13 @@ GEM
activesupport (>= 3.0.0)
fivemat (1.2.1)
i18n (0.6.5)
- json (1.8.0)
+ json (1.8.1)
metasploit_data_models (0.16.9)
activerecord (>= 3.2.13)
activesupport
pg
mini_portile (0.5.1)
+ minitest (5.2.2)
msgpack (0.5.5)
multi_json (1.0.4)
network_interface (0.0.1)
@@ -35,6 +36,7 @@ GEM
packetfu (1.1.9)
pcaprub (0.11.3)
pg (0.16.0)
+ racc (1.4.11)
rake (10.1.0)
redcarpet (3.0.0)
robots (0.10.1)
@@ -46,12 +48,43 @@ GEM
rspec-expectations (2.14.2)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.3)
+ rubinius-coverage (2.0.3)
+ rubysl-abbrev (2.0.4)
+ rubysl-base64 (2.0.0)
+ rubysl-benchmark (2.0.1)
+ rubysl-bigdecimal (2.0.2)
+ rubysl-coverage (2.0.3)
+ rubysl-csv (2.0.2)
+ rubysl-english (~> 2.0)
+ rubysl-digest (2.0.3)
+ rubysl-drb (2.0.1)
+ rubysl-e2mmap (2.0.0)
+ rubysl-english (2.0.0)
+ rubysl-enumerator (2.0.0)
+ rubysl-find (2.0.1)
+ rubysl-ipaddr (2.0.0)
+ rubysl-irb (2.0.4)
+ rubysl-e2mmap (~> 2.0)
+ rubysl-mathn (~> 2.0)
+ rubysl-readline (~> 2.0)
+ rubysl-thread (~> 2.0)
+ rubysl-logger (2.0.0)
+ rubysl-mathn (2.0.0)
+ rubysl-mutex_m (2.0.0)
+ rubysl-observer (2.0.0)
+ rubysl-open3 (2.0.0)
+ rubysl-readline (2.0.2)
+ rubysl-rexml (2.0.2)
+ rubysl-rinda (2.0.1)
+ rubysl-singleton (2.0.0)
+ rubysl-thread (2.0.2)
shoulda-matchers (2.3.0)
activesupport (>= 3.0.0)
simplecov (0.5.4)
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
+ test-unit (2.5.5)
timecop (0.6.3)
tzinfo (0.3.37)
yard (0.8.7)
@@ -68,17 +101,40 @@ DEPENDENCIES
fivemat (= 1.2.1)
json
metasploit_data_models (~> 0.16.9)
+ minitest
msgpack
network_interface (~> 0.0.1)
nokogiri
packetfu (= 1.1.9)
pcaprub
pg (>= 0.11)
+ racc
rake (>= 10.0.0)
redcarpet
robots
rspec (>= 2.12)
+ rubinius-coverage
+ rubysl-abbrev
+ rubysl-base64
+ rubysl-benchmark
+ rubysl-bigdecimal
+ rubysl-coverage
+ rubysl-csv
+ rubysl-digest
+ rubysl-drb
+ rubysl-enumerator
+ rubysl-find
+ rubysl-ipaddr
+ rubysl-irb
+ rubysl-logger
+ rubysl-mutex_m
+ rubysl-observer
+ rubysl-open3
+ rubysl-rexml
+ rubysl-rinda
+ rubysl-singleton
shoulda-matchers
simplecov (= 0.5.4)
+ test-unit
timecop
yard
11 lib/msf/core/option_container.rb
View
@@ -472,6 +472,15 @@ def valid?(value)
#
###
class OptRegexp < OptBase
+ regexp_compile_errors = [RegexpError, TypeError]
+
+ # @see https://github.com/rubinius/rubinius/issues/2959
+ if RUBY_ENGINE == 'rbx'
+ regexp_compile_errors << PrimitiveFailure
+ end
+
+ REGEXP_COMPILE_ERRORS = regexp_compile_errors
+
def type
return 'regexp'
end
@@ -486,7 +495,7 @@ def valid?(value)
Regexp.compile(value)
return true
- rescue RegexpError, TypeError
+ rescue *REGEXP_COMPILE_ERRORS
return false
end
end
20 lib/rex/text.rb
View
@@ -330,17 +330,7 @@ def self.to_raw(str)
# Converts ISO-8859-1 to UTF-8
#
def self.to_utf8(str)
-
- if str.respond_to?(:encode)
- # Skip over any bytes that fail to convert to UTF-8
- return str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
- end
-
- begin
- Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
- rescue
- raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
- end
+ str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
end
#
@@ -378,8 +368,8 @@ def self.from_ebcdic_rex(str)
def self.to_ebcdic(str)
begin
- Iconv.iconv("EBCDIC-US", "ASCII", str).first
- rescue ::Iconv::IllegalSequence => e
+ str.encode('EBCDIC-US')
+ rescue Encoding::InvalidByteSequenceError => e
raise e
rescue
self.to_ebcdic_rex(str)
@@ -391,8 +381,8 @@ def self.to_ebcdic(str)
#
def self.from_ebcdic(str)
begin
- Iconv.iconv("ASCII", "EBCDIC-US", str).first
- rescue ::Iconv::IllegalSequence => e
+ str.encode('ASCII')
+ rescue Encoding::InvalidByteSequenceError => e
raise e
rescue
self.from_ebcdic_rex(str)
16 lib/zip/zip.rb
View
@@ -1,11 +1,5 @@
# encoding: ASCII-8BIT
require 'delegate'
-
-begin
- require 'iconv'
-rescue ::LoadError
-end
-
require 'singleton'
require 'tempfile'
require 'fileutils'
@@ -362,15 +356,7 @@ def name_encoding
# Converts string encoding
def encode_string(str, src, dst)
- if str.respond_to?(:encode)
- str.encode(dst, { :invalid => :replace, :undef => :replace, :replace => '' })
- else
- begin
- Iconv.conv(dst, src, str)
- rescue
- raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
- end
- end
+ str.encode(dst, { :invalid => :replace, :undef => :replace, :replace => '' })
end
# Returns the name in the encoding specified by enc
50 msfcli
View
@@ -16,10 +16,27 @@ require 'rex'
class Msfcli
+ #
+ # Attributes
+ #
+
+ # @!attribute [rw] framework
+ # Framework used by Msfcli
+ #
+ # @return [Msf::Simple::Framework]
+ attr_writer :framework
+
+ #
+ # Methods
+ #
+
+ def framework
+ @framework ||= Msf::Simple::Framework.create
+ end
+
def initialize(args)
@args = {}
@indent = ' '
- @framework = nil
@args[:module_name] = args.shift # First argument should be the module name
@args[:mode] = args.pop || 'h' # Last argument should be the mode
@@ -72,7 +89,6 @@ class Msfcli
# msfcli will end up loading EVERYTHING to memory to show you a help
# menu plus a list of modules available. Really expensive if you ask me.
$stdout.puts "[*] Please wait while we load the module tree..."
- framework = Msf::Simple::Framework.create
ext = ''
tbl = Rex::Ui::Text::Table.new(
@@ -282,7 +298,7 @@ class Msfcli
# Initializes exploit/payload/encoder/nop modules.
#
def init_modules
- @framework = Msf::Simple::Framework.create({'DeferModuleLoads'=>true})
+ self.framework = Msf::Simple::Framework.create({'DeferModuleLoads'=>true})
$stdout.puts "[*] Initializing modules..."
module_name = @args[:module_name]
@@ -296,11 +312,11 @@ class Msfcli
whitelist = generate_whitelist
# Load up all the possible modules, this is where things get slow again
- @framework.init_module_paths({:whitelist=>whitelist})
- if (@framework.modules.module_load_error_by_path.length > 0)
+ framework.init_module_paths({:whitelist=>whitelist})
+ if (framework.modules.module_load_error_by_path.length > 0)
print("Warning: The following modules could not be loaded!\n\n")
- @framework.modules.module_load_error_by_path.each do |path, error|
+ framework.modules.module_load_error_by_path.each do |path, error|
print("\t#{path}: #{error}\n\n")
end
@@ -309,16 +325,16 @@ class Msfcli
# Determine what type of module it is
if module_name =~ /exploit\/(.*)/
- modules[:module] = @framework.exploits.create($1)
+ modules[:module] = framework.exploits.create($1)
elsif module_name =~ /auxiliary\/(.*)/
- modules[:module] = @framework.auxiliary.create($1)
+ modules[:module] = framework.auxiliary.create($1)
elsif module_name =~ /post\/(.*)/
- modules[:module] = @framework.post.create($1)
+ modules[:module] = framework.post.create($1)
else
- modules[:module] = @framework.exploits.create(module_name)
+ modules[:module] = framework.exploits.create(module_name)
if modules[:module].nil?
# Try falling back on aux modules
- modules[:module] = @framework.auxiliary.create(module_name)
+ modules[:module] = framework.auxiliary.create(module_name)
end
end
@@ -341,7 +357,7 @@ class Msfcli
# Create the payload to use
if (modules[:module].datastore['PAYLOAD'])
- modules[:payload] = @framework.payloads.create(modules[:module].datastore['PAYLOAD'])
+ modules[:payload] = framework.payloads.create(modules[:module].datastore['PAYLOAD'])
if modules[:payload]
modules[:payload].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_')
end
@@ -349,7 +365,7 @@ class Msfcli
# Create the encoder to use
if modules[:module].datastore['ENCODER']
- modules[:encoder] = @framework.encoders.create(modules[:module].datastore['ENCODER'])
+ modules[:encoder] = framework.encoders.create(modules[:module].datastore['ENCODER'])
if modules[:encoder]
modules[:encoder].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_')
end
@@ -357,7 +373,7 @@ class Msfcli
# Create the NOP to use
if modules[:module].datastore['NOP']
- modules[:nop] = @framework.nops.create(modules[:module].datastore['NOP'])
+ modules[:nop] = framework.nops.create(modules[:module].datastore['NOP'])
if modules[:nop]
modules[:nop].datastore.import_options_from_s(@args[:params].join('_|_'), '_|_')
end
@@ -444,7 +460,7 @@ class Msfcli
Msf::Ui::Console::Driver::DefaultPrompt,
Msf::Ui::Console::Driver::DefaultPromptChar,
{
- 'Framework' => @framework,
+ 'Framework' => framework,
# When I use msfcli, chances are I want speed, so ASCII art fanciness
# probably isn't much of a big deal for me.
'DisableBanner' => true
@@ -464,7 +480,7 @@ class Msfcli
con.run_single("exploit")
# If we have sessions or jobs, keep running
- if @framework.sessions.length > 0 or @framework.jobs.length > 0
+ if framework.sessions.length > 0 or framework.jobs.length > 0
con.run
else
con.run_single("quit")
@@ -547,7 +563,7 @@ class Msfcli
end
# Process special var/val pairs...
- Msf::Ui::Common.process_cli_arguments(@framework, @args[:params])
+ Msf::Ui::Common.process_cli_arguments(framework, @args[:params])
engage_mode(modules)
$stdout.puts
59 spec/lib/msf/core/framework_spec.rb
View
@@ -4,40 +4,47 @@
require 'msf/core/framework'
describe Msf::Framework do
+ include_context 'Msf::Framework'
- describe "#version" do
- CURRENT_VERSION = "4.9.0-dev"
+ subject do
+ framework
+ end
- subject do
- described_class.new
- end
+ context 'CONSTANTS' do
+ context 'Version' do
+ subject(:version) do
+ described_class::Version
+ end
- it "should return the current version" do
- subject.version.should == CURRENT_VERSION
- end
+ it { should == '4.9.0-dev' }
- it "should return the Version constant" do
- described_class.const_get(:Version).should == subject.version
- end
+ it "should return the concatenation of Major.Minor.Point-Release" do
+ major,minor,point,release = version.split(/[.-]/)
+ major.to_i.should == described_class::Major
+ minor.to_i.should == described_class::Minor
+ point.to_i.should == described_class::Point
+ "-#{release}".should == described_class::Release
+ end
- it "should return the concatenation of Major.Minor.Point-Release" do
- major,minor,point,release = subject.version.split(/[.-]/)
- major.to_i.should == described_class::Major
- minor.to_i.should == described_class::Minor
- point.to_i.should == described_class::Point
- "-#{release}".should == described_class::Release
+ pending "conform to SemVer 2.0 syntax: http://semver.org/" do
+ it "should have constants that correspond to SemVer standards" do
+ major,minor,patch,label = subject.version.split(/[.-]/)
+ major.to_i.should == described_class::VERSION::MAJOR
+ minor.to_i.should == described_class::VERSION::MINOR
+ point.to_i.should == described_class::VERSION::POINT
+ label.to_s.should == described_class::VERSION::LABEL
+ end
+ end
end
+ end
- pending "conform to SemVer 2.0 syntax: http://semver.org/" do
- it "should have constants that correspond to SemVer standards" do
- major,minor,patch,label = subject.version.split(/[.-]/)
- major.to_i.should == described_class::VERSION::MAJOR
- minor.to_i.should == described_class::VERSION::MINOR
- point.to_i.should == described_class::VERSION::POINT
- label.to_s.should == described_class::VERSION::LABEL
- end
+ describe "#version" do
+ subject(:version) do
+ framework.version
end
+ it "should return the Version constant" do
+ expect(version).to eq(described_class::Version)
+ end
end
-
end
6 spec/lib/msf/core/modules/loader/base_spec.rb
View
@@ -148,7 +148,11 @@ module #{namespace_module_names[2]}
end
error.should_not be_nil
- error.backtrace[0].should include(module_path)
+ # The position of the line that includes the module_path can vary based on ruby engine, so just check for
+ # it on any line.
+ error.backtrace.any? { |line|
+ line.include? module_path
+ }.should be_true
end
end
end
2  spec/lib/msf/core/payload_generator_spec.rb
View
@@ -91,7 +91,7 @@
}
}
- it { should raise_error(KeyError, "key not found: :framework") }
+ it { should raise_error(KeyError, /framework/) }
end
context 'when not given a payload' do
9 spec/lib/msf/core/task_manager_spec.rb
View
@@ -1,16 +1,15 @@
# -*- coding:binary -*-
+require 'spec_helper'
+
require 'msf/core'
require 'msf/core/task_manager'
describe Msf::TaskManager do
-
- let(:framework) do
- Msf::Framework.new
- end
+ include_context 'Msf::Framework'
let(:tm) do
- Msf::TaskManager.new(framework)
+ described_class.new(framework)
end
it "should have attributes" do
66 spec/lib/msf/db_manager_spec.rb
View
@@ -89,14 +89,6 @@ def purge_all_module_details
end
context 'without modules_caching' do
- it 'should create a connection' do
- # in purge_all_module_details
- # in after(:each)
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice.and_call_original
-
- purge_all_module_details
- end
-
it 'should destroy all Mdm::Module::Details' do
expect {
purge_all_module_details
@@ -128,14 +120,6 @@ def purge_all_module_details
true
end
- it 'should create connection' do
- # 1st time from with_established_connection
- # 2nd time from report_session
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).exactly(2).times
-
- report_session
- end
-
context 'with :session' do
before(:each) do
options[:session] = session
@@ -752,13 +736,6 @@ def purge_all_module_details
end
it { should be_nil }
-
- it 'should not create a connection' do
- # 1st time for with_established_connection
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).once
-
- report_session
- end
end
end
@@ -1273,42 +1250,6 @@ def update_all_module_details
false
end
- it 'should create a connection' do
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice.and_call_original
-
- update_all_module_details
- end
-
- it 'should set framework.cache_thread to current thread and then nil around connection' do
- framework.should_receive(:cache_thread=).with(Thread.current).ordered
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered
- framework.should_receive(:cache_thread=).with(nil).ordered
-
- update_all_module_details
-
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
- end
-
- it 'should set modules_cached to false and then true around connection' do
- db_manager.should_receive(:modules_cached=).with(false).ordered
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered
- db_manager.should_receive(:modules_cached=).with(true).ordered
-
- update_all_module_details
-
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
- end
-
- it 'should set modules_caching to true and then false around connection' do
- db_manager.should_receive(:modules_caching=).with(true).ordered
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered
- db_manager.should_receive(:modules_caching=).with(false).ordered
-
- update_all_module_details
-
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
- end
-
context 'with Mdm::Module::Details' do
let(:module_pathname) do
parent_pathname.join(
@@ -1481,13 +1422,6 @@ def loader.load_error(module_path, error)
true
end
- it 'should create connection' do
- ActiveRecord::Base.connection_pool.should_receive(:with_connection)
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).and_call_original
-
- update_module_details
- end
-
it 'should call module_to_details_hash to get Mdm::Module::Detail attributes and association attributes' do
db_manager.should_receive(:module_to_details_hash).and_call_original
468 spec/msfcli_spec.rb
View
@@ -82,10 +82,19 @@ def get_stdout(&block)
# This one is slow because we're loading all modules
#
context ".dump_module_list" do
+ let(:cli) do
+ cli = Msfcli.new([])
+ end
+
+ include_context 'Msf::ThreadManager' do
+ let(:thread_manager) do
+ cli.framework.threads
+ end
+ end
+
it "it should dump a list of modules" do
tbl = ''
stdout = get_stdout {
- cli = Msfcli.new([])
tbl = cli.dump_module_list
}
tbl.should =~ /Exploits/ and stdout.should =~ /Please wait/
@@ -93,7 +102,9 @@ def get_stdout(&block)
end
context ".guess_payload_name" do
- cli = Msfcli.new([])
+ let(:cli) do
+ Msfcli.new([])
+ end
it "should contain matches nedded for windows/meterpreter/reverse_tcp" do
m = cli.guess_payload_name('windows/meterpreter/reverse_tcp')
@@ -137,7 +148,10 @@ def get_stdout(&block)
end
context ".guess_encoder_name" do
- cli = Msfcli.new([])
+ let(:cli) do
+ Msfcli.new([])
+ end
+
it "should contain a match for x86/shikata_ga_nai" do
encoder = 'x86/shikata_ga_nai'
m = cli.guess_encoder_name(encoder)
@@ -146,7 +160,10 @@ def get_stdout(&block)
end
context ".guess_nop_name" do
- cli = Msfcli.new([])
+ let(:cli) do
+ Msfcli.new([])
+ end
+
it "should contain a match for guess_nop_name" do
nop = 'x86/single_byte'
m = cli.guess_nop_name(nop)
@@ -222,197 +239,340 @@ def get_stdout(&block)
end
context ".init_modules" do
+ include_context 'Msf::ThreadManager' do
+ let(:thread_manager) do
+ cli.framework.threads
+ end
+ end
- it "should inititalize an exploit module" do
- args = 'exploit/windows/smb/psexec S'
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
- m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ subject(:init_modules) do
+ cli.init_modules
end
- it "should inititalize an auxiliary module" do
- args = 'auxiliary/server/browser_autopwn S'
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
- m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ let(:cli) do
+ described_class.new(args)
end
- it "should inititalize a post module" do
- args = 'post/windows/gather/credentials/gpp S'
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
- m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ let(:args) do
+ []
end
- it "should have multi/handler module initialized" do
- args = "multi/handler payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E"
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
+ context 'with exploit' do
+ let(:args) do
+ [
+ 'exploit/windows/smb/psexec',
+ 'S'
+ ]
+ end
- m[:module].class.to_s.should =~ /^Msf::Modules::/
- end
+ it "should inititalize an exploit module" do
+ m = nil
- it "should have my payload windows/meterpreter/reverse_tcp initialized" do
- args = "multi/handler payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E"
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
+ get_stdout {
+ m = cli.init_modules
+ }
- m[:payload].class.to_s.should =~ /<Class:/
+ m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ end
end
- it "should have my modules initialized with the correct parameters" do
- args = "multi/handler payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E"
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
+ context 'with auxiliary' do
+ let(:args) do
+ [
+ 'auxiliary/server/browser_autopwn',
+ 'S'
+ ]
+ end
- m[:module].datastore['lhost'].should eq("127.0.0.1")
- end
+ it "should inititalize an auxiliary module" do
+ m = nil
- it "should give me an empty hash as a result of an invalid module name" do
- args = "WHATEVER payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E"
- m = ''
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- }
+ get_stdout {
+ m = cli.init_modules
+ }
- m.should eq({})
+ m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ end
end
- end
- context ".engage_mode" do
- it "should show me the summary of module auxiliary/scanner/http/http_version" do
- args = 'auxiliary/scanner/http/http_version s'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
+ context 'with post' do
+ let(:args) do
+ %w{post/windows/gather/credentials/gpp S}
+ end
- stdout.should =~ /Module: auxiliary\/scanner\/http\/http_version/
- end
+ it "should inititalize a post module" do
+ m = nil
- it "should show me the options of module auxiliary/scanner/http/http_version" do
- args = 'auxiliary/scanner/http/http_version O'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
+ get_stdout {
+ m = cli.init_modules
+ }
- stdout.should =~ /The target address range or CIDR identifier/
+ m[:module].class.to_s.should start_with("Msf::Modules::Mod")
+ end
end
- it "should me the advanced options of module auxiliary/scanner/http/http_version" do
- args = 'auxiliary/scanner/http/http_version A'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
+ context 'with multi/handler' do
+ let(:args) do
+ %w{multi/handler payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E}
+ end
+
+ it "should have multi/handler module initialized" do
+ m = nil
+ stdout = get_stdout {
+ m = cli.init_modules
+ }
- stdout.should =~ /UserAgent/
+ m[:module].class.to_s.should =~ /^Msf::Modules::/
+ end
end
- it "should show me the IDS options of module auxiliary/scanner/http/http_version" do
- args = 'auxiliary/scanner/http/http_version I'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /Insert fake relative directories into the uri/
+ context 'with options' do
+ let(:args) do
+ %w{multi/handler payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E}
+ end
+
+ it "should have my payload initialized" do
+ m = nil
+ get_stdout {
+ m = cli.init_modules
+ }
+
+ m[:payload].class.to_s.should =~ /<Class:/
+ end
+
+ it "should have my modules initialized with the correct parameters" do
+ m = nil
+ get_stdout {
+ m = cli.init_modules
+ }
+
+ m[:module].datastore['lhost'].should eq("127.0.0.1")
+ end
end
- it "should show me the targets available for module windows/browser/ie_cbutton_uaf" do
- args = "windows/browser/ie_cbutton_uaf T"
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /IE 8 on Windows 7/
+ context 'with invalid module name' do
+ let(:args) do
+ %w{WHATEVER payload=windows/meterpreter/reverse_tcp lhost=127.0.0.1 E}
+ end
+
+ it "should give me an empty hash as a result of an invalid module name" do
+ m = nil
+ get_stdout {
+ m = cli.init_modules
+ }
+
+ m.should eq({})
+ end
end
+ end
- it "should show me the payloads available for module windows/browser/ie_cbutton_uaf" do
- args = "windows/browser/ie_cbutton_uaf P"
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /windows\/meterpreter\/reverse_tcp/
+ context ".engage_mode" do
+ include_context 'Msf::ThreadManager' do
+ let(:thread_manager) do
+ cli.framework.threads
+ end
end
- it "should try to run the check function of an exploit" do
- args = "windows/smb/ms08_067_netapi rhost=0.0.0.1 C" # Some BS IP so we can fail
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /#{Msf::Exploit::CheckCode::Unknown[1]}/
+ let(:cli) do
+ described_class.new(args)
end
- it "should warn my auxiliary module isn't supported by mode 'p' (show payloads)" do
- args = 'auxiliary/scanner/http/http_version p'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /This type of module does not support payloads/
+ let(:args) do
+ nil
end
- it "should warn my auxiliary module isn't supported by mode 't' (show targets)" do
- args = 'auxiliary/scanner/http/http_version t'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /This type of module does not support targets/
+ context 'with s' do
+ let(:args) do
+ %w{auxiliary/scanner/http/http_version s}
+ end
+
+ it "should show me the summary of module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /Module: auxiliary\/scanner\/http\/http_version/
+ end
end
- it "should warn my exploit module isn't supported by mode 'ac' (show actions)" do
- args = 'windows/browser/ie_cbutton_uaf ac'
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /This type of module does not support actions/
+ context 'with O' do
+ let(:args) do
+ %w{auxiliary/scanner/http/http_version O}
+ end
+
+ it "should show me the options of module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /The target address range or CIDR identifier/
+ end
end
- it "should show actions available for module auxiliary/scanner/http/http_put" do
- args = "auxiliary/scanner/http/http_put ac"
- stdout = get_stdout {
- cli = Msfcli.new(args.split(' '))
- m = cli.init_modules
- cli.engage_mode(m)
- }
- stdout.should =~ /DELETE/
+ context 'with A' do
+ let(:args) do
+ %w{auxiliary/scanner/http/http_version A}
+ end
+
+ it "should me the advanced options of module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /UserAgent/
+ end
end
- end
+ context 'with I' do
+ let(:args) do
+ %w{auxiliary/scanner/http/http_version I}
+ end
+
+ it "should show me the IDS options of module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+ stdout.should =~ /Insert fake relative directories into the uri/
+ end
+ end
+
+ context 'with T' do
+ let(:args) do
+ [
+ module_name,
+ 'T'
+ ]
+ end
+
+ context 'with auxiliary' do
+ let(:module_name) do
+ 'auxiliary/scanner/http/http_version'
+ end
+
+ it "should warn my auxiliary module isn't supported by mode 't' (show targets)" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /This type of module does not support targets/
+ end
+ end
+
+ context 'with exploit' do
+ let(:module_name) do
+ 'windows/browser/ie_cbutton_uaf'
+ end
+
+ it "should show me the targets available for module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /IE 8 on Windows 7/
+ end
+ end
+ end
+
+ context 'with P' do
+ let(:args) do
+ [
+ module_name,
+ 'P'
+ ]
+ end
+
+ context 'with auxiliary' do
+ let(:module_name) do
+ 'auxiliary/scanner/http/http_version'
+ end
+
+ it "should warn my auxiliary module isn't supported by mode 'p' (show payloads)" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /This type of module does not support payloads/
+ end
+ end
+
+ context 'with exploit' do
+ let(:module_name) do
+ 'windows/browser/ie_cbutton_uaf'
+ end
+
+ it "should show me the payloads available for module " do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /windows\/meterpreter\/reverse_tcp/
+ end
+ end
+ end
+
+ context 'with C' do
+ let(:args) do
+ # Some BS IP so we can fail
+ %w{windows/smb/ms08_067_netapi rhost=0.0.0.1 C}
+ end
+
+ it "should try to run the check function of an exploit" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /#{Msf::Exploit::CheckCode::Unknown[1]}/
+ end
+ end
+
+ context 'with AC' do
+ let(:args) do
+ [
+ module_name,
+ 'AC'
+ ]
+ end
+
+ context 'with auxiliary' do
+ let(:module_name) do
+ "auxiliary/scanner/http/http_put"
+ end
+
+ it "should show actions available for module" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /DELETE/
+ end
+ end
+
+ context 'with exploit' do
+ let(:module_name) do
+ 'windows/browser/ie_cbutton_uaf'
+ end
+
+ it "should warn my exploit module isn't supported by mode 'ac' (show actions)" do
+ stdout = get_stdout {
+ m = cli.init_modules
+ cli.engage_mode(m)
+ }
+
+ stdout.should =~ /This type of module does not support actions/
+ end
+ end
+ end
+ end
end
end
22 spec/spec_helper.rb
View
@@ -45,5 +45,27 @@
FactoryGirl.find_definitions
end
+
+ config.around(:each) do |example|
+ threads_before = Thread.list
+
+ begin
+ example.run
+ ensure
+ threads_after = Thread.list
+ threads_remaining = threads_after - threads_before
+
+ unless threads_remaining.empty?
+ $stderr.puts "#{threads_remaining.count} thread left over after #{self.example.full_description}"
+
+ threads_remaining.each do |thread|
+ $stderr.puts thread
+ end
+
+ # fail the spec
+ expect(threads_remaining).to be_empty
+ end
+ end
+ end
end
11 spec/support/shared/contexts/msf/framework.rb
View
@@ -0,0 +1,11 @@
+shared_context 'Msf::Framework' do
+ include_context 'Msf::ThreadManager' do
+ let(:thread_manager) do
+ framework.threads
+ end
+ end
+
+ let(:framework) do
+ Msf::Framework.new
+ end
+end
4 spec/support/shared/contexts/msf/simple/framework.rb
View
@@ -33,8 +33,12 @@
thread_manager.each do |thread|
thread.kill
+ # join after kill to ensure kill completed and thread is removed form Thread.list
+ thread.join
end
thread_manager.monitor.kill
+ # join after kill to ensure kill completed and thread is removed form Thread.list
+ thread_manager.monitor.join
end
end
11 spec/support/shared/contexts/msf/thread_manager.rb
View
@@ -0,0 +1,11 @@
+shared_context 'Msf::ThreadManager' do
+ after(:each) do
+ thread_manager.each do |thread|
+ thread.kill
+ thread.join
+ end
+
+ thread_manager.monitor.kill
+ thread_manager.monitor.join
+ end
+end
2  spec/support/shared/examples/msf/db_manager/import_msf_xml.rb
View
@@ -556,7 +556,7 @@ def with_info
it 'should raise KeyError' do
expect {
import_msf_web_element
- }.to raise_error(KeyError, 'key not found: :type')
+ }.to raise_error(KeyError, /type/)
end
end
end
6 spec/support/shared/examples/msf/db_manager/migration.rb
View
@@ -6,12 +6,6 @@ def migrate
db_manager.migrate
end
- it 'should create a connection' do
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice
-
- migrate
- end
-
it 'should call ActiveRecord::Migrator.migrate' do
ActiveRecord::Migrator.should_receive(:migrate).with(
ActiveRecord::Migrator.migrations_paths
8 spec/support/shared/examples/msf/module_manager/cache.rb
View
@@ -373,14 +373,6 @@ def module_info_by_path_from_database!
framework.db.connect(spec)
end
- it 'should call ActiveRecord::Base.connection_pool.with_connection' do
- # 1st is from with_established_connection
- # 2nd is from module_info_by_path_from_database!
- ActiveRecord::Base.connection_pool.should_receive(:with_connection).at_least(2).times
-
- module_info_by_path_from_database!
- end
-
it 'should use ActiveRecord::Batches#find_each to enumerate Mdm::Module::Details in batches' do
Mdm::Module::Detail.should_receive(:find_each)
Something went wrong with that request. Please try again.