require 'ronin/exploits/exploit' require 'spec_helper' require 'helpers/objects' require 'controls/behaviors_examples' describe Exploits::Exploit do before(:each) do @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' exp2.should be_valid end it "should have a unique name and version" do first_exp = Exploits::Exploit.create( :name => 'test2', :version => '0.0.1' ) first_exp.should be_valid second_exp = Exploits::Exploit.new( :name => 'test2', :version => '0.0.1' ) second_exp.should_not be_valid third_exp = Exploits::Exploit.new( :name => 'test2', :version => '0.0.2' ) third_exp.should be_valid 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 lambda { @exploit.instance_eval { helper :obvious_not_there } }.should raise_error(Exploits::UnknownHelper) end it "should have targeted Archs" do @exploit.targeted_archs.should == [Arch.i686, Arch.i386] end it "should have targeted OSes" do @exploit.targeted_oses.should == [ OS.linux('2.6.23'), OS.windows('7.1') ] end it "should have targeted products" do @exploit.targeted_products.all? { |product| product.name == 'ExampleWare' && product.version == '1.5' }.should == true end 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 @exploit.target.arch.should == Arch.i686 @exploit.target.os.name.should == 'Linux' @exploit.target.os.version.should == '2.6.23' end it "should have a default targeted Arch" do @exploit.arch.should == Arch.i686 end it "should have a default targeted OS" do @exploit.os.should == OS.linux('2.6.23') end 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.raw_payload = 'data' @exploit.encode_payload! @exploit.encoded_payload.should == 'data' end it "should encode a String using encoders" do @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.raw_payload = 'data' @exploit.encoders << lambda { |payload| nil } @exploit.encode_payload! @exploit.encoded_payload.should == 'data' end it "should have 'unbuilt' and 'built' states" do @exploit.should_not be_built @exploit.build! @exploit.should be_built end 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 @exploit.build! @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 == 'simple 0.2' end it "should have a custom inspect method" do @exploit.inspect.should == '#' 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