Commit 6d7514ce799d78c0b23c4d187554423ca78b3149

Authored by decalage2
1 parent 8b97e45b

plugin_biff: updated to v0.0.11 (improved formula parsing)

oletools/olevba.py
@@ -227,7 +227,7 @@ from __future__ import print_function @@ -227,7 +227,7 @@ from __future__ import print_function
227 # 2020-01-31 v0.56 KS: - added option --no-xlm, improved MHT detection 227 # 2020-01-31 v0.56 KS: - added option --no-xlm, improved MHT detection
228 # 2020-03-22 PL: - uses plugin_biff to display DCONN objects and their URL 228 # 2020-03-22 PL: - uses plugin_biff to display DCONN objects and their URL
229 229
230 -__version__ = '0.56dev3' 230 +__version__ = '0.56dev4'
231 231
232 #------------------------------------------------------------------------------ 232 #------------------------------------------------------------------------------
233 # TODO: 233 # TODO:
oletools/thirdparty/oledump/oledump_extract.py 0 → 100644
  1 +#!/usr/bin/env python
  2 +
  3 +# Small extract of oledump.py to be able to run plugin_biff from olevba
  4 +
  5 +__description__ = 'Analyze OLE files (Compound Binary Files)'
  6 +__author__ = 'Didier Stevens'
  7 +__version__ = '0.0.49'
  8 +__date__ = '2020/03/28'
  9 +
  10 +"""
  11 +
  12 +Source code put in public domain by Didier Stevens, no Copyright
  13 +https://DidierStevens.com
  14 +Use at your own risk
  15 +"""
  16 +
  17 +class cPluginParent():
  18 + macroOnly = False
  19 + indexQuiet = False
  20 +
  21 +plugins = []
  22 +
  23 +def AddPlugin(cClass):
  24 + global plugins
  25 +
  26 + plugins.append(cClass)
  27 +
  28 +
  29 +# CIC: Call If Callable
  30 +def CIC(expression):
  31 + if callable(expression):
  32 + return expression()
  33 + else:
  34 + return expression
  35 +
  36 +# IFF: IF Function
  37 +def IFF(expression, valueTrue, valueFalse):
  38 + if expression:
  39 + return CIC(valueTrue)
  40 + else:
  41 + return CIC(valueFalse)
  42 +
  43 +def P23Ord(value):
  44 + if type(value) == int:
  45 + return value
  46 + else:
  47 + return ord(value)
  48 +
  49 +def P23Chr(value):
  50 + if type(value) == int:
  51 + return chr(value)
  52 + else:
  53 + return value
oletools/thirdparty/oledump/plugin_biff.py
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 2
3 __description__ = 'BIFF plugin for oledump.py' 3 __description__ = 'BIFF plugin for oledump.py'
4 __author__ = 'Didier Stevens' 4 __author__ = 'Didier Stevens'
5 -__version__ = '0.0.9'  
6 -__date__ = '2020/03/09' 5 +__version__ = '0.0.11'
  6 +__date__ = '2020/04/06'
7 7
8 # Slightly modified version by Philippe Lagadec to be imported into olevba 8 # Slightly modified version by Philippe Lagadec to be imported into olevba
9 9
@@ -28,6 +28,14 @@ History: @@ -28,6 +28,14 @@ History:
28 2020/02/23: 0.0.7 performance improvement 28 2020/02/23: 0.0.7 performance improvement
29 2020/03/08: 0.0.8 added options -X and -d 29 2020/03/08: 0.0.8 added options -X and -d
30 2020/03/09: 0.0.9 improved formula parsing; Python 3 bugfixes 30 2020/03/09: 0.0.9 improved formula parsing; Python 3 bugfixes
  31 + 2020/03/27: 0.0.10 improved formula parsing and debug modes. (by @JohnLaTwC)
  32 + 05219f8c047f1dff861634c4b50d4f6978c87c35f4c14d21ee9d757cac9280cf (ptgConcat)
  33 + 94b26003699efba54ced98006379a230d1154f340589cc89af7d0cbedb861a53 (encoding, ptgFuncVarA, ptgNameX)
  34 + d3c1627ca2775d98717eb1abf2b70aedf383845d87993c6b924f2f55d9d4d696 (ptgArea)
  35 + 01761b06c24baa818b0a75059e745871246a5e9c6ce0243ad96e8632342cbb59 (ptgFuncVarA)
  36 + d3c1627ca2775d98717eb1abf2b70aedf383845d87993c6b924f2f55d9d4d696 (ptgFunc)
  37 + 1d48a42a0b06a087e966b860c8f293a9bf57da8d70f5f83c61242afc5b81eb4f (=SELECT($B$1:$1000:$1000:$B:$B,$B$1))
  38 + 2020/04/06: 0.0.11 Python 2 bugfixes; password protect record FILEPASS
