Commit 9d2795aa1a3b3af0d7255da9b63e7171e65af843

Authored by Vincent Brillault
1 parent 425a038a

WIP: oleform: implement other types of stored controls

Showing 1 changed file with 158 additions and 3 deletions
oletools/oleform.py
@@ -52,6 +52,52 @@ class MorphDataPropMask(Mask): @@ -52,6 +52,52 @@ class MorphDataPropMask(Mask):
52 'fBorderColor', 'fSpecialEffect', 'fMouseIcon', 'fPicture', 'fAccelerator', 52 'fBorderColor', 'fSpecialEffect', 'fMouseIcon', 'fPicture', 'fAccelerator',
53 'UnusedBits2', 'Reserved', 'fGroupName'] 53 'UnusedBits2', 'Reserved', 'fGroupName']
54 54
  55 +class ImagePropMask(Mask):
  56 + """ImagePropMask: [MS-OFORMS] 2.2.3.2"""
  57 + _size = 15
  58 + _names = ['UnusedBits1_1', 'UnusedBits1_2', 'fAutoSize', 'fBorderColor', 'fBackColor',
  59 + 'fBorderStyle', 'fMousePointer', 'fPictureSizeMode', 'fSpecialEffect', 'fSize',
  60 + 'fPicture', 'fPictureAlignment', 'fPictureTiling', 'fVariousPropertyBits',
  61 + 'fMouseIcon']
  62 +
  63 +class CommandButtonPropMask(Mask):
  64 + """CommandButtonPropMask: [MS-OFORMS] 2.2.1.2"""
  65 + _size = 11
  66 + _names = ['fForeColor', 'fBackColor', 'fVariousPropertyBits', 'fCaption', 'fPicturePosition',
  67 + 'fSize', 'fMousePointer', 'fPicture', 'fAccelerator', 'fTakeFocusOnClick',
  68 + 'fMouseIcon']
  69 +
  70 +class SpinButtonPropMask(Mask):
  71 + """SpinButtonPropMask: [MS-OFORMS] 2.2.8.2"""
  72 + _size = 15
  73 + _names = ['fForeColor', 'fBackColor', 'fVariousPropertyBits', 'fSize', 'UnusedBits1',
  74 + 'fMin', 'fMax', 'fPosition', 'fPrevEnabled', 'fNextEnabled', 'fSmallChange',
  75 + 'fOrientation', 'fDelay', 'fMouseIcon', 'fMousePointer']
  76 +
  77 +class TabStripPropMask(Mask):
  78 + """TabStripPropMask: [MS-OFORMS] 2.2.9.2"""
  79 + _size = 25
  80 + _names = ['fListIndex', 'fBackColor', 'fForeColor', 'Unused1', 'fSize', 'fItems',
  81 + 'fMousePointer', 'Unused2', 'fTabOrientation', 'fTabStyle', 'fMultiRow',
  82 + 'fTabFixedWidth', 'fTabFixedHeight', 'fTooltips', 'Unused3', 'fTipStrings',
  83 + 'Unused4', 'fNames', 'fVariousPropertyBits', 'fNewVersion', 'fTabsAllocated',
  84 + 'fTags', 'fTabData', 'fAccelerator', 'fMouseIcon']
  85 +
  86 +class LabelPropMask(Mask):
  87 + """LabelPropMask: [MS-OFORMS] 2.2.4.2"""
  88 + _size = 13
  89 + _names = ['fForeColor', 'fBackColor', 'fVariousPropertyBits', 'fCaption',
  90 + 'fPicturePosition', 'fSize', 'fMousePointer', 'fBorderColor', 'fBorderStyle',
  91 + 'fSpecialEffect', 'fPicture', 'fAccelerator', 'fMouseIcon']
  92 +
  93 +class ScrollBarPropMask(Mask):
  94 + """ScrollBarPropMask: [MS-OFORMS] 2.2.7.2"""
  95 + _size = 17
  96 + _names = ['fForeColor', 'fBackColor', 'fVariousPropertyBits', 'fSize', 'fMousePointer',
  97 + 'fMin', 'fMax', 'fPosition', 'UnusedBits1', 'fPrevEnabled', 'fNextEnabled',
  98 + 'fSmallChange', 'fLargeChange', 'fOrientation', 'fProportionalThumb',
  99 + 'fDelay', 'fMouseIcon']
  100 +
