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,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() |