31 39
32 Todo: 40 Todo:
33 """ 41 """
@@ -35,44 +43,19 @@ Todo: @@ -35,44 +43,19 @@ Todo:
35 import struct 43 import struct
36 import re 44 import re
37 import optparse 45 import optparse
  46 +
  47 +# Modifications for olevba:
38 import sys 48 import sys
39 import binascii 49 import binascii
40 -  
41 -# A few functions backported from oledump.py:  
42 -  
43 -class cPluginParent():  
44 - macroOnly = False  
45 - indexQuiet = False  
46 -  
47 -# CIC: Call If Callable  
48 -def CIC(expression):  
49 - if callable(expression):  
50 - return expression()  
51 - else:  
52 - return expression  
53 -  
54 -# IFF: IF Function  
55 -def IFF(expression, valueTrue, valueFalse):  
56 - if expression:  
57 - return CIC(valueTrue)  
58 - else:  
59 - return CIC(valueFalse)  
60 -  
61 -def P23Ord(value):  
62 - if type(value) == int:  
63 - return value  
64 - else:  
65 - return ord(value)  
66 -  
67 -def P23Chr(value):  
68 - if type(value) == int:  
69 - return chr(value)  
70 - else:  
71 - return value 50 +from .oledump_extract import *
  51 +# end modifications
72 52
73 def P23Decode(value): 53 def P23Decode(value):
74 if sys.version_info[0] > 2: 54 if sys.version_info[0] > 2:
75 - return value.decode() 55 + try:
  56 + return value.decode('utf-8')
  57 + except UnicodeDecodeError as u:
  58 + return value.decode('windows-1252')
76 else: 59 else:
77 return value 60 return value
78 61
@@ -115,6 +98,67 @@ def Strings(data, encodings='sL'): @@ -115,6 +98,67 @@ def Strings(data, encodings='sL'):
115 def ContainsWP23Ord(word, expression): 98 def ContainsWP23Ord(word, expression):
116 return struct.pack('<H', word) in expression 99 return struct.pack('<H', word) in expression
117 100
  101 +# https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/75afd109-b1ce-4511-b56f-2d63116f6647
  102 +def ParseArea(expression):
  103 + formatcodes = 'HHHH'
  104 + formatsize = struct.calcsize(formatcodes)
  105 + if len(expression) < formatsize:
  106 + return '*ERROR*'
  107 + row1,row2,col1,col2 = struct.unpack(formatcodes, expression[0:formatsize])
  108 + row1Relative = col1 & 0x8000
  109 + col1Relative = col1 & 0x4000
  110 + row2Relative = col2 & 0x8000
  111 + col2Relative = col2 & 0x4000
  112 + col1 = col1 & 0x3FFF
  113 + col2 = col2 & 0x3FFF
  114 +
  115 + if row1Relative:
  116 + row1indicator = '~'
  117 + else:
  118 + row1indicator = ''
  119 + row1 += 1
  120 + if col1Relative:
  121 + col1indicator = '~'
  122 + else:
  123 + col1indicator = ''
  124 + col1 += 1
  125 + if row2Relative:
  126 + row2indicator = '~'
  127 + else:
  128 + row2indicator = ''
  129 + row2 += 1
  130 + if col2Relative:
  131 + col2indicator = '~'
  132 + else:
  133 + col2indicator = ''
  134 + col2 += 1
  135 +
  136 + if row1 == row2 and col2 >=256:
  137 + return 'R%s%d' % (row1indicator, row1)
  138 + if col1 == col2 and row2 >= 65536:
  139 + return 'C%s%d' % (col1indicator, col1)
  140 +
  141 + return 'R%s%dC%s%d' % (row1indicator, row1, col1indicator, col1)
  142 +
  143 +# https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad
  144 +def ParseLocRelU(expression):
  145 + row = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
  146 + column = P23Ord(expression[2]) + P23Ord(expression[3]) * 0x100
  147 + rowRelative = False #P23Ord(expression[3]) & 0x0001
  148 + colRelative = False #P23Ord(expression[3]) & 0x0002
  149 + #column = column & 0xFFFC
  150 + if rowRelative:
  151 + rowindicator = '~'
  152 + else:
  153 + rowindicator = ''
  154 + row += 1
  155 + if colRelative:
  156 + colindicator = '~'
  157 + else:
  158 + colindicator = ''
  159 + column += 1
  160 + return 'R%s%dC%s%d' % (rowindicator, row, colindicator, column)
  161 +