55 class ExtendedStream(object): 101 class ExtendedStream(object):
56 def __init__(self, stream, path): 102 def __init__(self, stream, path):
57 self._pos = 0 103 self._pos = 0
@@ -287,16 +333,125 @@ def consume_MorphDataControl(stream): @@ -287,16 +333,125 @@ def consume_MorphDataControl(stream):
287 consume_TextProps(stream) 333 consume_TextProps(stream)
288 return value 334 return value
289 335
  336 +def consume_ImageControl(stream):
  337 + # ImageControl: [MS-OFORMS] 2.2.3.1
  338 + stream.check_values('ImageControl (versions)', '<BB', 2, (0, 2))
  339 + cbImage = stream.unpack('<H', 2)
  340 + with stream.will_jump_to(cbImage):
  341 + propmask = ImagePropMask(stream.unpack('<L', 4))
  342 + # Skip the DataBlock and the ExtraDataBlock
  343 + # ImageStreamData: [MS-OFORMS] 2.2.3.5
  344 + if propmask.fPicture:
  345 + consume_GuidAndPicture(stream)
  346 + if propmask.fMouseIcon:
  347 + consume_GuidAndPicture(stream)
  348 +
  349 +def consume_CommandButtonControl(stream):
  350 + # CommandButtonControl: [MS-OFORMS] 2.2.1.1
  351 + stream.check_values('CommandButtonControl (versions)', '<BB', 2, (0, 2))
  352 + cbCommandButton = stream.unpack('<H', 2)
  353 + with stream.will_jump_to(cbCommandButton):
  354 + propmask = CommandButtonPropMask(stream.unpack('<L', 4))
  355 + # Skip the DataBlock and the ExtraDataBlock
  356 + # ImageStreamData: [MS-OFORMS] 2.2.1.5
  357 + if propmask.fPicture:
  358 + consume_GuidAndPicture(stream)
  359 + if propmask.fMouseIcon:
  360 + consume_GuidAndPicture(stream)
  361 + consume_TextProps(stream)
  362 +
  363 +def consume_SpinButtonControl(stream):
  364 + # SpinButtonControl: [MS-OFORMS] 2.2.8.1
  365 + stream.check_values('SpinButtonControl (versions)', '<BB', 2, (0, 2))
  366 + cbSpinButton = stream.unpack('<H', 2)
  367 + with stream.will_jump_to(cbSpinButton):
  368 + propmask = SpinButtonPropMask(stream.unpack('<L', 4))
  369 + # Skip the DataBlock and the ExtraDataBlock
  370 + # SpinButtonStreamData: [MS-OFORMS] 2.2.8.5
  371 + if propmask.fMouseIcon:
  372 + consume_GuidAndPicture(stream)
  373 +
  374 +def consume_TabStripControl(stream):
  375 + # TabStripControl: [MS-OFORMS] 2.2.9.1
  376 + stream.check_values('TabStripControl (versions)', '<BB', 2, (0, 2))
  377 + cbTabStrip = stream.unpack('<H', 2)
  378 + with stream.will_jump_to(cbTabStrip):
  379 + propmask = TabStripPropMask(stream.unpack('<L', 4))
  380 + # TabStripDataBlock: [MS-OFORMS] 2.2.9.3
  381 + # All are 4B (or 4B + pad = 4B), except MousePointer, which is 1B + pad = 4b
  382 + for prop in ['fListIndex', 'fBackColor', 'fForeColor', 'fSize', 'fTabOrientation'
  383 + 'fTabStyle', 'fTabFixedWidth', 'fTabFixedHeight', 'fTipStrings',
  384 + 'fNames', 'fVariousPropertyBits', 'fTabsAllocated', 'fTags']:
  385 + if propmask[prop]:
  386 + stream.read(4)
  387 + tabData = 0
  388 + if propmask['fTabData']:
  389 + tabData = stream.unpack('<L', 4)
  390 + # Skip the ExtraDataBlock
  391 + # TabStripStreamData: [MS-OFORMS] 2.2.9.5
  392 + if propmask.fMouseIcon:
  393 + consume_GuidAndPicture(stream)
  394 + # TextProps
  395 + consume_TextProps(stream)
  396 + # TabStripTabFlagData: [MS-OFORMS] 2.2.9.6
  397 + for i in range(tabData):
  398 + stream.read(4)
  399 +
  400 +def consume_LabelControl(stream):
  401 + # LabelControl: [MS-OFORMS] 2.2.4.1
  402 + stream.check_values('LabelControl (versions)', '<BB', 2, (0, 2))
  403 + cbLabel = stream.unpack('<H', 2)
  404 + with stream.will_jump_to(cbLabel):
  405 + propmask = LabelPropMask(stream.unpack('<L', 4))
  406 + # Skip the DataBlock and the ExtraDataBlock
  407 + # LabelStreamData: [MS-OFORMS] 2.2.4.5
  408 + if propmask.fPicture:
  409 + consume_GuidAndPicture(stream)
  410 + if propmask.fMouseIcon:
  411 + consume_GuidAndPicture(stream)
  412 + # TextProps
  413 + consume_TextProps(stream)
  414 +
  415 +def consume_ScrollBarControl(stream):
  416 + # ScrollBarControl: [MS-OFORMS] 2.2.7.1
  417 + stream.check_values('LabelControl (versions)', '<BB', 2, (0, 2))
  418 + cbScrollBar = stream.unpack('<H', 2)
  419 + with stream.will_jump_to(cbScrollBar):
  420 + propmask = ScrollBarPropMask(stream.unpack('<L', 4))
  421 + # Skip the DataBlock and the ExtraDataBlock
  422 + # ScrollBarStreamData: [MS-OFORMS] 2.2.7.5
  423 + if propmask.fMouseIcon:
  424 + consume_GuidAndPicture(stream)
  425 +
