260 lines
7.8 KiB
Ruby
260 lines
7.8 KiB
Ruby
|
# -*- coding:binary -*-
|
||
|
require 'spec_helper'
|
||
|
|
||
|
require 'rex/ole'
|
||
|
|
||
|
describe Rex::OLE::DirEntry do
|
||
|
|
||
|
let(:storage) do
|
||
|
Rex::OLE::Storage.new
|
||
|
end
|
||
|
|
||
|
subject(:dir_entry) do
|
||
|
described_class.new(storage)
|
||
|
end
|
||
|
|
||
|
describe ".new" do
|
||
|
it "returns a Rex::OLE::DirEntry instance" do
|
||
|
expect(described_class.new(storage)).to be_a(Rex::OLE::DirEntry)
|
||
|
end
|
||
|
|
||
|
it { expect(dir_entry.instance_variable_get(:@stg)).to eq(storage) }
|
||
|
it { expect(dir_entry.sid).to eq(0) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_ab)).to eq('Root Entry') }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_cb)).to be_nil }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_mse)).to eq(Rex::OLE::STGTY_ROOT) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_bflags)).to eq(0) }
|
||
|
it { expect(dir_entry._sidLeftSib).to eq(Rex::OLE::SECT_FREE) }
|
||
|
it { expect(dir_entry._sidRightSib).to eq(Rex::OLE::SECT_FREE) }
|
||
|
it { expect(dir_entry._sidChild).to eq(Rex::OLE::SECT_FREE) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_clsId)).to be_a(Rex::OLE::CLSID) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_dwUserFlags)).to eq(0) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_ctime)).to eq("\x00" * 8) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_mtime)).to eq("\x00" * 8) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@_ulSize)).to eq(0) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@children)).to be_an(Array) }
|
||
|
it { expect(dir_entry.instance_variable_get(:@children)).to be_empty }
|
||
|
end
|
||
|
|
||
|
describe "#length" do
|
||
|
it "returns _ulSize" do
|
||
|
dir_entry.instance_variable_set(:@_ulSize, 28)
|
||
|
expect(dir_entry.length).to eq(28)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#<<" do
|
||
|
it "increments the children array" do
|
||
|
dir_entry << 1
|
||
|
children = dir_entry.instance_variable_get(:@children)
|
||
|
expect(children.length).to eq(1)
|
||
|
end
|
||
|
|
||
|
it "appends to the children array" do
|
||
|
dir_entry << 1
|
||
|
children = dir_entry.instance_variable_get(:@children)
|
||
|
expect(children).to eq([1])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#each" do
|
||
|
it "calls the block for every children element" do
|
||
|
dir_entry << 1
|
||
|
dir_entry << 2
|
||
|
dir_entry << 3
|
||
|
res = 0
|
||
|
dir_entry.each { |elem| res += elem}
|
||
|
expect(res).to eq(1 + 2 + 3)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#type" do
|
||
|
it "returns the _mse field" do
|
||
|
expect(dir_entry.type).to eq(Rex::OLE::STGTY_ROOT)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#type=" do
|
||
|
it "modifies the _mse field" do
|
||
|
dir_entry.type = 3838
|
||
|
expect(dir_entry.instance_variable_get(:@_mse)).to eq(3838)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#name" do
|
||
|
it "returns the _ab field" do
|
||
|
expect(dir_entry.name).to eq('Root Entry')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#name=" do
|
||
|
it "modifies the _ab field" do
|
||
|
dir_entry.name = 'test'
|
||
|
expect(dir_entry.instance_variable_get(:@_ab)).to eq('test')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#start_sector" do
|
||
|
it "returns the _sectStart field" do
|
||
|
expect(dir_entry.start_sector).to eq(Rex::OLE::SECT_END)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#start_sector=" do
|
||
|
it "modifies the _sectStart field" do
|
||
|
dir_entry.start_sector = Rex::OLE::SECT_FREE
|
||
|
expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#find_stream_by_name_and_type" do
|
||
|
context "when any children matches the search criteria" do
|
||
|
it "returns nil" do
|
||
|
expect(dir_entry.find_stream_by_name_and_type('name', Rex::OLE::STGTY_ROOT)).to be_nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when one children matches the search criteria" do
|
||
|
let(:stream) { Rex::OLE::Stream.new(storage) }
|
||
|
let(:name) { 'name' }
|
||
|
let(:type) { Rex::OLE::STGTY_ROOT }
|
||
|
it "returns the matching stream" do
|
||
|
stream.name = name
|
||
|
stream.type = type
|
||
|
dir_entry << stream
|
||
|
expect(dir_entry.find_stream_by_name_and_type(name, type)).to eq(stream)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when several children matches the search criteria" do
|
||
|
let(:stream) { Rex::OLE::Stream.new(storage) }
|
||
|
let(:stream_two) { Rex::OLE::Stream.new(storage) }
|
||
|
let(:name) { 'name' }
|
||
|
let(:type) { Rex::OLE::STGTY_ROOT }
|
||
|
let(:sid) { 2 }
|
||
|
it "returns the first matching stream" do
|
||
|
stream.name = name
|
||
|
stream.type = type
|
||
|
dir_entry << stream
|
||
|
|
||
|
stream_two.name = name
|
||
|
stream_two.type = type
|
||
|
stream_two.sid = sid
|
||
|
dir_entry << stream_two
|
||
|
expect(dir_entry.find_stream_by_name_and_type(name, type)).to eq(stream)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#find_by_sid" do
|
||
|
let(:stream) { Rex::OLE::Stream.new(storage) }
|
||
|
let(:another_stream) { Rex::OLE::Stream.new(storage) }
|
||
|
|
||
|
context "when self match the criteria" do
|
||
|
it "returns self" do
|
||
|
expect(dir_entry.find_by_sid(0, dir_entry)).to eq(dir_entry)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when self and a children stream match the criteria" do
|
||
|
it "returns self" do
|
||
|
stream.sid = 0
|
||
|
dir_entry << stream
|
||
|
expect(dir_entry.find_by_sid(0, dir_entry)).to eq(dir_entry)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when only one children stream match the criteria" do
|
||
|
it "returns the child stream" do
|
||
|
stream.sid = 20
|
||
|
dir_entry << stream
|
||
|
expect(dir_entry.find_by_sid(20, dir_entry)).to eq(stream)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when several children stream match the criteria" do
|
||
|
it "returns the first child" do
|
||
|
stream.sid = 20
|
||
|
stream.name = 'stream'
|
||
|
dir_entry << stream
|
||
|
another_stream.sid = 20
|
||
|
another_stream.name = 'another'
|
||
|
dir_entry << another_stream
|
||
|
expect(dir_entry.find_by_sid(20, dir_entry)).to eq(stream)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#pack" do
|
||
|
it "returns an string" do
|
||
|
expect(dir_entry.pack).to be_an(String)
|
||
|
end
|
||
|
|
||
|
it "includes the unicode dir entry name" do
|
||
|
expect(dir_entry.pack).to match(/R\x00o\x00o\x00t\x00 \x00E\x00n\x00t\x00r\x00y\x00/)
|
||
|
end
|
||
|
|
||
|
context "when _sectStart is undefined" do
|
||
|
it "sets _sectStart to SECT_END" do
|
||
|
dir_entry.instance_variable_set(:@_sectStart, nil)
|
||
|
dir_entry.pack
|
||
|
expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when _sectStart is defined" do
|
||
|
it "doesn't modify _sectStart value" do
|
||
|
dir_entry.instance_variable_set(:@_sectStart, Rex::OLE::SECT_FREE)
|
||
|
dir_entry.pack
|
||
|
expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "sets _cb as the unicode length of the name" do
|
||
|
dir_entry.pack
|
||
|
expect(dir_entry.instance_variable_get(:@_cb)).to eq("Root Entry\x00".length * 2)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "#to_s" do
|
||
|
it "returns an string" do
|
||
|
expect(dir_entry.to_s).to be_an(String)
|
||
|
end
|
||
|
|
||
|
it "starts with {" do
|
||
|
expect(dir_entry.to_s).to start_with('{')
|
||
|
end
|
||
|
|
||
|
it "ends with }" do
|
||
|
expect(dir_entry.to_s).to end_with('}')
|
||
|
end
|
||
|
|
||
|
it "contains the entry name" do
|
||
|
expect(dir_entry.to_s).to match(/Root Entry/)
|
||
|
end
|
||
|
|
||
|
context "when _sectStart is undefined" do
|
||
|
it "sets _sectStart to SECT_END" do
|
||
|
dir_entry.instance_variable_set(:@_sectStart, nil)
|
||
|
dir_entry.to_s
|
||
|
expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when _sectStart is defined" do
|
||
|
it "doesn't modify _sectStart value" do
|
||
|
dir_entry.instance_variable_set(:@_sectStart, Rex::OLE::SECT_FREE)
|
||
|
dir_entry.to_s
|
||
|
expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "sets _cb as the unicode length of the name" do
|
||
|
dir_entry.to_s
|
||
|
expect(dir_entry.instance_variable_get(:@_cb)).to eq("Root Entry\x00".length * 2)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|