118 #https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad 162 #https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad
119 def ParseLoc(expression): 163 def ParseLoc(expression):
120 formatcodes = 'HH' 164 formatcodes = 'HH'
@@ -160,6 +204,7 @@ def ParseExpression(expression): @@ -160,6 +204,7 @@ def ParseExpression(expression):
160 0x15: 'ptgParen', 204 0x15: 'ptgParen',
161 0x16: 'ptgMissArg', 205 0x16: 'ptgMissArg',
162 0x17: 'ptgStr', 206 0x17: 'ptgStr',
  207 +0x18: 'ptgExtend',
163 0x19: 'ptgAttr', 208 0x19: 'ptgAttr',
164 0x1A: 'ptgSheet', 209 0x1A: 'ptgSheet',
165 0x1B: 'ptgEndSheet', 210 0x1B: 'ptgEndSheet',
@@ -1017,15 +1062,38 @@ def ParseExpression(expression): @@ -1017,15 +1062,38 @@ def ParseExpression(expression):
1017 result += dTokens[ptgid] + ' ' 1062 result += dTokens[ptgid] + ' '
1018 if ptgid == 0x03: # ptgAdd https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/27db2f45-11e8-4238-94ed-92fd9c5721fb 1063 if ptgid == 0x03: # ptgAdd https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/27db2f45-11e8-4238-94ed-92fd9c5721fb
1019 pass 1064 pass
  1065 + elif ptgid == 0x4: # ptgSub
  1066 + pass
  1067 + elif ptgid == 0x5: # ptgMul
  1068 + pass
  1069 + elif ptgid == 0x6: # ptgDiv
  1070 + pass
  1071 + elif ptgid == 0x8: # ptgConcat
  1072 + pass
1020 elif ptgid == 0x09: # ptgLt https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/28de4981-1352-4a5e-a3b7-f15a8a6ce7fb 1073 elif ptgid == 0x09: # ptgLt https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/28de4981-1352-4a5e-a3b7-f15a8a6ce7fb
1021 pass 1074 pass
  1075 + elif ptgid == 0x0A: # ptgLE
  1076 + pass
  1077 + elif ptgid == 0x0B: # ptgEQ
  1078 + pass
  1079 + elif ptgid == 0x0C: # ptgGE
  1080 + pass
  1081 + elif ptgid == 0x0D: # ptgGT
  1082 + pass
  1083 + elif ptgid == 0x0E: # ptgNE
  1084 + pass
