rex-ole 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +52 -0
- data/Gemfile +6 -0
- data/LICENSE +27 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rex/ole/clsid.rb +44 -0
- data/lib/rex/ole/difat.rb +138 -0
- data/lib/rex/ole/directory.rb +228 -0
- data/lib/rex/ole/direntry.rb +237 -0
- data/lib/rex/ole/docs/dependencies.txt +8 -0
- data/lib/rex/ole/docs/references.txt +1 -0
- data/lib/rex/ole/fat.rb +96 -0
- data/lib/rex/ole/header.rb +201 -0
- data/lib/rex/ole/minifat.rb +74 -0
- data/lib/rex/ole/propset.rb +141 -0
- data/lib/rex/ole/samples/create_ole.rb +27 -0
- data/lib/rex/ole/samples/dir.rb +35 -0
- data/lib/rex/ole/samples/dump_stream.rb +34 -0
- data/lib/rex/ole/samples/ole_info.rb +23 -0
- data/lib/rex/ole/storage.rb +392 -0
- data/lib/rex/ole/stream.rb +50 -0
- data/lib/rex/ole/substorage.rb +46 -0
- data/lib/rex/ole/util.rb +154 -0
- data/lib/rex/ole/version.rb +5 -0
- data/lib/rex/ole.rb +203 -0
- data/rex-ole.gemspec +26 -0
- data.tar.gz.sig +2 -0
- metadata +208 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# Rex::OLE - an OLE implementation
|
5
|
+
# written in 2010 by Joshua J. Drake <jduck [at] metasploit.com>
|
6
|
+
##
|
7
|
+
|
8
|
+
module Rex
|
9
|
+
module OLE
|
10
|
+
|
11
|
+
#
|
12
|
+
# This class serves as the base class for SubStorage, Stream, and Directory head
|
13
|
+
#
|
14
|
+
class DirEntry
|
15
|
+
|
16
|
+
attr_accessor :sid
|
17
|
+
attr_accessor :_sidChild, :_sidLeftSib, :_sidRightSib
|
18
|
+
|
19
|
+
def initialize(stg)
|
20
|
+
@stg = stg
|
21
|
+
|
22
|
+
# default to a root entry :)
|
23
|
+
@sid = 0
|
24
|
+
@_ab = "Root Entry"
|
25
|
+
@_cb = nil # NOTE: this is not used until pack
|
26
|
+
@_mse = STGTY_ROOT
|
27
|
+
@_bflags = 0
|
28
|
+
@_sidLeftSib = SECT_FREE
|
29
|
+
@_sidRightSib = SECT_FREE
|
30
|
+
@_sidChild = SECT_FREE
|
31
|
+
@_clsId = CLSID.new
|
32
|
+
@_dwUserFlags = 0
|
33
|
+
@_ctime = "\x00" * 8
|
34
|
+
@_mtime = "\x00" * 8
|
35
|
+
@_sectStart = SECT_END
|
36
|
+
@_ulSize = 0
|
37
|
+
|
38
|
+
# keep track of logical children (in a tree)
|
39
|
+
@children = []
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def length
|
44
|
+
@_ulSize
|
45
|
+
end
|
46
|
+
|
47
|
+
def <<(expr)
|
48
|
+
@children << expr
|
49
|
+
end
|
50
|
+
|
51
|
+
def each
|
52
|
+
@children.each { |de|
|
53
|
+
yield de
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def type
|
59
|
+
@_mse
|
60
|
+
end
|
61
|
+
def type=(arg)
|
62
|
+
@_mse = arg
|
63
|
+
end
|
64
|
+
|
65
|
+
def name
|
66
|
+
@_ab
|
67
|
+
end
|
68
|
+
def name=(arg)
|
69
|
+
# XXX: validate?
|
70
|
+
@_ab = arg
|
71
|
+
end
|
72
|
+
|
73
|
+
def start_sector
|
74
|
+
@_sectStart
|
75
|
+
end
|
76
|
+
def start_sector=(expr)
|
77
|
+
@_sectStart = expr
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# NOTE: this will not look at children
|
82
|
+
def find_stream_by_name_and_type(name, type)
|
83
|
+
@children.each { |de|
|
84
|
+
next if (de.type != type)
|
85
|
+
|
86
|
+
if (de.name == name)
|
87
|
+
return de
|
88
|
+
end
|
89
|
+
}
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def find_by_sid(sid, de=self)
|
95
|
+
if (de.sid == sid)
|
96
|
+
return de
|
97
|
+
end
|
98
|
+
@children.each { |cde|
|
99
|
+
ret = find_by_sid(sid, cde)
|
100
|
+
if (ret)
|
101
|
+
return ret
|
102
|
+
end
|
103
|
+
}
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
#
|
109
|
+
# low-level functions
|
110
|
+
#
|
111
|
+
def from_s(sid, buf)
|
112
|
+
@sid = sid
|
113
|
+
@_ab = Util.getUnicodeString(buf[0x00,64])
|
114
|
+
@_cb = Util.get16(buf, 0x40)
|
115
|
+
|
116
|
+
# too big?
|
117
|
+
if (@_cb > 0x40)
|
118
|
+
raise RuntimeError, 'Invalid directory entry name length %#x' % @_cb
|
119
|
+
end
|
120
|
+
|
121
|
+
# mismatch?
|
122
|
+
if (@_ab.length > 0)
|
123
|
+
declen = ((@_cb) / 2) - 1
|
124
|
+
if (declen != @_ab.length)
|
125
|
+
raise RuntimeError, 'Directory entry name and length mismatch (%d != %d)' % [declen, @_ab.length]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
@_mse = Util.get8(buf, 0x42)
|
130
|
+
@_bflags = Util.get8(buf, 0x43)
|
131
|
+
@_sidLeftSib = Util.get32(buf, 0x44)
|
132
|
+
@_sidRightSib = Util.get32(buf, 0x48)
|
133
|
+
@_sidChild = Util.get32(buf, 0x4c)
|
134
|
+
|
135
|
+
# only used for storages..
|
136
|
+
@_clsId = CLSID.new(buf[0x50,16])
|
137
|
+
@_dwUserFlags = Util.get32(buf, 0x60)
|
138
|
+
@_ctime = buf[0x64,8]
|
139
|
+
@_mtime = buf[0x6c,8]
|
140
|
+
|
141
|
+
# only used for streams...
|
142
|
+
@_sectStart = Util.get32(buf, 0x74)
|
143
|
+
if (@stg.header._uMajorVersion == 4)
|
144
|
+
@_ulSize = Util.get64(buf, 0x78)
|
145
|
+
else
|
146
|
+
@_ulSize = Util.get32(buf, 0x78)
|
147
|
+
end
|
148
|
+
|
149
|
+
# ignore _dptPropType and pad
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def pack
|
154
|
+
@_sectStart ||= SECT_END
|
155
|
+
@_cb = (@_ab.length + 1) * 2
|
156
|
+
|
157
|
+
data = ""
|
158
|
+
data << Util.putUnicodeString(@_ab) # gets padded/truncated to 0x40 bytes
|
159
|
+
data << Util.pack16(@_cb)
|
160
|
+
data << Util.pack8(@_mse)
|
161
|
+
data << Util.pack8(@_bflags)
|
162
|
+
data << Util.pack32(@_sidLeftSib)
|
163
|
+
data << Util.pack32(@_sidRightSib)
|
164
|
+
data << Util.pack32(@_sidChild)
|
165
|
+
data << @_clsId.pack
|
166
|
+
data << Util.pack32(@_dwUserFlags)
|
167
|
+
data << @_ctime
|
168
|
+
data << @_mtime
|
169
|
+
data << Util.pack32(@_sectStart)
|
170
|
+
data << Util.pack64(@_ulSize)
|
171
|
+
data
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
def to_s(extra_spaces=0)
|
176
|
+
@_sectStart ||= SECT_END
|
177
|
+
@_cb = (@_ab.length + 1) * 2
|
178
|
+
|
179
|
+
spstr = " " * extra_spaces
|
180
|
+
|
181
|
+
ret = "%s{\n" % spstr
|
182
|
+
ret << "%s sid => 0x%x" % [spstr, @sid]
|
183
|
+
ret << ",\n"
|
184
|
+
ret << "%s _ab => \"%s\"" % [spstr, Util.Printable(@_ab)]
|
185
|
+
ret << ",\n"
|
186
|
+
ret << "%s _cb => 0x%04x" % [spstr, @_cb]
|
187
|
+
ret << ",\n"
|
188
|
+
ret << "%s _mse => 0x%02x" % [spstr, @_mse]
|
189
|
+
ret << ",\n"
|
190
|
+
ret << "%s _bflags => 0x%02x" % [spstr, @_bflags]
|
191
|
+
ret << ",\n"
|
192
|
+
ret << "%s _sidLeftSib => 0x%08x" % [spstr, @_sidLeftSib]
|
193
|
+
ret << ",\n"
|
194
|
+
ret << "%s _sidRightSib => 0x%08x" % [spstr, @_sidRightSib]
|
195
|
+
ret << ",\n"
|
196
|
+
ret << "%s _sidChild => 0x%08x" % [spstr, @_sidChild]
|
197
|
+
ret << ",\n"
|
198
|
+
ret << "%s _clsId => %s" % [spstr, @_clsId.to_s]
|
199
|
+
ret << ",\n"
|
200
|
+
ret << "%s _dwUserFlags => 0x%08x" % [spstr, @_dwUserFlags]
|
201
|
+
ret << ",\n"
|
202
|
+
ret << "%s _ctime => %s" % [spstr, Rex::Text.to_hex_dump(@_ctime).strip]
|
203
|
+
ret << "\n"
|
204
|
+
ret << "%s _mtime => %s" % [spstr, Rex::Text.to_hex_dump(@_mtime).strip]
|
205
|
+
ret << "\n"
|
206
|
+
ret << "%s _sectStart => 0x%08x" % [spstr, @_sectStart]
|
207
|
+
ret << ",\n"
|
208
|
+
ret << "%s _ulSize => 0x%016x" % [spstr, @_ulSize]
|
209
|
+
if (@_mse == STGTY_STREAM)
|
210
|
+
ret << ",\n"
|
211
|
+
ret << "%s data =>\n" % spstr
|
212
|
+
if (@data)
|
213
|
+
#ret << Util.Printable(@data)
|
214
|
+
ret << Rex::Text.to_hex_dump(@data).strip
|
215
|
+
else
|
216
|
+
if (@_ulSize > 0)
|
217
|
+
ret << "--NOT OPENED YET--"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
elsif (@_mse == STGTY_STORAGE) or (@_mse == STGTY_ROOT)
|
221
|
+
if (@children.length > 0)
|
222
|
+
ret << ",\n"
|
223
|
+
ret << "%s *children* =>\n" % spstr
|
224
|
+
@children.each { |de|
|
225
|
+
ret << de.to_s(extra_spaces+2)
|
226
|
+
ret << "\n"
|
227
|
+
}
|
228
|
+
end
|
229
|
+
end
|
230
|
+
ret << "\n"
|
231
|
+
ret << "%s}" % spstr
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
[MS-CFB].pdf
|
data/lib/rex/ole/fat.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# Rex::OLE - an OLE implementation
|
5
|
+
# written in 2010 by Joshua J. Drake <jduck [at] metasploit.com>
|
6
|
+
##
|
7
|
+
|
8
|
+
module Rex
|
9
|
+
module OLE
|
10
|
+
|
11
|
+
class FAT < DIFAT
|
12
|
+
|
13
|
+
#
|
14
|
+
# low-level functions
|
15
|
+
#
|
16
|
+
def read(difat)
|
17
|
+
@entries = []
|
18
|
+
cnt = left = @stg.header._csectFat
|
19
|
+
difat.each { |fs|
|
20
|
+
break if (left == 0)
|
21
|
+
|
22
|
+
if (fs != SECT_FREE)
|
23
|
+
buf = @stg.read_sector(fs, @stg.header.sector_size)
|
24
|
+
arr = Util.get32array(buf)
|
25
|
+
|
26
|
+
# hax!
|
27
|
+
if (@entries[fs] == SECT_DIF)
|
28
|
+
# chop the next ptr
|
29
|
+
@entries += arr.slice!(0, arr.length - 1)
|
30
|
+
else
|
31
|
+
@entries += arr
|
32
|
+
end
|
33
|
+
left -= 1
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
if (left != 0)
|
38
|
+
raise RuntimeError, 'Only found %u of %u sectors' % [(cnt - left), cnt]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def allocate_sector(type=nil)
|
43
|
+
idx = @entries.index(SECT_FREE)
|
44
|
+
if (not idx)
|
45
|
+
# add a sector worth
|
46
|
+
idx = @entries.length
|
47
|
+
@stg.header.idx_per_sect.times {
|
48
|
+
@entries << SECT_FREE
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# mark the sector as in use
|
53
|
+
if (type)
|
54
|
+
@entries[idx] = type
|
55
|
+
else
|
56
|
+
# default normal sectors to end of chain
|
57
|
+
@entries[idx] = SECT_END
|
58
|
+
end
|
59
|
+
idx
|
60
|
+
end
|
61
|
+
|
62
|
+
def write(difat)
|
63
|
+
# we build the difat as we write these..
|
64
|
+
difat.reset
|
65
|
+
|
66
|
+
# allocate the sectors
|
67
|
+
fat_sects = []
|
68
|
+
left = @entries.length
|
69
|
+
while (left > 0)
|
70
|
+
if (left > @stg.header.idx_per_sect)
|
71
|
+
left -= @stg.header.idx_per_sect
|
72
|
+
else
|
73
|
+
left = 0
|
74
|
+
end
|
75
|
+
fat_sects << allocate_sector(SECT_FAT)
|
76
|
+
end
|
77
|
+
|
78
|
+
# write the fat into the difat/allocated sectors
|
79
|
+
copy = @entries.dup
|
80
|
+
fat_sects.each { |fs|
|
81
|
+
part = copy.slice!(0, @stg.header.idx_per_sect)
|
82
|
+
sbuf = Util.pack32array(part)
|
83
|
+
|
84
|
+
if (sbuf.length != @stg.header.sector_size)
|
85
|
+
raise RuntimeError, 'Unsupported number of fat sectors (not multiple of idx per sect)'
|
86
|
+
end
|
87
|
+
|
88
|
+
@stg.write_sector_raw(fs, sbuf)
|
89
|
+
difat << fs
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# Rex::OLE - an OLE implementation
|
5
|
+
# written in 2010 by Joshua J. Drake <jduck [at] metasploit.com>
|
6
|
+
##
|
7
|
+
|
8
|
+
#
|
9
|
+
# Should we support major == 4 && sectorshift == 0xc ?
|
10
|
+
#
|
11
|
+
|
12
|
+
module Rex
|
13
|
+
module OLE
|
14
|
+
|
15
|
+
require 'rex/ole/util'
|
16
|
+
|
17
|
+
class Header
|
18
|
+
|
19
|
+
attr_accessor :_csectFat, :_sectFat
|
20
|
+
attr_accessor :_csectMiniFat, :_sectMiniFatStart
|
21
|
+
attr_accessor :_ulMiniSectorCutoff, :_uMiniSectorShift
|
22
|
+
attr_accessor :_csectDif, :_sectDifStart
|
23
|
+
attr_accessor :_sectDirStart
|
24
|
+
attr_accessor :_uMajorVersion
|
25
|
+
|
26
|
+
attr_accessor :sector_size, :idx_per_sect
|
27
|
+
attr_accessor :mini_sector_size
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
set_defaults
|
31
|
+
|
32
|
+
# calculate some numbers (save a little math)
|
33
|
+
@sector_size = 1 << @_uSectorShift
|
34
|
+
@mini_sector_size = 1 << @_uMiniSectorShift
|
35
|
+
@idx_per_sect = @sector_size / 4
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_defaults
|
39
|
+
@_abSig = SIG
|
40
|
+
@_clid = CLSID.new
|
41
|
+
@_uByteOrder = LITTLE_ENDIAN
|
42
|
+
|
43
|
+
@_uMinorVersion = 0x3e
|
44
|
+
@_uMajorVersion = 0x03
|
45
|
+
|
46
|
+
@_uSectorShift = 9 # 512 byte sectors
|
47
|
+
@_uMiniSectorShift = 6 # 64 byte mini-sectors
|
48
|
+
|
49
|
+
@_csectDir = nil # TBD (v4 only, 1 required)
|
50
|
+
|
51
|
+
@_csectFat = nil # TBD (one required)
|
52
|
+
@_sectDirStart = nil # TBD (one required)
|
53
|
+
|
54
|
+
@_signature = 0 # no transactions support
|
55
|
+
|
56
|
+
@_ulMiniSectorCutoff = 0x1000 # 4k
|
57
|
+
@_sectMiniFatStart = SECT_END # TBD
|
58
|
+
@_csectMiniFat = 0 # TBD
|
59
|
+
|
60
|
+
@_sectDifStart = SECT_END # TBD (default to none)
|
61
|
+
@_csectDif = 0 # TBD (default to none)
|
62
|
+
|
63
|
+
@_sectFat = [] # TBD
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
ret = "{\n"
|
68
|
+
ret << " _abSig => \"%s\"" % Util.Printable(@_abSig)
|
69
|
+
ret << ",\n"
|
70
|
+
ret << " _clid => %s" % @_clid.to_s
|
71
|
+
ret << ",\n"
|
72
|
+
ret << " _uMinorVersion => 0x%04x" % @_uMinorVersion
|
73
|
+
ret << ",\n"
|
74
|
+
ret << " _uMajorVersion => 0x%04x" % @_uMajorVersion
|
75
|
+
ret << ",\n"
|
76
|
+
ret << " _uByteOrder => 0x%04x" % @_uByteOrder
|
77
|
+
ret << ",\n"
|
78
|
+
ret << " _uSectorShift => 0x%04x" % @_uSectorShift
|
79
|
+
ret << ",\n"
|
80
|
+
ret << " _uMiniSectorShift => 0x%04x" % @_uMiniSectorShift
|
81
|
+
ret << ",\n"
|
82
|
+
|
83
|
+
if (@_csectDir)
|
84
|
+
ret << " _csectDir => 0x%08x" % @_csectDir
|
85
|
+
else
|
86
|
+
ret << " _csectDir => UNALLOCATED" % @_csectDir
|
87
|
+
end
|
88
|
+
ret << ",\n"
|
89
|
+
|
90
|
+
if (@_csectFat)
|
91
|
+
ret << " _csectFat => 0x%08x" % @_csectFat
|
92
|
+
else
|
93
|
+
ret << " _csectFat => UNALLOCATED"
|
94
|
+
end
|
95
|
+
ret << ",\n"
|
96
|
+
|
97
|
+
if (@_sectDirStart)
|
98
|
+
ret << " _sectDirStart => 0x%08x" % @_sectDirStart
|
99
|
+
else
|
100
|
+
ret << " _sectDirStart => UNALLOCATED"
|
101
|
+
end
|
102
|
+
ret << ",\n"
|
103
|
+
|
104
|
+
ret << " _signature => 0x%08x" % @_signature
|
105
|
+
ret << ",\n"
|
106
|
+
ret << " _uMiniSectorCutoff => 0x%08x" % @_ulMiniSectorCutoff
|
107
|
+
ret << ",\n"
|
108
|
+
ret << " _sectMiniFatStart => 0x%08x" % @_sectMiniFatStart
|
109
|
+
ret << ",\n"
|
110
|
+
ret << " _csectMiniFat => 0x%08x" % @_csectMiniFat
|
111
|
+
ret << ",\n"
|
112
|
+
ret << " _sectDifStart => 0x%08x" % @_sectDifStart
|
113
|
+
ret << ",\n"
|
114
|
+
ret << " _csectDif => 0x%08x" % @_csectDif
|
115
|
+
#ret << ",\n"
|
116
|
+
#ret << " _sectFat => "
|
117
|
+
#ret << Rex::Text.to_hex_dump32array(@_sectFat)
|
118
|
+
ret << "\n}"
|
119
|
+
ret
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# low-level functions
|
124
|
+
#
|
125
|
+
def read(fd)
|
126
|
+
buf = fd.read(HDR_SZ)
|
127
|
+
|
128
|
+
@_abSig = buf[0x00,8]
|
129
|
+
if (@_abSig != SIG) and (@_abSig != SIG_BETA)
|
130
|
+
raise RuntimeError, 'Invalid signature for OLE file'
|
131
|
+
end
|
132
|
+
@_clid = CLSID.new(buf[0x08,16])
|
133
|
+
|
134
|
+
@_uByteOrder = Util.get16(buf, 0x1c)
|
135
|
+
Util.set_endian(@_uByteOrder)
|
136
|
+
|
137
|
+
@_uMinorVersion = Util.get16(buf, 0x18)
|
138
|
+
@_uMajorVersion = Util.get16(buf, 0x1a)
|
139
|
+
|
140
|
+
@_uSectorShift = Util.get16(buf, 0x1e)
|
141
|
+
@_uMiniSectorShift = Util.get16(buf, 0x20)
|
142
|
+
|
143
|
+
# ignore reserved bytes
|
144
|
+
|
145
|
+
@_csectDir = Util.get32(buf, 0x28) # NOTE: only for v4 files
|
146
|
+
|
147
|
+
@_csectFat = Util.get32(buf, 0x2c)
|
148
|
+
@_sectDirStart = Util.get32(buf, 0x30)
|
149
|
+
|
150
|
+
@_signature = Util.get32(buf, 0x34)
|
151
|
+
|
152
|
+
@_ulMiniSectorCutoff = Util.get32(buf, 0x38)
|
153
|
+
@_sectMiniFatStart = Util.get32(buf, 0x3c)
|
154
|
+
@_csectMiniFat = Util.get32(buf, 0x40)
|
155
|
+
|
156
|
+
@_sectDifStart = Util.get32(buf, 0x44)
|
157
|
+
@_csectDif = Util.get32(buf, 0x48)
|
158
|
+
|
159
|
+
@_sectFat = Util.get32array(buf[0x4c, (109 * 4)])
|
160
|
+
end
|
161
|
+
|
162
|
+
def write(fd)
|
163
|
+
hdr = ""
|
164
|
+
hdr << @_abSig
|
165
|
+
hdr << @_clid.pack
|
166
|
+
hdr << Util.pack16(@_uMinorVersion)
|
167
|
+
hdr << Util.pack16(@_uMajorVersion)
|
168
|
+
hdr << Util.pack16(@_uByteOrder)
|
169
|
+
hdr << Util.pack16(@_uSectorShift)
|
170
|
+
hdr << Util.pack16(@_uMiniSectorShift)
|
171
|
+
if (@_uMajorVersion == 0x04)
|
172
|
+
hdr << "\x00" * 6 # reserved bytes
|
173
|
+
hdr << Util.pack32(@_csectDir)
|
174
|
+
else
|
175
|
+
hdr << "\x00" * 10 # reserved bytes
|
176
|
+
end
|
177
|
+
|
178
|
+
fs_count = @_csectFat
|
179
|
+
fs_count ||= 0
|
180
|
+
hdr << Util.pack32(fs_count)
|
181
|
+
|
182
|
+
dir_start = @_sectDirStart
|
183
|
+
dir_start ||= SECT_END
|
184
|
+
hdr << Util.pack32(dir_start)
|
185
|
+
|
186
|
+
hdr << Util.pack32(@_signature)
|
187
|
+
hdr << Util.pack32(@_ulMiniSectorCutoff)
|
188
|
+
hdr << Util.pack32(@_sectMiniFatStart)
|
189
|
+
hdr << Util.pack32(@_csectMiniFat)
|
190
|
+
hdr << Util.pack32(@_sectDifStart)
|
191
|
+
hdr << Util.pack32(@_csectDif)
|
192
|
+
hdr << Util.pack32array(@_sectFat)
|
193
|
+
|
194
|
+
fd.seek(0, ::IO::SEEK_SET)
|
195
|
+
fd.write(hdr)
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# Rex::OLE - an OLE implementation
|
5
|
+
# written in 2010 by Joshua J. Drake <jduck [at] metasploit.com>
|
6
|
+
##
|
7
|
+
|
8
|
+
module Rex
|
9
|
+
module OLE
|
10
|
+
|
11
|
+
class MiniFAT < DIFAT
|
12
|
+
|
13
|
+
#
|
14
|
+
# low-level functions
|
15
|
+
#
|
16
|
+
def read
|
17
|
+
@entries = []
|
18
|
+
|
19
|
+
visited = []
|
20
|
+
sect = @stg.header._sectMiniFatStart
|
21
|
+
@stg.header._csectMiniFat.times { |idx|
|
22
|
+
break if sect == SECT_END
|
23
|
+
|
24
|
+
if (visited.include?(sect))
|
25
|
+
raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect
|
26
|
+
end
|
27
|
+
visited << sect
|
28
|
+
|
29
|
+
buf = @stg.read_sector(sect, @stg.header.sector_size)
|
30
|
+
@stg.header.idx_per_sect.times { |idx|
|
31
|
+
@entries << Util.get32(buf, (idx*4))
|
32
|
+
}
|
33
|
+
sect = @stg.next_sector(sect)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def allocate_sector
|
38
|
+
idx = @entries.index(SECT_FREE)
|
39
|
+
|
40
|
+
if (not idx)
|
41
|
+
# add a sector worth
|
42
|
+
idx = @entries.length
|
43
|
+
@stg.header.idx_per_sect.times {
|
44
|
+
@entries << SECT_FREE
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
# default mini-sectors to end of chain
|
49
|
+
@entries[idx] = SECT_END
|
50
|
+
idx
|
51
|
+
end
|
52
|
+
|
53
|
+
def write
|
54
|
+
return if (@entries.length < 1)
|
55
|
+
|
56
|
+
mf_start = nil
|
57
|
+
mfs_count = 0
|
58
|
+
prev_sect = nil
|
59
|
+
copy = @entries.dup
|
60
|
+
while (copy.length > 0)
|
61
|
+
part = copy.slice!(0, @stg.header.idx_per_sect)
|
62
|
+
sbuf = Util.pack32array(part)
|
63
|
+
idx = @stg.write_sector(sbuf, nil, prev_sect)
|
64
|
+
mfs_count += 1
|
65
|
+
mf_start ||= idx
|
66
|
+
end
|
67
|
+
@stg.header._sectMiniFatStart = mf_start
|
68
|
+
@stg.header._csectMiniFat = mfs_count
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|