Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 88 additions & 17 deletions oletools/oleform.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class FormPropMask(Mask):
"""FormPropMask: [MS-OFORMS] 2.2.10.2"""
_size = 28
_names = ['Unused1', 'fBackColor', 'fForeColor', 'fNextAvailableID', 'Unused2_0', 'Unused2_1',
'fBooleanProperties', 'fBooleanProperties', 'fMousePointer', 'fScrollBars',
'fBooleanProperties', 'fBorderStyle', 'fMousePointer', 'fScrollBars',
'fDisplayedSize', 'fLogicalSize', 'fScrollPosition', 'fGroupCnt', 'Reserved',
'fMouseIcon', 'fCycle', 'fSpecialEffect', 'fBorderColor', 'fCaption', 'fFont',
'fPicture', 'fZoom', 'fPictureAlignment', 'fPictureTiling', 'fPictureSizeMode',
Expand Down Expand Up @@ -310,20 +310,20 @@ def consume_OleSiteConcreteControl(stream):
# SiteExtraDataBlock: [MS-OFORMS] 2.2.10.12.4
name = None
if (name_len > 0):
name = stream.read(name_len)
# Consume 2 null bytes between name and tag.
#if ((tag_len > 0) or (control_tip_text_len > 0)):
# stream.read(2)
# # Sometimes it looks like 2 extra null bytes go here whether or not there is a tag.
with stream.will_pad():
name = stream.read(name_len)
tag = None
if (tag_len > 0):
tag = stream.read(tag_len)
with stream.will_pad():
tag = stream.read(tag_len)
# Skip SitePosition.
if propmask.fPosition:
stream.read(8)
control_tip_text = stream.read(control_tip_text_len)
if (len(control_tip_text) == 0):
if (control_tip_text_len == 0):
control_tip_text = None
else:
with stream.will_pad():
control_tip_text = stream.read(control_tip_text_len)
return {'name': name, 'tag': tag, 'id': id, 'tabindex': tabindex,
'ClsidCacheIndex': ClsidCacheIndex, 'value': None, 'caption': None,
'control_tip_text':control_tip_text}
Expand Down Expand Up @@ -400,15 +400,20 @@ def consume_MorphDataControl(stream):
# MorphDataExtraDataBlock: [MS-OFORMS] 2.2.5.4
# Discard Size
stream.read(8)
value = stream.read(value_size)
value = ""
if (value_size > 0):
with stream.will_pad():
value = stream.read(value_size)
# Read caption text.
caption = ""
if (caption_size > 0):
caption = stream.read(caption_size)
with stream.will_pad():
caption = stream.read(caption_size)
# Read groupname text.
group_name = ""
if (group_name_size > 0):
group_name = stream.read(group_name_size)
with stream.will_pad():
group_name = stream.read(group_name_size)

# MorphDataStreamData: [MS-OFORMS] 2.2.5.5
if propmask.fMouseIcon:
Expand Down Expand Up @@ -437,13 +442,31 @@ def consume_CommandButtonControl(stream):
cbCommandButton = stream.unpack('<H', 2)
with stream.will_jump_to(cbCommandButton):
propmask = CommandButtonPropMask(stream.unpack('<L', 4))
# Skip the DataBlock and the ExtraDataBlock
# ImageStreamData: [MS-OFORMS] 2.2.1.5
# CommandButtonDataBlock: [MS-OFORMS] 2.2.1.3
with stream.padded_struct():
propmask.consume(stream, [('fForeColor', 4), ('fBackColor', 4),
('fVariousPropertyBits', 4)])
if propmask.fCaption:
caption_size = consume_CountOfBytesWithCompressionFlag(stream)
else:
caption_size = 0
propmask.consume(stream, [('fPicturePosition', 4), ('fMousePointer', 1),
('fPicture', 2), ('fAccelerator', 2),
('fMouseIcon', 2)])
# CommandButtonExtraDataBlock: [MS-OFORMS] 2.2.1.4
caption = ""
if (caption_size > 0):
with stream.will_pad():
caption = stream.read(caption_size)
stream.read(8)
# CommandButtonStreamData: [MS-OFORMS] 2.2.1.5
if propmask.fPicture:
consume_GuidAndPicture(stream)
if propmask.fMouseIcon:
consume_GuidAndPicture(stream)
# TextProps
consume_TextProps(stream)
return caption

def consume_SpinButtonControl(stream):
# SpinButtonControl: [MS-OFORMS] 2.2.8.1
Expand Down Expand Up @@ -502,7 +525,10 @@ def consume_LabelControl(stream):
('fSpecialEffect', 2), ('fPicture', 2),
('fAccelerator', 2), ('fMouseIcon', 2)])
# LabelExtraDataBlock: [MS-OFORMS] 2.2.4.4
caption = stream.read(caption_size)
caption = ""
if (caption_size > 0):
with stream.will_pad():
caption = stream.read(caption_size)
stream.read(8)
# LabelStreamData: [MS-OFORMS] 2.2.4.5
if propmask.fPicture:
Expand All @@ -524,6 +550,39 @@ def consume_ScrollBarControl(stream):
if propmask.fMouseIcon:
consume_GuidAndPicture(stream)

