Commit a962dd2032feaaca92d19b50abcef4c79f5a4180

Authored by decalage2
1 parent abece8c5

olemap: added optparse, added support for zip files and wildcards

Showing 1 changed file with 68 additions and 27 deletions
oletools/olemap.py
@@ -43,7 +43,9 @@ http://www.decalage.info/python/oletools @@ -43,7 +43,9 @@ http://www.decalage.info/python/oletools
43 # 2016-01-13 v0.02 PL: - improved display with tablestream, added colors 43 # 2016-01-13 v0.02 PL: - improved display with tablestream, added colors
44 # 2016-07-20 v0.50 SL: - added Python 3 support 44 # 2016-07-20 v0.50 SL: - added Python 3 support
45 # 2016-09-05 PL: - added main entry point for setup.py 45 # 2016-09-05 PL: - added main entry point for setup.py
46 -# 2017-03-20 v0.51 PL: - fixed absolute imports 46 +# 2017-03-20 v0.51 PL: - fixed absolute imports, added optparse
  47 +# - added support for zip files and wildcards
  48 +
47 49
48 __version__ = '0.51dev3' 50 __version__ = '0.51dev3'
49 51
@@ -52,7 +54,7 @@ __version__ = '0.51dev3' @@ -52,7 +54,7 @@ __version__ = '0.51dev3'
52 54
53 # === IMPORTS ================================================================ 55 # === IMPORTS ================================================================
54 56
55 -import sys, os 57 +import sys, os, optparse
56 58
57 # IMPORTANT: it should be possible to run oletools directly as scripts 59 # IMPORTANT: it should be possible to run oletools directly as scripts
58 # in any directory without installing them with pip or setup.py. 60 # in any directory without installing them with pip or setup.py.
@@ -68,9 +70,12 @@ if not _parent_dir in sys.path: @@ -68,9 +70,12 @@ if not _parent_dir in sys.path:
68 70
69 from oletools.thirdparty.olefile import olefile 71 from oletools.thirdparty.olefile import olefile
70 from oletools.thirdparty.tablestream import tablestream 72 from oletools.thirdparty.tablestream import tablestream
  73 +from oletools.thirdparty.xglob import xglob
71 74
72 # === CONSTANTS ============================================================== 75 # === CONSTANTS ==============================================================
73 76
  77 +BANNER = 'olemap %s - http://decalage.info/python/oletools' % __version__
  78 +
