spec/exploits/exploit_spec.rb in ronin-exploits-0.2.1 vs spec/exploits/exploit_spec.rb in ronin-exploits-0.3.0
- old
+ new
@@ -1,15 +1,20 @@
require 'ronin/exploits/exploit'
require 'spec_helper'
require 'helpers/objects'
+require 'controls/behaviors_examples'
describe Exploits::Exploit do
before(:each) do
- @exploit = load_exploit('test')
+ @exploit = load_exploit('simple')
+ @payload = load_payload('simple')
+ @controler = @exploit
end
+ it_should_behave_like "controls behaviors"
+
it "should require a name attribute" do
exp2 = Exploits::Exploit.new
exp2.should_not be_valid
exp2.name = 'test'
@@ -34,23 +39,10 @@
:version => '0.0.2'
)
third_exp.should be_valid
end
- it "should not have any allowances by default" do
- @exploit.allows.should be_empty
- end
-
- it "should specify the behaviors allowed by the exploit" do
- @exploit.allowing :memory_read, :memory_write
-
- @exploit.behaviors.should == [
- Vuln::Behavior[:memory_read],
- Vuln::Behavior[:memory_write]
- ]
- end
-
it "should allow for the extending of Helper modules" do
@exploit.instance_eval { helper :padding }.should == true
end
it "should raise an UnknownHelper when extending an unknown helper" do
@@ -74,13 +66,25 @@
@exploit.targeted_products.all? { |product|
product.name == 'ExampleWare' && product.version == '1.5'
}.should == true
end
- it "should allow the explicit selection of a target" do
- @exploit.select_target { |target| target.arch == Arch.i686 }
+ it "should allow the selection of a target by index" do
+ @exploit.use_target!(1)
+ @exploit.target.arch.should == Arch.i386
+ end
+
+ it "should allow the selection of a target that matches a block" do
+ @exploit.use_target! { |target| target.arch == Arch.i386 }
+
+ @exploit.target.arch.should == Arch.i386
+ end
+
+ it "should select the first target if nothing is passed to use_target!" do
+ @exploit.use_target!()
+
@exploit.target.arch.should == Arch.i686
end
it "should have a default target" do
@exploit.target.should_not be_nil
@@ -102,27 +106,122 @@
it "should have a default targeted Product" do
@exploit.product.name.should == 'ExampleWare'
@exploit.product.version.should == '1.5'
end
+ it "should set the payloads exploit when setting the payload" do
+ @payload.exploit.should be_nil
+
+ @exploit.payload = @payload
+ @payload.exploit.should == @exploit
+ end
+
+ it "should be able to set the payload to nil" do
+ @exploit.payload = @payload
+ @exploit.payload = nil
+
+ @exploit.payload.should be_nil
+ end
+
+ it "should set the payload and the exploit of the payload to nil" do
+ @exploit.payload = @payload
+ @exploit.payload = nil
+
+ @payload.exploit.should be_nil
+ end
+
+ it "should specify the additional behaviors controlled by the payload" do
+ @payload.control :code_exec
+ @payload.control :command_exec
+ @exploit.control :code_exec
+
+ @exploit.payload = @payload
+
+ @exploit.behaviors.should == [:code_exec, :command_exec]
+ end
+
+ it "should build a raw payload" do
+ @exploit.payload = @payload
+ @exploit.build_payload!
+
+ @exploit.raw_payload.should == 'code.func'
+ end
+
+ it "should pass options to the payload when building the raw payload" do
+ @exploit.payload = @payload
+ @exploit.build_payload!(:custom => 'test')
+
+ @exploit.raw_payload.should == 'code.test'
+ end
+
+ it "should default raw_payload to an empty String, if payload is nil" do
+ @exploit.payload = nil
+ @exploit.build_payload!
+
+ @exploit.raw_payload.should == ''
+ end
+
+ it "should not reset raw_payload, if payload is nil" do
+ @exploit.payload = nil
+ @exploit.raw_payload = 'data'
+
+ @exploit.build_payload!
+ @exploit.raw_payload.should == 'data'
+ end
+
+ it "should have no payload encoders by default" do
+ @exploit.encoders.should be_empty
+ end
+
+ it "should accept blocks as payload encoders" do
+ @exploit.raw_payload = 'data'
+
+ @exploit.encode_payload do |payload|
+ payload.capitalize
+ end
+
+ @exploit.encode_payload!
+ @exploit.encoded_payload.should == 'Data'
+ end
+
+ it "should accept an object with an #encode method" do
+ @exploit.raw_payload = 'data'
+ @exploit.encode_payload(Payloads::Encoders::Encoder.new)
+
+ @exploit.encode_payload!
+ @exploit.encoded_payload.should == 'data'
+ end
+
+ it "should not accept objects without an #encode method" do
+ lambda {
+ @exploit.encode_payload(Object.new)
+ }.should raise_error(RuntimeError)
+ end
+
+ it "should accept either a payload encoder object or a block" do
+ lambda {
+ @exploit.encode_payload()
+ }.should raise_error(ArgumentError)
+ end
+
it "should encode a String payload" do
- @exploit.payload = 'data'
+ @exploit.raw_payload = 'data'
@exploit.encode_payload!
@exploit.encoded_payload.should == 'data'
end
it "should encode a String using encoders" do
- @exploit.payload = 'data'
+ @exploit.raw_payload = 'data'
@exploit.encoders << lambda { |payload| payload.upcase }
@exploit.encode_payload!
@exploit.encoded_payload.should == 'DATA'
end
it "should ignore payload encoders which return nil" do
- @exploit.payload = 'data'
+ @exploit.raw_payload = 'data'
@exploit.encoders << lambda { |payload| nil }
@exploit.encode_payload!
@exploit.encoded_payload.should == 'data'
end
@@ -131,14 +230,26 @@
@exploit.should_not be_built
@exploit.build!
@exploit.should be_built
end
- it "should return the result of the builder" do
- @exploit.build!.should == 'result'
+ it "should pass the built exploit to a given block" do
+ @exploit.build! do |exploit|
+ exploit.should be_built
+ end
end
+ it "should respect the arity of blocks passed to build!" do
+ @exploit.build! do
+ @exploit.should be_built
+ end
+ end
+
+ it "should return the built exploit" do
+ @exploit.build!.should be_built
+ end
+
it "should require the exploit is built before being deployed" do
lambda { @exploit.deploy! }.should raise_error(Exploits::ExploitNotBuilt)
end
it "should have a default deployer method" do
@@ -147,13 +258,56 @@
@exploit.deploy! do |exploit|
@exploit.should == exploit
end
end
+ it "should respect the arity of blocks passed to deploy!" do
+ @exploit.build!
+
+ @exploit.deploy! do
+ @exploit.should be_deployed
+ end
+ end
+
+ it "should deploy the payload after deploying the exploit" do
+ @exploit.payload = @payload
+ @payload.should_not be_deployed
+
+ @exploit.build!
+ @exploit.deploy! do |exploit|
+ exploit.payload.should be_deployed
+ end
+ end
+
+ it "should build and deploy the exploit when exploited" do
+ @exploit.exploit!
+
+ @exploit.should be_built
+ @exploit.should be_deployed
+ end
+
+ it "should not deploy during a dry-run of the exploit" do
+ @exploit.exploit!(:dry_run => true)
+
+ @exploit.should be_built
+ @exploit.should_not be_deployed
+ end
+
it "should return the name and the version when calling to_s" do
- @exploit.to_s.should == 'test 0.2'
+ @exploit.to_s.should == 'simple 0.2'
end
it "should have a custom inspect method" do
- @exploit.inspect.should == '#<Ronin::Exploits::Exploit: test 0.2>'
+ @exploit.inspect.should == '#<Ronin::Exploits::Exploit: simple 0.2>'
+ end
+
+ it "should pass missing methods to the payload" do
+ @exploit.payload = @payload
+ @exploit.some_control.should == 'control data'
+ end
+
+ it "should not pass missing methods, if payload is nil" do
+ lambda {
+ @exploit.some_control
+ }.should raise_error(NoMethodError)
end
end