def consume_EmbeddedFormControl(stream):
# FormControl: [MS-OFORMS] 2.2.10.1
stream.check_values('FormControl (versions)', '<BB', 2, (0, 4))
cbform = stream.unpack('<H', 2)
caption = ""
with stream.will_jump_to(cbform):
propmask = FormPropMask(stream.unpack('<L', 4))
# Only extract Caption string, if it exists. Ignore everything else.
if propmask.fCaption:
# FormDataBlock: [MS-OFORMS] 2.2.10.3

with stream.padded_struct():
propmask.consume(stream, [('fBackColor', 4), ('fForeColor', 4),
('fNextAvailableID', 4), ('fBooleanProperties', 4),
('fBorderStyle', 1), ('fMousePointer', 1),
('fScrollBars', 1), ('fGroupCnt', 4),
('fMouseIcon', 2), ('fCycle', 1),
('fSpecialEffect', 1), ('fBorderColor', 4)])
caption_size = consume_CountOfBytesWithCompressionFlag(stream)
propmask.consume(stream, [('fFont', 2), ('fPicture', 2),
('fZoom', 4), ('fPictureAlignment', 1),
('fPictureSizeMode', 1),('fShapeCookie', 4),
('fDrawBuffer', 4)])

# FormExtraDataBlock: [MS-OFORMS] 2.2.10.4
propmask.consume(stream, [('fDisplayedSize', 8), ('fLogicalSize', 8), ('fScrollPosition', 8)])
# Read caption text.
if (caption_size > 0):
with stream.will_pad():
caption = stream.read(caption_size)
# Ignore rest of the stream
return caption

def extract_OleFormVariables(ole_file, stream_dir):
control = ExtendedStream.open(ole_file, '/'.join(stream_dir + ['f']))
variables = list(consume_FormControl(control))
Expand All @@ -535,13 +594,25 @@ def extract_OleFormVariables(ole_file, stream_dir):
elif var['ClsidCacheIndex'] == 12:
consume_ImageControl(data)
elif var['ClsidCacheIndex'] == 14:
consume_FormControl(data)
# Frame Control: [MS-OFORMS] 2.2.2
# Also see Embedded Parents : [MS-OFORMS] 2.1.2.2.2
if var['id'] < 10:
embedded_fstream_dir = '/'.join(stream_dir + ['i0'+str(var['id'])] + ['f'])
else:
embedded_fstream_dir = '/'.join(stream_dir + ['i'+str(var['id'])] + ['f'])

try:
embedded_form_control = ExtendedStream.open(ole_file, embedded_fstream_dir)
except:
pass
else:
var['caption'] = consume_EmbeddedFormControl(embedded_form_control)
elif var['ClsidCacheIndex'] in [15, 23, 24, 25, 26, 27, 28]:
var['value'], var['caption'], var['group_name'] = consume_MorphDataControl(data)
elif var['ClsidCacheIndex'] == 16:
consume_SpinButtonControl(data)
elif var['ClsidCacheIndex'] == 17:
consume_CommandButtonControl(data)
var['caption'] = consume_CommandButtonControl(data)
elif var['ClsidCacheIndex'] == 18:
consume_TabStripControl(data)
elif var['ClsidCacheIndex'] == 21:
Expand Down