Skip to content

Commit 526251f

Browse files
committed
Add specs for Rex::OLE::Header
1 parent 5e0993d commit 526251f

File tree

1 file changed

+352
-0
lines changed

1 file changed

+352
-0
lines changed

spec/lib/rex/ole/header_spec.rb

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
# -*- coding:binary -*-
2+
require 'spec_helper'
3+
4+
require 'rex/ole'
5+
6+
describe Rex::OLE::Header do
7+
8+
subject(:header) do
9+
described_class.new
10+
end
11+
12+
describe ".new" do
13+
it "returns a Rex::OLE::Header instance" do
14+
expect(described_class.new).to be_a(Rex::OLE::Header)
15+
end
16+
17+
it { expect(header.instance_variable_get(:@_abSig)).to eq(Rex::OLE::SIG) }
18+
it { expect(header.instance_variable_get(:@_clid)).to be_a(Rex::OLE::CLSID) }
19+
it { expect(header.instance_variable_get(:@_uByteOrder)).to eq(Rex::OLE::LITTLE_ENDIAN) }
20+
it { expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x3e) }
21+
it { expect(header._uMajorVersion).to eq(0x03) }
22+
it { expect(header.instance_variable_get(:@_uSectorShift)).to eq(9) }
23+
it { expect(header._uMiniSectorShift).to eq(6) }
24+
it { expect(header.instance_variable_get(:@_csectDir)).to be_nil }
25+
it { expect(header._csectFat).to be_nil }
26+
it { expect(header._sectDirStart).to be_nil }
27+
it { expect(header.instance_variable_get(:@_signature)).to eq(0) }
28+
it { expect(header._ulMiniSectorCutoff).to eq(0x1000) }
29+
it { expect(header._sectMiniFatStart).to eq(Rex::OLE::SECT_END) }
30+
it { expect(header._csectMiniFat).to eq(0) }
31+
it { expect(header._sectDifStart).to eq(Rex::OLE::SECT_END) }
32+
it { expect(header._csectDif).to eq(0) }
33+
it { expect(header._sectFat).to be_an(Array) }
34+
it { expect(header.instance_variable_get(:@_sectFat)).to be_empty }
35+
it { expect(header.sector_size).to eq(1 << 9) }
36+
it { expect(header.mini_sector_size).to eq(1 << 6) }
37+
it { expect(header.idx_per_sect).to eq((1 << 9) / 4) }
38+
end
39+
40+
describe "#set_defaults" do
41+
it "sets OLECF signature" do
42+
header.set_defaults
43+
expect(header.instance_variable_get(:@_abSig)).to eq(Rex::OLE::SIG)
44+
end
45+
46+
it "setup a class identifier (guid)" do
47+
header.set_defaults
48+
expect(header.instance_variable_get(:@_clid)).to be_a(Rex::OLE::CLSID)
49+
end
50+
51+
it "sets byte order identifier as little endian" do
52+
header.set_defaults
53+
expect(header.instance_variable_get(:@_uByteOrder)).to eq(Rex::OLE::LITTLE_ENDIAN)
54+
end
55+
56+
it "sets the minor version to 0x3e" do
57+
header.set_defaults
58+
expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x3e)
59+
end
60+
61+
it "sets the major version to 0x3" do
62+
header.set_defaults
63+
expect(header._uMajorVersion).to eq(0x03)
64+
end
65+
66+
it "sets the size of sectors to 9" do
67+
header.set_defaults
68+
expect(header.instance_variable_get(:@_uSectorShift)).to eq(9)
69+
end
70+
71+
it "sets the size of mini-sectors to 6" do
72+
header.set_defaults
73+
expect(header._uMiniSectorShift).to eq(6)
74+
end
75+
76+
it "sets the number of sectors in the directory chain to nil" do
77+
header.set_defaults
78+
expect(header.instance_variable_get(:@_csectDir)).to be_nil
79+
end
80+
81+
it "sets the number of sectors in the FAT chain to nil" do
82+
header.set_defaults
83+
expect(header._csectFat).to be_nil
84+
end
85+
86+
it "sets first sector in the directory chain to nil" do
87+
header.set_defaults
88+
expect(header._sectDirStart).to be_nil
89+
end
90+
91+
it "sets the signature used for transactioning to zero" do
92+
header.set_defaults
93+
expect(header.instance_variable_get(:@_signature)).to eq(0)
94+
end
95+
96+
it "sets the maximum size of mini-streams to 4096" do
97+
header.set_defaults
98+
expect(header._ulMiniSectorCutoff).to eq(0x1000)
99+
end
100+
101+
it "sets the first sector in the mini-FAT chain to end of chain" do
102+
header.set_defaults
103+
expect(header._sectMiniFatStart).to eq(Rex::OLE::SECT_END)
104+
end
105+
106+
it "sets the number of sectors in the mini-FAT chain to 0" do
107+
header.set_defaults
108+
expect(header._csectMiniFat).to eq(0)
109+
end
110+
111+
it "sets the first sector in the DIF chain to end of chain" do
112+
header.set_defaults
113+
expect(header._sectDifStart).to eq(Rex::OLE::SECT_END)
114+
end
115+
116+
it "sets the number of sectors in the DIF chain to 0" do
117+
header.set_defaults
118+
expect(header._csectDif).to eq(0)
119+
end
120+
121+
it "creates an array for the sectors of the first 109 FAT sectors" do
122+
header.set_defaults
123+
expect(header._sectFat).to be_an(Array)
124+
end
125+
126+
it "creates an empty array for the FAT sectors" do
127+
header.set_defaults
128+
expect(header.instance_variable_get(:@_sectFat)).to be_empty
129+
end
130+
end
131+
132+
describe "#to_s" do
133+
subject(:header_string) { header.to_s }
134+
135+
it "returns an String" do
136+
expect(header_string).to be_an(String)
137+
end
138+
139+
it "starts with {" do
140+
expect(header_string).to start_with('{')
141+
end
142+
143+
it "ends with {" do
144+
expect(header_string).to end_with('}')
145+
end
146+
147+
it "includes the OLECF signature" do
148+
expect(header_string).to match(/_abSig => "\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1"/)
149+
end
150+
151+
it "includes the class identifier value" do
152+
expect(header_string).to match(/_clid => 00000000-0000-0000-0000-000000000000/)
153+
end
154+
155+
it "includes the minor version value" do
156+
expect(header_string).to match(/_uMinorVersion => 0x003e/)
157+
end
158+
159+
it "includes the major version value" do
160+
expect(header_string).to match(/_uMajorVersion => 0x0003/)
161+
end
162+
163+
it "includes the byte order identifier value" do
164+
expect(header_string).to match(/_uByteOrder => 0xfffe/)
165+
end
166+
167+
it "includes the size of sectors value" do
168+
expect(header_string).to match(/_uSectorShift => 0x0009/)
169+
end
170+
171+
it "includes the size of mini-sectors value" do
172+
expect(header_string).to match(/_uMiniSectorShift => 0x0006/)
173+
end
174+
175+
it "includes the number of sectors in the directory chain" do
176+
expect(header_string).to match(/_csectDir => UNALLOCATED/)
177+
end
178+
179+
it "includes the number of sectors in the FAT chain" do
180+
expect(header_string).to match(/_csectFat => UNALLOCATED/)
181+
end
182+
183+
it "includes the first sector in the directory chain" do
184+
expect(header_string).to match(/_sectDirStart => UNALLOCATED/)
185+
end
186+
187+
it "includes the signature used for transactioning" do
188+
expect(header_string).to match(/_signature => 0x00000000/)
189+
end
190+
191+
it "includes the maximum size of mini-streams" do
192+
expect(header_string).to match(/_uMiniSectorCutoff => 0x00001000/)
193+
end
194+
195+
it "includes the first sector in the mini-FAT chain value" do
196+
expect(header_string).to match(/_sectMiniFatStart => 0xfffffffe/)
197+
end
198+
199+
it "includes the number of sectors in the mini-FAT chain" do
200+
expect(header_string).to match(/_csectMiniFat => 0x00000000/)
201+
end
202+
203+
it "includes the first sector in the DIF chain value" do
204+
expect(header_string).to match(/_sectDifStart => 0xfffffffe/)
205+
end
206+
207+
it "includes the number of sectors in the DIF chain" do
208+
expect(header_string).to match(/_csectDif => 0x00000000/)
209+
end
210+
end
211+
212+
describe "#read" do
213+
context "when reading empty header" do
214+
let(:empty_fd) do
215+
s = ''
216+
StringIO.new(s, 'rb')
217+
end
218+
219+
it "raises NoMethodError" do
220+
expect { header.read(empty_fd) }.to raise_error(NoMethodError)
221+
end
222+
end
223+
224+
225+
context "when reading header with invalid signature" do
226+
let(:incorrect_fd) do
227+
s = 'A' * Rex::OLE::HDR_SZ
228+
StringIO.new(s, 'rb')
229+
end
230+
231+
it "raises RuntimeError" do
232+
expect { header.read(incorrect_fd) }.to raise_error(RuntimeError)
233+
end
234+
end
235+
236+
context "when reading header with valid signature" do
237+
let(:correct_fd) do
238+
hdr = ""
239+
hdr << Rex::OLE::SIG
240+
hdr << 'A' * 16 # @_clid
241+
hdr << 'BB' # @_uMinorVersion
242+
hdr << 'CC' # @_uMajorVersion
243+
hdr << 'DD' # @_uByteOrder
244+
hdr << 'EE' # @_uSectorShift
245+
hdr << 'FF' # @_uMiniSectorShift
246+
hdr << '123456' # padding
247+
hdr << 'GGGG' # @_csectDir
248+
hdr << 'HHHH' # @_csectFat
249+
hdr << 'IIII' # @_sectDirStart
250+
hdr << 'JJJJ' # @_signature
251+
hdr << 'KKKK' # @_ulMiniSectorCutoff
252+
hdr << 'LLLL' # @_sectMiniFatStart
253+
hdr << 'MMMM' # @_csectMiniFat
254+
hdr << 'NNNN' # @_sectDifStart
255+
hdr << 'OOOO' # @_csectDif
256+
hdr << 'P' * 109 * 4 # @_sectFat
257+
258+
StringIO.new(hdr, 'rb')
259+
end
260+
261+
it "sets clsid from input" do
262+
header.read(correct_fd)
263+
expect(header.instance_variable_get(:@_clid).to_s).to eq("41414141-4141-4141-4141-414141414141")
264+
end
265+
266+
it "sets minor version from input" do
267+
header.read(correct_fd)
268+
expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x4242)
269+
end
270+
271+
it "sets major version from input" do
272+
header.read(correct_fd)
273+
expect(header._uMajorVersion).to eq(0x4343)
274+
end
275+
276+
it "sets byte order from input" do
277+
header.read(correct_fd)
278+
expect(header.instance_variable_get(:@_uByteOrder)).to eq(0x4444)
279+
end
280+
281+
it "sets the size of sectors from input" do
282+
header.read(correct_fd)
283+
expect(header.instance_variable_get(:@_uSectorShift)).to eq(0x4545)
284+
end
285+
286+
it "sets the size of mini-sectors from input" do
287+
header.read(correct_fd)
288+
expect(header._uMiniSectorShift).to eq(0x4646)
289+
end
290+
291+
it "sets the number of sectors in the directory chain from input" do
292+
header.read(correct_fd)
293+
expect(header.instance_variable_get(:@_csectDir)).to eq(0x47474747)
294+
end
295+
296+
it "sets the number of sectors in the FAT chain from input" do
297+
header.read(correct_fd)
298+
expect(header._csectFat).to eq(0x48484848)
299+
end
300+
301+
it "sets the first sector in the directory chain from input" do
302+
header.read(correct_fd)
303+
expect(header._sectDirStart).to eq(0x49494949)
304+
end
305+
306+
it "sets the signature used for transactioning from input" do
307+
header.read(correct_fd)
308+
expect(header.instance_variable_get(:@_signature)).to eq(0x4a4a4a4a)
309+
end
310+
311+
it "sets the maximum size of mini-streams from input" do
312+
header.read(correct_fd)
313+
expect(header._ulMiniSectorCutoff).to eq(0x4b4b4b4b)
314+
end
315+
316+
it "sets the first sector in the mini-FAT chain from input" do
317+
header.read(correct_fd)
318+
expect(header._sectMiniFatStart).to eq(0x4c4c4c4c)
319+
end
320+
321+
it "sets the number of sectors in the mini-FAT chain from input" do
322+
header.read(correct_fd)
323+
expect(header._csectMiniFat).to eq(0x4d4d4d4d)
324+
end
325+
326+
it "sets the first sector in the DIF chain from input" do
327+
header.read(correct_fd)
328+
expect(header._sectDifStart).to eq(0x4e4e4e4e)
329+
end
330+
331+
it "sets the number of sectors in the DIF chain from input" do
332+
header.read(correct_fd)
333+
expect(header._csectDif).to eq(0x4f4f4f4f)
334+
end
335+
336+
it "creates an array for the FAT sectors from input" do
337+
header.read(correct_fd)
338+
expect(header._sectFat.length).to eq(109)
339+
end
340+
end
341+
end
342+
343+
describe "#write" do
344+
context "when default header" do
345+
it "writes 76 bytes" do
346+
fd = StringIO.new('', 'wb')
347+
header.write(fd)
348+
expect(fd.string.length).to eq(76)
349+
end
350+
end
351+
end
352+
end

0 commit comments

Comments
 (0)