74 STORAGE_NAMES = { 79 STORAGE_NAMES = {
75 olefile.STGTY_EMPTY: 'Empty', 80 olefile.STGTY_EMPTY: 'Empty',
76 olefile.STGTY_STORAGE: 'Storage', 81 olefile.STGTY_STORAGE: 'Storage',
@@ -108,34 +113,70 @@ def sid_display(sid): @@ -108,34 +113,70 @@ def sid_display(sid):
108 # === MAIN =================================================================== 113 # === MAIN ===================================================================
109 114
110 def main(): 115 def main():
  116 + usage = 'usage: olemap [options] <filename> [filename2 ...]'
  117 + parser = optparse.OptionParser(usage=usage)
  118 + parser.add_option("-r", action="store_true", dest="recursive",
  119 + help='find files recursively in subdirectories.')
  120 + parser.add_option("-z", "--zip", dest='zip_password', type='str', default=None,
  121 + help='if the file is a zip archive, open all files from it, using the provided password (requires Python 2.6+)')
  122 + parser.add_option("-f", "--zipfname", dest='zip_fname', type='str', default='*',
  123 + help='if the file is a zip archive, file(s) to be opened within the zip. Wildcards * and ? are supported. (default:*)')
  124 + # parser.add_option('-l', '--loglevel', dest="loglevel", action="store", default=DEFAULT_LOG_LEVEL,
  125 + # help="logging level debug/info/warning/error/critical (default=%default)")
  126 +
  127 + # TODO: add logfile option
  128 +
  129 + (options, args) = parser.parse_args()
  130 +
  131 + # Print help if no arguments are passed
  132 + if len(args) == 0:
  133 + print(BANNER)
  134 + print(__doc__)
  135 + parser.print_help()
  136 + sys.exit()
  137 +
  138 + # print banner with version
  139 + print(BANNER)
111 # print banner with version 140 # print banner with version
112 print('olemap %s - http://decalage.info/python/oletools' % __version__) 141 print('olemap %s - http://decalage.info/python/oletools' % __version__)
113 142
114 - fname = sys.argv[1]  
115 - ole = olefile.OleFileIO(fname)  
116 -  
117 - print('FAT:')  
118 - t = tablestream.TableStream([8, 12, 8, 8], header_row=['Sector #', 'Type', 'Offset', 'Next #'])  
119 - for i in range(ole.nb_sect):  
120 - fat_value = ole.fat[i]  
121 - fat_type = FAT_TYPES.get(fat_value, '<Data>')  
122 - color_type = FAT_COLORS.get(fat_value, FAT_COLORS['default'])  
123 - # compute offset based on sector size:  
124 - offset = ole.sectorsize * (i+1)  
125 - # print '%8X: %-12s offset=%08X next=%8X' % (i, fat_type, 0, fat_value)  
126 - t.write_row(['%8X' % i, fat_type, '%08X' % offset, '%8X' % fat_value],  
127 - colors=[None, color_type, None, None])  
128 - print('')  
129 -  
130 - print('MiniFAT:')  
131 - # load MiniFAT if it wasn't already done:  
132 - ole.loadminifat()  
133 - for i in range(len(ole.minifat)):  
134 - fat_value = ole.minifat[i]  
135 - fat_type = FAT_TYPES.get(fat_value, 'Data')  
136 - print('%8X: %-12s offset=%08X next=%8X' % (i, fat_type, 0, fat_value))  
137 -  
138 - ole.close() 143 + for container, filename, data in xglob.iter_files(args, recursive=options.recursive,
  144 + zip_password=options.zip_password, zip_fname=options.zip_fname):
  145 + # TODO: handle xglob errors
  146 + # ignore directory names stored in zip files:
  147 + if container and filename.endswith('/'):
  148 + continue
  149 + full_name = '%s in %s' % (filename, container) if container else filename
  150 + print("-" * 79)
  151 + print('FILE: %s\n' % full_name)
  152 + if data is not None:
  153 + # data extracted from zip file
  154 + ole = olefile.OleFileIO(data)
  155 + else:
  156 + # normal filename
  157 + ole = olefile.OleFileIO(filename)
  158 + print('FAT:')
  159 + t = tablestream.TableStream([8, 12, 8, 8], header_row=['Sector #', 'Type', 'Offset', 'Next #'])
  160 + for i in range(ole.nb_sect):
  161 + fat_value = ole.fat[i]
  162 + fat_type = FAT_TYPES.get(fat_value, '<Data>')
  163 + color_type = FAT_COLORS.get(fat_value, FAT_COLORS['default'])
  164 + # compute offset based on sector size:
  165 + offset = ole.sectorsize * (i+1)
  166 + # print '%8X: %-12s offset=%08X next=%8X' % (i, fat_type, 0, fat_value)
  167 + t.write_row(['%8X' % i, fat_type, '%08X' % offset, '%8X' % fat_value],
  168 + colors=[None, color_type, None, None])
  169 + print('')
  170 +
  171 + print('MiniFAT:')
  172 + # load MiniFAT if it wasn't already done:
  173 + ole.loadminifat()
  174 + for i in range(len(ole.minifat)):
  175 + fat_value = ole.minifat[i]
  176 + fat_type = FAT_TYPES.get(fat_value, 'Data')
  177 + print('%8X: %-12s offset=%08X next=%8X' % (i, fat_type, 0, fat_value))
  178 +
  179 + ole.close()
139 180
140 if __name__ == '__main__': 181 if __name__ == '__main__':
141 main() 182 main()