1022 elif ptgid == 0x17: # ptgStr https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/87c2a057-705c-4473-a168-6d5fac4a9eba 1085 elif ptgid == 0x17: # ptgStr https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/87c2a057-705c-4473-a168-6d5fac4a9eba
1023 length = P23Ord(expression[0]) 1086 length = P23Ord(expression[0])
1024 expression = expression[1:] 1087 expression = expression[1:]
1025 if P23Ord(expression[0]) == 0: # probably BIFF8 -> UNICODE (compressed) 1088 if P23Ord(expression[0]) == 0: # probably BIFF8 -> UNICODE (compressed)
1026 expression = expression[1:] 1089 expression = expression[1:]
1027 - result += '"%s" ' % P23Decode(expression[:length])  
1028 - expression = expression[length:] 1090 + result += '"%s" ' % P23Decode(expression[:length])
  1091 + expression = expression[length:]
  1092 + elif P23Ord(expression[0]) == 1: # if 1, then double byte chars
  1093 + # doublebyte check: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/05162858-0ca9-44cb-bb07-a720928f63f8
  1094 + expression = expression[1:]
  1095 + result += '"%s" ' % P23Decode(expression[:length*2])
  1096 + expression = expression[length*2:]
1029 elif ptgid == 0x19: 1097 elif ptgid == 0x19:
1030 grbit = P23Ord(expression[0]) 1098 grbit = P23Ord(expression[0])
1031 expression = expression[1:] 1099 expression = expression[1:]
@@ -1046,10 +1114,12 @@ def ParseExpression(expression): @@ -1046,10 +1114,12 @@ def ParseExpression(expression):
1046 functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100 1114 functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
1047 result += '%s (0x%04x) ' % (dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) 1115 result += '%s (0x%04x) ' % (dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid)
1048 expression = expression[2:] 1116 expression = expression[2:]
1049 - elif ptgid == 0x22 or ptgid == 0x42: 1117 + elif ptgid == 0x22 or ptgid == 0x42 or ptgid == 0x62:
1050 functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100 1118 functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100
1051 result += 'args %d func %s (0x%04x) ' % (P23Ord(expression[0]), dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) 1119 result += 'args %d func %s (0x%04x) ' % (P23Ord(expression[0]), dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid)
1052 expression = expression[3:] 1120 expression = expression[3:]
  1121 + if functionid == 0x806D:
  1122 + expression = expression[9:]
1053 elif ptgid == 0x23: # ptgName https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/5f05c166-dfe3-4bbf-85aa-31c09c0258c0 1123 elif ptgid == 0x23: # ptgName https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/5f05c166-dfe3-4bbf-85aa-31c09c0258c0
1054 result += '0x%08x ' % (struct.unpack('<I', expression[0:4])) 1124 result += '0x%08x ' % (struct.unpack('<I', expression[0:4]))
1055 expression = expression[4:] 1125 expression = expression[4:]
@@ -1057,8 +1127,9 @@ def ParseExpression(expression): @@ -1057,8 +1127,9 @@ def ParseExpression(expression):
1057 result += 'FLOAT ' 1127 result += 'FLOAT '
1058 expression = expression[8:] 1128 expression = expression[8:]
1059 elif ptgid == 0x26: 1129 elif ptgid == 0x26:
1060 - expression = expression[4:]  
1061 - expression = expression[P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100:] 1130 + ## expression = expression[4:]
  1131 + ## expression = expression[P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100:]
  1132 + expression = expression[6:]
1062 result += 'REFERENCE-EXPRESSION ' 1133 result += 'REFERENCE-EXPRESSION '
1063 elif ptgid == 0x01: 1134 elif ptgid == 0x01:
1064 formatcodes = 'HH' 1135 formatcodes = 'HH'
@@ -1067,11 +1138,32 @@ def ParseExpression(expression): @@ -1067,11 +1138,32 @@ def ParseExpression(expression):
1067 expression = expression[formatsize:] 1138 expression = expression[formatsize:]
1068 result += 'R%dC%d ' % (row + 1, column + 1) 1139 result += 'R%dC%d ' % (row + 1, column + 1)
1069 elif ptgid == 0x24 or ptgid == 0x44: 1140 elif ptgid == 0x24 or ptgid == 0x44:
1070 - result += '%s ' % ParseLoc(expression) 1141 + result += '%s ' % ParseLocRelU(expression)
1071 expression = expression[4:] 1142 expression = expression[4:]
  1143 + elif ptgid == 0x11: # ptgRange
  1144 + pass
  1145 + elif ptgid == 0x25: # ptgArea
  1146 + result += '%s ' % ParseArea(expression[0:8])
  1147 + expression = expression[8:]
