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