From c5d4ec7b870d46c31949ef29dc91e634b8896ba7 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Tue, 31 Jan 2017 18:55:06 +0100 Subject: [PATCH] WIP: better parsing for /o --- oletools/oleform.py | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------- 1 file changed, 120 insertions(+), 76 deletions(-) diff --git a/oletools/oleform.py b/oletools/oleform.py index a7be38d..3ad821f 100644 --- a/oletools/oleform.py +++ b/oletools/oleform.py @@ -7,36 +7,60 @@ class OleFormParsingError(Exception): class Mask(object): def __init__(self, val): - self._val = [(val & (1<>i for i in range(32)] + self._val = [(val & (1<>i for i in range(self._size)] def __str__(self): - return ', '.join(self._names[i] for i in range(32) if self._val[i]) + return ', '.join(self._names[i] for i in range(self._size) if self._val[i]) def __getattr__(self, name): return self._val[self._names.index(name)] -class PropMask(Mask): + def __len__(self): + return self.size + + def __getitem__(self, key): + return self._val[self._names.index(key)] + +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', 'fDisplayedSize', 'fLogicalSize', 'fScrollPosition', 'fGroupCnt', 'Reserved', 'fMouseIcon', 'fCycle', 'fSpecialEffect', 'fBorderColor', 'fCaption', 'fFont', 'fPicture', 'fZoom', 'fPictureAlignment', 'fPictureTiling', 'fPictureSizeMode', - 'fShapeCookie', 'fDrawBuffer', 'Unused3_0', 'Unused3_1', 'Unused3_2', 'Unused3_3'] + 'fShapeCookie', 'fDrawBuffer'] class SitePropMask(Mask): + """SitePropMask: [MS-OFORMS] 2.2.10.12.2""" + _size = 15 _names = ['fName', 'fTag', 'fID', 'fHelpContextID', 'fBitFlags', 'fObjectStreamSize', 'fTabIndex', 'fClsidCacheIndex', 'fPosition', 'fGroupID', 'Unused1', - 'fControlTipText', 'fRuntimeLicKey', 'fControlSource', 'fRowSource', 'Unused2_0', - 'Unused2_1', 'Unused2_2', 'Unused2_3', 'Unused2_4', 'Unused2_5', 'Unused2_6', - 'Unused2_7', 'Unused2_8', 'Unused2_9', 'Unused2_10', 'Unused2_11', 'Unused2_12', - 'Unused2_13', 'Unused2_14', 'Unused2_15', 'Unused2_16'] + 'fControlTipText', 'fRuntimeLicKey', 'fControlSource', 'fRowSource'] + +class MorphDataPropMask(Mask): + """MorphDataPropMask: [MS-OFORMS] 2.2.5.2""" + _size = 33 + _names = ['fVariousPropertyBits', 'fBackColor', 'fForeColor', 'fMaxLength', 'fBorderStyle', + 'fScrollBars', 'fDisplayStyle', 'fMousePointer', 'fSize', 'fPasswordChar', + 'fListWidth', 'fBoundColumn', 'fTextColumn', 'fColumnCount', 'fListRows', + 'fcColumnInfo', 'fMatchEntry', 'fListStyle', 'fShowDropButtonWhen', 'UnusedBits1', + 'fDropButtonStyle', 'fMultiSelect', 'fValue', 'fCaption', 'fPicturePosition', + 'fBorderColor', 'fSpecialEffect', 'fMouseIcon', 'fPicture', 'fAccelerator', + 'UnusedBits2', 'Reserved', 'fGroupName'] class OleUserFormParser(object): - def __init__(self, stream): - self.content = [] - self._stream = stream + def __init__(self, control_stream, data_stream): + self.variables = [] + self.set_stream(control_stream) + self.consume_FormControl() + self.set_stream(data_stream) + self.consume_stored_data() + + def set_stream(self, stream): self._pos = 0 self._frozen_pos = [] + self._stream = stream def read(self, size): self._pos += size @@ -67,6 +91,12 @@ class OleUserFormParser(object): def check_value(self, name, format, size, expected): self.check_values(name, format, size, (expected,)) + def consume_TextProps(self): + # TextProps: [MS-OFORMS] 2.3.1 + self.check_values('TextProps (versions)', 'Q', 8) @@ -80,10 +110,7 @@ class OleUserFormParser(object): self.read(bFaceLen) elif UUIDs == (2948729120, 55886, 4558, 13349514450607572916L): # UUID == {AFC20920-DA4E-11CE-B94300AA006887B4} - # TextProps: [MS-OFORMS] 2.3.1 - self.check_value('TextProps (versions)', '> 15 @@ -208,36 +223,65 @@ class OleUserFormParser(object): for i in range(CountOfSites): self.consume_OleSiteConcreteControl() - def consume_stream_o(self): - # Adapted from plugin_stream_o.py from Didier Stevens's oledump.py - while(True): - try: - (code, length) = self.unpacks('