1072 elif ptgid == 0x3A or ptgid == 0x5A: 1148 elif ptgid == 0x3A or ptgid == 0x5A:
1073 result += '%s ' % ParseLoc(expression[2:]) 1149 result += '%s ' % ParseLoc(expression[2:])
1074 expression = expression[6:] 1150 expression = expression[6:]
  1151 + elif ptgid == 0x39: # PtgNameX
  1152 + expression = expression[2:]
  1153 + formatcodes = 'H'
  1154 + formatsize = struct.calcsize(formatcodes)
  1155 + nameindex = struct.unpack(formatcodes, expression[0:formatsize])[0]
  1156 + result += ' NAMEIDX %d ' % nameindex
  1157 + expression = expression[4:]
  1158 + elif ptgid == 0x21: #ptgFunc
  1159 + functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100
  1160 + result += '%s ' % dFunctions.get(functionid, '*UNKNOWN FUNCTION*')
  1161 + expression = expression[2:]
  1162 + elif ptgid == 0x61 or ptgid == 0x62: # ptgFuncVar ptgFuncVarA
  1163 + params_count = P23Ord(expression[0])
  1164 + functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100
  1165 + result += '%s ' % dFunctions.get(functionid, '*UNKNOWN FUNCTION*')
  1166 + expression = expression[(2+params_count):]
1075 else: 1167 else:
1076 break 1168 break
1077 else: 1169 else:
@@ -1101,6 +1193,7 @@ class cBIFF(cPluginParent): @@ -1101,6 +1193,7 @@ class cBIFF(cPluginParent):
1101 def Analyze(self): 1193 def Analyze(self):
1102 result = [] 1194 result = []
1103 macros4Found = False 1195 macros4Found = False
  1196 + filepassFound = False
