Commit d02c84562f0273643a123cd6e94aa4c084cd0b64

Authored by decalage2
1 parent d14635d2

pyxswf, xxxswf: fixed to run on Python 2+3 (issue #62)

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