Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Rubinius support for specs and travis-ci #3053

Closed
wants to merge 27 commits into from

4 participants

@limhoff-r7
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
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' 12a1e8a
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' c7c7653
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' a6cdad1
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' 69b04b4
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' cd0d7be
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' f7f3cb9
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' 6f59b34
@limhoff-r7 limhoff-r7 And standard library gems for Rubinius b2aaf3d
@limhoff-r7 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
@limhoff-r7 limhoff-r7 msfconsole booting under Rubinius
msfconsole boots and gets to a prompt, but prints warnings.
003f88b
@limhoff-r7 limhoff-r7 Fix load warnings before rinda 79e5978
@limhoff-r7 limhoff-r7 Fix rinda loading c8e4de2
@limhoff-r7 limhoff-r7 Fix irb command b77adac
@limhoff-r7 limhoff-r7 Add rubinius (rbx) to travis-ci builds fe69f6a
@limhoff-r7 limhoff-r7 Add msfcli_spec dependencies 31fbf31
@limhoff-r7 limhoff-r7 Add coverage libraries for simplecov 9410288
@limhoff-r7 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
@limhoff-r7 limhoff-r7 Merge remote-tracking branch 'upstream/master' 528856d
@limhoff-r7 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
@limhoff-r7 limhoff-r7 Fix merge error 89462d4
@limhoff-r7 limhoff-r7 Merge branch 'master' into feature/rubinius 3d196cb
@limhoff-r7 limhoff-r7 Rescue PrimiteFailure for Regexp.compile
On rubinius, Regexp.compile(<Integer>) raised PrimitiveFailure instead
of TypeError raised by MRI.
13972f8
@limhoff-r7 limhoff-r7 Loosen message match on KeyError
Rubinius's wording is slightly different.
5afc145
@limhoff-r7 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
@limhoff-r7 limhoff-r7 Remove remainder of specs using should_receive(:with_connection)
Too unreliable: unpredicatble failures.
be79e6b
@limhoff-r7 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
@limhoff-r7
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.
@mbuck-r7
Collaborator
@limhoff-r7 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
@limhoff-r7
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.

@limhoff-r7
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. @limhoff-r7
Commits on Dec 6, 2013
  1. @limhoff-r7
Commits on Dec 12, 2013
  1. @limhoff-r7
Commits on Dec 14, 2013
  1. @limhoff-r7
Commits on Dec 21, 2013
  1. @limhoff-r7
Commits on Jan 16, 2014
  1. @limhoff-r7
Commits on Feb 9, 2014
  1. @limhoff-r7
  2. @limhoff-r7
  3. @limhoff-r7

    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. @limhoff-r7

    msfconsole booting under Rubinius

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

    Fix rinda loading

    limhoff-r7 authored
  7. @limhoff-r7

    Fix irb command

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

    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. @limhoff-r7
Commits on Mar 2, 2014
  1. @limhoff-r7

    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. @limhoff-r7

    Fix merge error

    limhoff-r7 authored
  3. @limhoff-r7
  4. @limhoff-r7

    Rescue PrimiteFailure for Regexp.compile

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

    Loosen message match on KeyError

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

    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. @limhoff-r7

    Remove remainder of specs using should_receive(:with_connection)

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

    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. @limhoff-r7

    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.
View
1  .travis.yml
@@ -14,6 +14,7 @@ before_script:
rvm:
#- '1.8.7'
- '1.9.3'
+ - 'rbx'
notifications:
irc: "irc.freenode.org#msfnotify"
View
26 Gemfile
@@ -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'
View
58 Gemfile.lock
@@ -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
View
11 lib/msf/core/option_container.rb
@@ -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
View
20 lib/rex/text.rb
@@ -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)
View
16 lib/zip/zip.rb
@@ -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
View
50 msfcli
@@ -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
View
59 spec/lib/msf/core/framework_spec.rb
@@ -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
View
6 spec/lib/msf/core/modules/loader/base_spec.rb
@@ -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
View
2  spec/lib/msf/core/payload_generator_spec.rb
@@ -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
View
9 spec/lib/msf/core/task_manager_spec.rb
@@ -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
View
66 spec/lib/msf/db_manager_spec.rb
@@ -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
View
468 spec/msfcli_spec.rb
@@ -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
View
22 spec/spec_helper.rb
@@ -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
View
11 spec/support/shared/contexts/msf/framework.rb
@@ -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
View
4 spec/support/shared/contexts/msf/simple/framework.rb
@@ -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
View
11 spec/support/shared/contexts/msf/thread_manager.rb
@@ -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
View
2  spec/support/shared/examples/msf/db_manager/import_msf_xml.rb
@@ -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
View
6 spec/support/shared/examples/msf/db_manager/migration.rb
@@ -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
View
8 spec/support/shared/examples/msf/module_manager/cache.rb
@@ -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.