Commit d02c84562f0273643a123cd6e94aa4c084cd0b64
1 parent
d14635d2
pyxswf, xxxswf: fixed to run on Python 2+3 (issue #62)
Showing
2 changed files
with
22 additions
and
17 deletions
oletools/pyxswf.py
| @@ -56,11 +56,13 @@ http://www.decalage.info/python/oletools | @@ -56,11 +56,13 @@ http://www.decalage.info/python/oletools | ||
| 56 | # - improved usage display with -h | 56 | # - improved usage display with -h |
| 57 | # 2016-09-06 v0.50 PL: - updated to match the rtfobj API | 57 | # 2016-09-06 v0.50 PL: - updated to match the rtfobj API |
| 58 | # 2016-10-25 PL: - fixed print for Python 3 | 58 | # 2016-10-25 PL: - fixed print for Python 3 |
| 59 | +# 2016-11-01 PL: - replaced StringIO by BytesIO for Python 3 | ||
| 59 | 60 | ||
| 60 | __version__ = '0.50' | 61 | __version__ = '0.50' |
| 61 | 62 | ||
| 62 | #------------------------------------------------------------------------------ | 63 | #------------------------------------------------------------------------------ |
| 63 | # TODO: | 64 | # TODO: |
| 65 | +# + update xxxswf to latest version | ||
| 64 | # + add support for LZMA-compressed flash files (ZWS header) | 66 | # + add support for LZMA-compressed flash files (ZWS header) |
| 65 | # references: http://blog.malwaretracker.com/2014/01/cve-2013-5331-evaded-av-by-using.html | 67 | # references: http://blog.malwaretracker.com/2014/01/cve-2013-5331-evaded-av-by-using.html |
| 66 | # http://code.metager.de/source/xref/adobe/flash/crossbridge/tools/swf-info.py | 68 | # http://code.metager.de/source/xref/adobe/flash/crossbridge/tools/swf-info.py |
| @@ -72,7 +74,8 @@ __version__ = '0.50' | @@ -72,7 +74,8 @@ __version__ = '0.50' | ||
| 72 | 74 | ||
| 73 | #=== IMPORTS ================================================================= | 75 | #=== IMPORTS ================================================================= |
| 74 | 76 | ||
| 75 | -import optparse, sys, os, rtfobj, StringIO | 77 | +import optparse, sys, os, rtfobj |
| 78 | +from io import BytesIO | ||
| 76 | from thirdparty.xxxswf import xxxswf | 79 | from thirdparty.xxxswf import xxxswf |
| 77 | import thirdparty.olefile as olefile | 80 | import thirdparty.olefile as olefile |
| 78 | 81 | ||
| @@ -122,7 +125,7 @@ def main(): | @@ -122,7 +125,7 @@ def main(): | ||
| 122 | f = ole._open(direntry.isectStart, direntry.size) | 125 | f = ole._open(direntry.isectStart, direntry.size) |
| 123 | # check if data contains the SWF magic: FWS or CWS | 126 | # check if data contains the SWF magic: FWS or CWS |
| 124 | data = f.getvalue() | 127 | data = f.getvalue() |
| 125 | - if 'FWS' in data or 'CWS' in data: | 128 | + if b'FWS' in data or b'CWS' in data: |
| 126 | print('OLE stream: %s' % repr(direntry.name)) | 129 | print('OLE stream: %s' % repr(direntry.name)) |
| 127 | # call xxxswf to scan or extract Flash files: | 130 | # call xxxswf to scan or extract Flash files: |
| 128 | xxxswf.disneyland(f, direntry.name, options) | 131 | xxxswf.disneyland(f, direntry.name, options) |
| @@ -133,9 +136,9 @@ def main(): | @@ -133,9 +136,9 @@ def main(): | ||
| 133 | elif options.rtf: | 136 | elif options.rtf: |
| 134 | for filename in args: | 137 | for filename in args: |
| 135 | for index, orig_len, data in rtfobj.rtf_iter_objects(filename): | 138 | for index, orig_len, data in rtfobj.rtf_iter_objects(filename): |
| 136 | - if 'FWS' in data or 'CWS' in data: | 139 | + if b'FWS' in data or b'CWS' in data: |
| 137 | print('RTF embedded object size %d at index %08X' % (len(data), index)) | 140 | print('RTF embedded object size %d at index %08X' % (len(data), index)) |
| 138 | - f = StringIO.StringIO(data) | 141 | + f = BytesIO(data) |
| 139 | name = 'RTF_embedded_object_%08X' % index | 142 | name = 'RTF_embedded_object_%08X' % index |
| 140 | # call xxxswf to scan or extract Flash files: | 143 | # call xxxswf to scan or extract Flash files: |
| 141 | xxxswf.disneyland(f, name, options) | 144 | xxxswf.disneyland(f, name, options) |
oletools/thirdparty/xxxswf/xxxswf.py
| @@ -5,6 +5,8 @@ | @@ -5,6 +5,8 @@ | ||
| 5 | # - Tag Parser | 5 | # - Tag Parser |
| 6 | # - ActionScript Decompiler | 6 | # - ActionScript Decompiler |
| 7 | 7 | ||
| 8 | +# 2016-11-01 PL: - A few changes for Python 2+3 compatibility | ||
| 9 | + | ||
| 8 | import fnmatch | 10 | import fnmatch |
| 9 | import hashlib | 11 | import hashlib |
| 10 | import imp | 12 | import imp |
| @@ -14,7 +16,7 @@ import re | @@ -14,7 +16,7 @@ import re | ||
| 14 | import struct | 16 | import struct |
| 15 | import sys | 17 | import sys |
| 16 | import time | 18 | import time |
| 17 | -from StringIO import StringIO | 19 | +from io import BytesIO |
| 18 | from optparse import OptionParser | 20 | from optparse import OptionParser |
| 19 | import zlib | 21 | import zlib |
| 20 | 22 | ||
| @@ -63,14 +65,14 @@ def yaraScan(d): | @@ -63,14 +65,14 @@ def yaraScan(d): | ||
| 63 | def findSWF(d): | 65 | def findSWF(d): |
| 64 | # d = buffer of the read file | 66 | # d = buffer of the read file |
| 65 | # Search for SWF Header Sigs in files | 67 | # Search for SWF Header Sigs in files |
| 66 | - return [tmp.start() for tmp in re.finditer('CWS|FWS', d.read())] | 68 | + return [tmp.start() for tmp in re.finditer(b'CWS|FWS', d.read())] |
| 67 | 69 | ||
| 68 | def hashBuff(d): | 70 | def hashBuff(d): |
| 69 | # d = buffer of the read file | 71 | # d = buffer of the read file |
| 70 | # This function hashes the buffer | 72 | # This function hashes the buffer |
| 71 | # source: http://stackoverflow.com/q/5853830 | 73 | # source: http://stackoverflow.com/q/5853830 |
| 72 | if type(d) is str: | 74 | if type(d) is str: |
| 73 | - d = StringIO(d) | 75 | + d = BytesIO(d) |
| 74 | md5 = hashlib.md5() | 76 | md5 = hashlib.md5() |
| 75 | while True: | 77 | while True: |
| 76 | data = d.read(128) | 78 | data = d.read(128) |
| @@ -99,16 +101,16 @@ def verifySWF(f,addr): | @@ -99,16 +101,16 @@ def verifySWF(f,addr): | ||
| 99 | print(' - [ERROR] Invalid SWF Size') | 101 | print(' - [ERROR] Invalid SWF Size') |
| 100 | return None | 102 | return None |
| 101 | if type(t) is str: | 103 | if type(t) is str: |
| 102 | - f = StringIO(t) | 104 | + f = BytesIO(t) |
| 103 | # Error check for version above 20 | 105 | # Error check for version above 20 |
| 104 | if ver > 20: | 106 | if ver > 20: |
| 105 | print(' - [ERROR] Invalid SWF Version') | 107 | print(' - [ERROR] Invalid SWF Version') |
| 106 | return None | 108 | return None |
| 107 | 109 | ||
| 108 | - if 'CWS' in header: | 110 | + if b'CWS' in header: |
| 109 | try: | 111 | try: |
| 110 | f.read(3) | 112 | f.read(3) |
| 111 | - tmp = 'FWS' + f.read(5) + zlib.decompress(f.read()) | 113 | + tmp = b'FWS' + f.read(5) + zlib.decompress(f.read()) |
| 112 | print(' - CWS Header') | 114 | print(' - CWS Header') |
| 113 | return tmp | 115 | return tmp |
| 114 | 116 | ||
| @@ -117,7 +119,7 @@ def verifySWF(f,addr): | @@ -117,7 +119,7 @@ def verifySWF(f,addr): | ||
| 117 | print('- [ERROR]: Zlib decompression error. Invalid CWS SWF') | 119 | print('- [ERROR]: Zlib decompression error. Invalid CWS SWF') |
| 118 | return None | 120 | return None |
| 119 | 121 | ||
| 120 | - elif 'FWS' in header: | 122 | + elif b'FWS' in header: |
| 121 | try: | 123 | try: |
| 122 | tmp = f.read(size) | 124 | tmp = f.read(size) |
| 123 | print(' - FWS Header') | 125 | print(' - FWS Header') |
| @@ -144,20 +146,20 @@ def headerInfo(f): | @@ -144,20 +146,20 @@ def headerInfo(f): | ||
| 144 | # [HEADER] Movie width: 217.00 | 146 | # [HEADER] Movie width: 217.00 |
| 145 | # [HEADER] Movie height: 85.00 | 147 | # [HEADER] Movie height: 85.00 |
| 146 | if type(f) is str: | 148 | if type(f) is str: |
| 147 | - f = StringIO(f) | 149 | + f = BytesIO(f) |
| 148 | sig = f.read(3) | 150 | sig = f.read(3) |
| 149 | print('\t[HEADER] File header: %s' % sig) | 151 | print('\t[HEADER] File header: %s' % sig) |
| 150 | - if 'C' in sig: | 152 | + if b'C' in sig: |
| 151 | print('\t[HEADER] File is zlib compressed.') | 153 | print('\t[HEADER] File is zlib compressed.') |
| 152 | version = struct.unpack('<b', f.read(1))[0] | 154 | version = struct.unpack('<b', f.read(1))[0] |
| 153 | print('\t[HEADER] File version: %d' % version) | 155 | print('\t[HEADER] File version: %d' % version) |
| 154 | size = struct.unpack('<i', f.read(4))[0] | 156 | size = struct.unpack('<i', f.read(4))[0] |
| 155 | print('\t[HEADER] File size: %d' % size) | 157 | print('\t[HEADER] File size: %d' % size) |
| 156 | # deflate compressed SWF | 158 | # deflate compressed SWF |
| 157 | - if 'C' in sig: | 159 | + if b'C' in sig: |
| 158 | f = verifySWF(f,0) | 160 | f = verifySWF(f,0) |
| 159 | if type(f) is str: | 161 | if type(f) is str: |
| 160 | - f = StringIO(f) | 162 | + f = BytesIO(f) |
| 161 | f.seek(0, 0) | 163 | f.seek(0, 0) |
| 162 | x = f.read(8) | 164 | x = f.read(8) |
| 163 | ta = f.tell() | 165 | ta = f.tell() |
| @@ -245,10 +247,10 @@ def CWSize(f): | @@ -245,10 +247,10 @@ def CWSize(f): | ||
| 245 | 247 | ||
| 246 | def compressSWF(f): | 248 | def compressSWF(f): |
| 247 | if type(f) is str: | 249 | if type(f) is str: |
| 248 | - f = StringIO(f) | 250 | + f = BytesIO(f) |
| 249 | try: | 251 | try: |
| 250 | f.read(3) | 252 | f.read(3) |
| 251 | - tmp = 'CWS' + f.read(5) + zlib.compress(f.read()) | 253 | + tmp = b'CWS' + f.read(5) + zlib.compress(f.read()) |
| 252 | return tmp | 254 | return tmp |
| 253 | except: | 255 | except: |
| 254 | pass | 256 | pass |