Commit a962dd2032feaaca92d19b50abcef4c79f5a4180
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 | 43 | # 2016-01-13 v0.02 PL: - improved display with tablestream, added colors |
| 44 | 44 | # 2016-07-20 v0.50 SL: - added Python 3 support |
| 45 | 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 | 50 | __version__ = '0.51dev3' |
| 49 | 51 | |
| ... | ... | @@ -52,7 +54,7 @@ __version__ = '0.51dev3' |
| 52 | 54 | |
| 53 | 55 | # === IMPORTS ================================================================ |
| 54 | 56 | |
| 55 | -import sys, os | |
| 57 | +import sys, os, optparse | |
| 56 | 58 | |
| 57 | 59 | # IMPORTANT: it should be possible to run oletools directly as scripts |
| 58 | 60 | # in any directory without installing them with pip or setup.py. |
| ... | ... | @@ -68,9 +70,12 @@ if not _parent_dir in sys.path: |
| 68 | 70 | |
| 69 | 71 | from oletools.thirdparty.olefile import olefile |
| 70 | 72 | from oletools.thirdparty.tablestream import tablestream |
| 73 | +from oletools.thirdparty.xglob import xglob | |
| 71 | 74 | |
| 72 | 75 | # === CONSTANTS ============================================================== |
| 73 | 76 | |
| 77 | +BANNER = 'olemap %s - http://decalage.info/python/oletools' % __version__ | |
| 78 | + | |
| 74 | 79 | STORAGE_NAMES = { |
| 75 | 80 | olefile.STGTY_EMPTY: 'Empty', |
| 76 | 81 | olefile.STGTY_STORAGE: 'Storage', |
| ... | ... | @@ -108,34 +113,70 @@ def sid_display(sid): |
| 108 | 113 | # === MAIN =================================================================== |
| 109 | 114 | |
| 110 | 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 | 140 | # print banner with version |
| 112 | 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 | 181 | if __name__ == '__main__': |
| 141 | 182 | main() | ... | ... |