290 def extract_OleFormVariables(ole_file, stream_dir): 426 def extract_OleFormVariables(ole_file, stream_dir):
291 control = ExtendedStream.open(ole_file, '/'.join(stream_dir + ['f'])) 427 control = ExtendedStream.open(ole_file, '/'.join(stream_dir + ['f']))
292 variables = list(consume_FormControl(control)) 428 variables = list(consume_FormControl(control))
293 # print('/'.join(stream_dir + ['o'])) 429 # print('/'.join(stream_dir + ['o']))
294 data = ExtendedStream.open(ole_file, '/'.join(stream_dir + ['o'])) 430 data = ExtendedStream.open(ole_file, '/'.join(stream_dir + ['o']))
295 for var in variables: 431 for var in variables:
296 - if var['ClsidCacheIndex'] != 23: 432 + # See FormEmbeddedActiveXControlCached for type definition: [MS-OFORMS] 2.4.5
  433 + if var['ClsidCacheIndex'] == 7:
  434 + raise OleFormParsingError('Malformed document: Forms should be stored in the f stream')
  435 + elif var['ClsidCacheIndex'] == 12:
  436 + consume_ImageControl(data)
  437 + elif var['ClsidCacheIndex'] == 14:
  438 + raise OleFormParsingError('Malformed document: Frames should be stored in the f stream')
  439 + elif var['ClsidCacheIndex'] in [15, 23, 24, 25, 26, 27, 28]:
  440 + var['value'] = consume_MorphDataControl(data)
  441 + elif var['ClsidCacheIndex'] == 16:
  442 + consume_SpinButtonControl(data)
  443 + elif var['ClsidCacheIndex'] == 17:
  444 + consume_CommandButtonControl(data)
  445 + elif var['ClsidCacheIndex'] == 18:
  446 + consume_TabStripControl(data)
  447 + elif var['ClsidCacheIndex'] == 21:
  448 + consume_LabelControl(data)
  449 + elif var['ClsidCacheIndex'] == 47:
  450 + consume_ScrollBarControl(data)
  451 + elif var['ClsidCacheIndex'] == 57:
  452 + raise OleFormParsingError('Malformed document: MultiPages should be stored in a x stream')
  453 + else:
297 # TODO: use logging instead of print 454 # TODO: use logging instead of print
298 print('ERROR: Unsupported stored type in user form: {0}'.format(str(var['ClsidCacheIndex']))) 455 print('ERROR: Unsupported stored type in user form: {0}'.format(str(var['ClsidCacheIndex'])))
299 break 456 break
300 - else:  
301 - var['value'] = consume_MorphDataControl(data)  
302 return variables 457 return variables