1104 dOpcodes = { 1197 dOpcodes = {
1105 0x06: 'FORMULA : Cell Formula', 1198 0x06: 'FORMULA : Cell Formula',
1106 0x0A: 'EOF : End of File', 1199 0x0A: 'EOF : End of File',
@@ -1370,6 +1463,7 @@ class cBIFF(cPluginParent): @@ -1370,6 +1463,7 @@ class cBIFF(cPluginParent):
1370 oParser.add_option('-s', '--strings', action='store_true', default=False, help='Dump strings') 1463 oParser.add_option('-s', '--strings', action='store_true', default=False, help='Dump strings')
1371 oParser.add_option('-a', '--hexascii', action='store_true', default=False, help='Dump hex ascii') 1464 oParser.add_option('-a', '--hexascii', action='store_true', default=False, help='Dump hex ascii')
1372 oParser.add_option('-X', '--hex', action='store_true', default=False, help='Dump hex without whitespace') 1465 oParser.add_option('-X', '--hex', action='store_true', default=False, help='Dump hex without whitespace')
  1466 + oParser.add_option('-b', '--formulabytes', action='store_true', default=False, help='Dump formula bytes')
1373 oParser.add_option('-d', '--dump', action='store_true', default=False, help='Dump') 1467 oParser.add_option('-d', '--dump', action='store_true', default=False, help='Dump')
1374 oParser.add_option('-x', '--xlm', action='store_true', default=False, help='Select all records relevant for Excel 4.0 macros') 1468 oParser.add_option('-x', '--xlm', action='store_true', default=False, help='Select all records relevant for Excel 4.0 macros')
1375 oParser.add_option('-o', '--opcode', type=str, default='', help='Opcode to filter for') 1469 oParser.add_option('-o', '--opcode', type=str, default='', help='Opcode to filter for')
@@ -1405,6 +1499,10 @@ class cBIFF(cPluginParent): @@ -1405,6 +1499,10 @@ class cBIFF(cPluginParent):
1405 length = struct.unpack(formatcodes, data[20:20 + formatsize])[0] 1499 length = struct.unpack(formatcodes, data[20:20 + formatsize])[0]
1406 expression = data[22:] 1500 expression = data[22:]
1407 line += ' - R%dC%d len=%d %s' % (row + 1, column + 1, length, ParseExpression(expression)) 1501 line += ' - R%dC%d len=%d %s' % (row + 1, column + 1, length, ParseExpression(expression))
  1502 + if options.formulabytes:
  1503 + data_hex = P23Decode(binascii.b2a_hex(data))
  1504 + spaced_data_hex = ' '.join(a+b for a,b in zip(data_hex[::2], data_hex[1::2]))
  1505 + line += '\nFORMULA BYTES: %s' % spaced_data_hex
1408 1506
1409 # FORMULA record #a# difference BIFF4 and BIFF5+ 1507 # FORMULA record #a# difference BIFF4 and BIFF5+
1410 if opcode == 0x18 and len(data) >= 16: 1508 if opcode == 0x18 and len(data) >= 16:
@@ -1420,6 +1518,10 @@ class cBIFF(cPluginParent): @@ -1420,6 +1518,10 @@ class cBIFF(cPluginParent):
1420 offset = 15 1518 offset = 15
1421 line += ' - %s' % (P23Decode(data[offset:offset+P23Ord(data[3])])) 1519 line += ' - %s' % (P23Decode(data[offset:offset+P23Ord(data[3])]))
1422 1520
  1521 + # FILEPASS record
  1522 + if opcode == 0x2f:
  1523 + filepassFound = True
  1524 +
1423 # BOUNDSHEET record 1525 # BOUNDSHEET record
1424 if opcode == 0x85 and len(data) >= 6: 1526 if opcode == 0x85 and len(data) >= 6:
1425 dSheetType = {0: 'worksheet or dialog sheet', 1: 'Excel 4.0 macro sheet', 2: 'chart', 6: 'Visual Basic module'} 1527 dSheetType = {0: 'worksheet or dialog sheet', 1: 'Excel 4.0 macro sheet', 2: 'chart', 6: 'Visual Basic module'}
@@ -1433,7 +1535,7 @@ class cBIFF(cPluginParent): @@ -1433,7 +1535,7 @@ class cBIFF(cPluginParent):
1433 values = list(Strings(data[3:]).values()) 1535 values = list(Strings(data[3:]).values())
1434 strings = b'' 1536 strings = b''
1435 if values[0] != []: 1537 if values[0] != []:
1436 - strings += b' '.join(values[0]) 1538 + strings = values[0][0].encode()
1437 if values[1] != []: 1539 if values[1] != []:
1438 if strings != b'': 1540 if strings != b'':
1439 strings += b' ' 1541 strings += b' '
@@ -1457,9 +1559,11 @@ class cBIFF(cPluginParent): @@ -1457,9 +1559,11 @@ class cBIFF(cPluginParent):
1457 elif options.dump: 1559 elif options.dump:
1458 result = data 1560 result = data
1459 1561
1460 - if options.xlm and not macros4Found: 1562 + if options.xlm and filepassFound:
  1563 + result = ['FILEPASS record: file is password protected']
  1564 + elif options.xlm and not macros4Found:
1461 result = [] 1565 result = []
1462 1566
1463 return result 1567 return result
1464 1568
1465 -#AddPlugin(cBIFF) 1569 +AddPlugin(cBIFF)
setup.py
@@ -52,7 +52,7 @@ import os, fnmatch @@ -52,7 +52,7 @@ import os, fnmatch
52 #--- METADATA ----------------------------------------------------------------- 52 #--- METADATA -----------------------------------------------------------------
53 53
54 name = "oletools" 54 name = "oletools"
55 -version = '0.56dev3' 55 +version = '0.56dev4'
56 desc = "Python tools to analyze security characteristics of MS Office and OLE files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), for Malware Analysis and Incident Response #DFIR" 56 desc = "Python tools to analyze security characteristics of MS Office and OLE files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), for Malware Analysis and Incident Response #DFIR"
57 long_desc = open('oletools/README.rst').read() 57 long_desc = open('oletools/README.rst').read()
58 author = "Philippe Lagadec" 58 author = "Philippe Lagadec"