diff --git a/lib/rex/java/serialization/model.rb b/lib/rex/java/serialization/model.rb index 68d42a6afa..8709d0da61 100644 --- a/lib/rex/java/serialization/model.rb +++ b/lib/rex/java/serialization/model.rb @@ -3,4 +3,5 @@ require 'rex/java/serialization/model/end_block_data' require 'rex/java/serialization/model/null_reference' require 'rex/java/serialization/model/utf' require 'rex/java/serialization/model/long_utf' +require 'rex/java/serialization/model/block_data' require 'rex/java/serialization/model/field' \ No newline at end of file diff --git a/lib/rex/java/serialization/model/block_data.rb b/lib/rex/java/serialization/model/block_data.rb new file mode 100644 index 0000000000..c290888c4b --- /dev/null +++ b/lib/rex/java/serialization/model/block_data.rb @@ -0,0 +1,55 @@ +module Rex + module Java + module Serialization + module Model + # This class provides a block data representation + class BlockData < Element + + # @!attribute length + # @return [Integer] the length of the block + attr_accessor :length + # @!attribute contents + # @return [String] the contents of the block + attr_accessor :contents + + # @param contents [String] the contents of the block + def initialize(contents = '') + self.contents = contents + self.length = contents.length + end + + # Unserializes a Java::Serialization::Model::BlockData + # + # @param io [IO] the io to read from + # @return [self] if deserialization is possible + # @return [nil] if deserialization isn't possible + def decode(io) + raw_length = io.read(1) + return nil if raw_length.nil? + self.length = raw_length.unpack('C')[0] + + if length == 0 + self.contents = '' + else + self.contents = io.read(length) + return nil if contents.nil? || contents.length != length + end + + self + end + + # Serializes the Java::Serialization::Model::BlockData + # + # @return [String] if serialization is possible + # @return [nil] if serialization isn't possible + def encode + encoded = [length].pack('C') + encoded << contents + + encoded + end + end + end + end + end +end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/block_data_spec.rb b/spec/lib/rex/java/serialization/model/block_data_spec.rb new file mode 100644 index 0000000000..7145521112 --- /dev/null +++ b/spec/lib/rex/java/serialization/model/block_data_spec.rb @@ -0,0 +1,91 @@ +require 'rex/java' +require 'stringio' + +describe Rex::Java::Serialization::Model::BlockData do + subject(:block) do + described_class.new + end + + let(:sample_block) { "\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" } + let(:sample_block_io) { StringIO.new(sample_block) } + let(:empty_block) { "\x00" } + let(:empty_block_io) { StringIO.new(empty_block) } + let(:incomplete_block) { "\x10\x01\x02\x03\x04\x05" } + let(:incomplete_block_io) { StringIO.new(incomplete_block) } + let(:empty_io) { StringIO.new('') } + + describe ".new" do + it "Rex::Java::Serialization::Model::BlockData" do + expect(block).to be_a(Rex::Java::Serialization::Model::BlockData) + end + + it "initializes length to 0" do + expect(block.length).to eq(0) + end + + it "initializes contents with empty string" do + expect(block.contents).to be_empty + end + end + + describe "#encode" do + context "when empty block" do + it { expect(block.encode).to eq(empty_block) } + end + + context "when filled block" do + it do + block.length = 16 + block.contents = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + expect(block.encode).to eq(sample_block) + end + end + end + + describe "#decode" do + context "when stream contains empty string" do + it "returns nil" do + expect(block.decode(empty_io)).to be_nil + end + end + + context "when stream contains empty block" do + it "returns a Rex::Java::Serialization::Model::BlockData" do + expect(block.decode(empty_block_io)).to be_a(Rex::Java::Serialization::Model::BlockData) + end + + it "sets length to 0" do + block.decode(empty_block_io) + expect(block.length).to eq(0) + end + + it "sets contents to empty string" do + block.decode(empty_block_io) + expect(block.contents).to be_empty + end + end + + context "when stream contains incomplete block" do + it "returns nil" do + expect(block.decode(incomplete_block_io)).to be_nil + end + end + + context "when stream contains correct block" do + + it "returns a Rex::Java::Serialization::Model::BlockData" do + expect(block.decode(sample_block_io)).to be_a(Rex::Java::Serialization::Model::BlockData) + end + + it "sets length to 0" do + block.decode(sample_block_io) + expect(block.length).to eq(16) + end + + it "sets contents to sample string" do + block.decode(sample_block_io) + expect(block.contents).to eq("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10") + end + end + end +end \ No newline at end of file