def run(self): super(Shellcode, self).run() if self.args is None: return if not __sessions__.is_set(): self.log("error", "No session opened") return collection = [ { "description": "FS:[30h] shellcode", "patterns": [ b"\x64\xa1\x30\x00|\x64\x8b\x0d\x30|\x64\x8b\x0d\x30|\x64\x8b\x15\x30|\x64\x8b\x35\x30|\x64\x8b\x3d\x30|\x6a\x30.\x64\x8b|\x33..\xb3\x64\x8b", "64a13000|648b0d30|648b0d30|648b1530|648b3530|648b3d30|6a30..648b|33....b3648b", ], }, { "description": "FS:[00h] shellcode", "patterns": [ b"\x64\x8b\x1d|\x64\xa1\x00|\x64\x8b\x0d|\x64\x8b\x15|\x64\x8b\x35|\x64\x8b\x3d", "648b1d00|64a10000|648b0d00|648b1500|648b3500|648b3d00", ], }, { "description": "API hashing", "patterns": [b"\x74.\xc1.\x0d\x03|\x74.\xc1.\x07\x03", "74..c1..0d03|74..c1..0703"], }, {"description": "PUSH DWORD[]/CALL[]", "patterns": [b"\x00\xff\x75\x00\xff\x55", "00ff7500ff55"]}, { "description": "FLDZ/FSTENV [esp-12]", "patterns": [b"\x00\xd9\x00\xee\x00\xd9\x74\x24\x00\xf4\x00\x00", "00d900ee00d9742400f40000"], }, { "description": "CALL next/POP", "patterns": [ b"\x00\xe8\x00\x00\x00\x00(\x58|\x59|\x5a|\x5b|\x5e|\x5f|\x5d)\x00\x00", "00e800000000(58|59|5a|5b|5e|5f|5d)0000", ], }, { "description": "Function prolog", "patterns": [ b"\x55\x8b\x00\xec\x83\x00\xc4|\x55\x8b\x0ec\x81\x00\xec|\x55\x8b\x00\xec\x8b|\x55\x8b\x00\xec\xe8|\x55\x8b\x00\xec\xe9", "558b00ec8300c4|558b0ec8100ec|558b00ec8b|558b00ece8|558b00ece9", ], }, ] self.log("info", "Searching for known shellcode patterns...") for entry in collection: for pattern in entry["patterns"]: match = re.search(pattern, __sessions__.current.file.data) if match: offset = match.start() self.log("info", "{0} pattern matched at offset {1}".format(entry["description"], offset)) self.log("", cyan(hexdump(__sessions__.current.file.data[offset:], maxlines=15)))
def view(self): offset_input = input("Enter numeric offset: ") self.log('', offset_input) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input:], maxlines=32))) self.log('', offset_input + 512) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 512:], maxlines=32))) self.log('', offset_input + 1024) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 1024:], maxlines=32))) self.log('', offset_input + 1536) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 1536:], maxlines=32))) self.log('', offset_input + 2048) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 2048:], maxlines=32))) self.log('', offset_input + 2560) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 2560:], maxlines=32))) self.log('', offset_input + 3072) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 3072:], maxlines=32))) self.log('', offset_input + 3584) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset_input + 3584:], maxlines=32))) self.log('', offset_input + 4096)
def view(self): offset_input = input("Enter numeric offset: ") self.log('',offset_input) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input:], maxlines=32))) self.log('',offset_input+512) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+512:], maxlines=32))) self.log('',offset_input+1024) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+1024:], maxlines=32))) self.log('',offset_input+1536) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+1536:], maxlines=32))) self.log('',offset_input+2048) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+2048:], maxlines=32))) self.log('',offset_input+2560) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+2560:], maxlines=32))) self.log('',offset_input+3072) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+3072:], maxlines=32))) self.log('',offset_input+3584) self.log('', cyan(hexdump(__sessions__.current.file.data[offset_input+3584:], maxlines=32))) self.log('',offset_input+4096)
def decompress(self, dump_dir): # Check if the file type is right. # TODO: this might be a bit hacky, need to verify whether malformed # Flash exploit would get a different file type. if 'Flash' not in __sessions__.current.file.type: self.log( 'error', "The opened file doesn't appear to be a valid SWF object") return # Retrieve key information from the opened SWF file. header, version, size, data = self.parse_swf() # Decompressed data. decompressed = None # Check if the file is already a decompressed Flash object. if header == 'FWS': self.log('info', "The opened file doesn't appear to be compressed") return # Check if the file is compressed with zlib. elif header == 'CWS': self.log('info', "The opened file appears to be compressed with Zlib") # Open an handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + zlib.decompress( compressed.read()) # Check if the file is compressed with lzma. elif header == 'ZWS': self.log('info', "The opened file appears to be compressed with Lzma") # We need an third party library to decompress this. if not HAVE_PYLZMA: self.log( 'error', "Missing dependency, please install pylzma (`pip install pylzma`)" ) return # Open and handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress with pylzma and reconstruct the Flash object. ## ZWS(LZMA) ## | 4 bytes | 4 bytes | 4 bytes | 5 bytes | n bytes | 6 bytes | ## | 'ZWS'+version | scriptLen | compressedLen | LZMA props | LZMA data | LZMA end marker | decompressed = 'FWS' + compressed.read(5) compressed.read(4) # skip compressedLen decompressed += pylzma.decompress(compressed.read()) # If we obtained some decompressed data, we print it and eventually # dump it to file. if decompressed: # Print the decompressed data # TODO: this prints too much, need to find a better wayto display # this. Paginate? self.log('', cyan(hexdump(decompressed))) if dump_dir: # Dump the decompressed SWF file to the specified directory # or to the default temporary one. dump_path = os.path.join( dump_dir, '{0}.swf'.format(get_md5(decompressed))) with open(dump_path, 'wb') as handle: handle.write(decompressed) self.log('info', "Flash object dumped at {0}".format(dump_path)) # Directly open a session on the dumped Flash object. __sessions__.new(dump_path)
def run(self): super(Shellcode, self).run() if self.args is None: return if not __sessions__.is_set(): self.log('error', "No session opened") return collection = [ { 'description': 'FS:[30h] shellcode', 'patterns': [ b'\x64\xa1\x30\x00|\x64\x8b\x0d\x30|\x64\x8b\x0d\x30|\x64\x8b\x15\x30|\x64\x8b\x35\x30|\x64\x8b\x3d\x30|\x6a\x30.\x64\x8b|\x33..\xb3\x64\x8b', '64a13000|648b0d30|648b0d30|648b1530|648b3530|648b3d30|6a30..648b|33....b3648b' ] }, { 'description': 'FS:[00h] shellcode', 'patterns': [ b'\x64\x8b\x1d|\x64\xa1\x00|\x64\x8b\x0d|\x64\x8b\x15|\x64\x8b\x35|\x64\x8b\x3d', '648b1d00|64a10000|648b0d00|648b1500|648b3500|648b3d00' ] }, { 'description': 'API hashing', 'patterns': [ b'\x74.\xc1.\x0d\x03|\x74.\xc1.\x07\x03', '74..c1..0d03|74..c1..0703' ] }, { 'description': 'PUSH DWORD[]/CALL[]', 'patterns': [b'\x00\xff\x75\x00\xff\x55', '00ff7500ff55'] }, { 'description': 'FLDZ/FSTENV [esp-12]', 'patterns': [ b'\x00\xd9\x00\xee\x00\xd9\x74\x24\x00\xf4\x00\x00', '00d900ee00d9742400f40000' ] }, { 'description': 'CALL next/POP', 'patterns': [ b'\x00\xe8\x00\x00\x00\x00(\x58|\x59|\x5a|\x5b|\x5e|\x5f|\x5d)\x00\x00', '00e800000000(58|59|5a|5b|5e|5f|5d)0000' ] }, { 'description': 'Function prolog', 'patterns': [ b'\x55\x8b\x00\xec\x83\x00\xc4|\x55\x8b\x0ec\x81\x00\xec|\x55\x8b\x00\xec\x8b|\x55\x8b\x00\xec\xe8|\x55\x8b\x00\xec\xe9', '558b00ec8300c4|558b0ec8100ec|558b00ec8b|558b00ece8|558b00ece9' ] }, ] self.log('info', "Searching for known shellcode patterns...") for entry in collection: for pattern in entry['patterns']: match = re.search(pattern, __sessions__.current.file.data) if match: offset = match.start() self.log( 'info', "{0} pattern matched at offset {1}".format( entry['description'], offset)) self.log( '', cyan( hexdump(__sessions__.current.file.data[offset:], maxlines=15)))
def decompress(self, dump_dir): # Check if the file type is right. # TODO: this might be a bit hacky, need to verify whether malformed # Flash exploit would get a different file type. if 'Flash' not in __sessions__.current.file.type: self.log('error', "The opened file doesn't appear to be a valid SWF object") return # Retrieve key information from the opened SWF file. header, version, size, data = self.parse_swf() # Decompressed data. decompressed = None # Check if the file is already a decompressed Flash object. if header == 'FWS': self.log('info', "The opened file doesn't appear to be compressed") return # Check if the file is compressed with zlib. elif header == 'CWS': self.log('info', "The opened file appears to be compressed with Zlib") # Open an handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + zlib.decompress(compressed.read()) # Check if the file is compressed with lzma. elif header == 'ZWS': self.log('info', "The opened file appears to be compressed with Lzma") # We need an third party library to decompress this. if not HAVE_PYLZMA: self.log('error', "Missing dependency, please install pylzma (`pip install pylzma`)") return # Open and handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress with pylzma and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + pylzma.decompress(compressed.read()) # If we obtained some decompressed data, we print it and eventually # dump it to file. if decompressed: # Print the decompressed data # TODO: this prints too much, need to find a better wayto display # this. Paginate? self.log('', cyan(hexdump(decompressed))) if dump_dir: # Dump the decompressed SWF file to the specified directory # or to the default temporary one. dump_path = os.path.join(dump_dir, '{0}.swf'.format(get_md5(decompressed))) with open(dump_path, 'wb') as handle: handle.write(decompressed) self.log('info', "Flash object dumped at {0}".format(dump_path)) # Directly open a session on the dumped Flash object. __sessions__.new(dump_path)
def run(self): super(Shellcode, self).run() if self.args is None: return if not __sessions__.is_set(): self.log('error', "No open session") return collection = [ { 'description': 'FS:[30h] shellcode', 'patterns': [ b'\x64\xa1\x30\x00|\x64\x8b\x0d\x30|\x64\x8b\x0d\x30|\x64\x8b\x15\x30|\x64\x8b\x35\x30|\x64\x8b\x3d\x30|\x6a\x30.\x64\x8b|\x33..\xb3\x64\x8b', '64a13000|648b0d30|648b0d30|648b1530|648b3530|648b3d30|6a30..648b|33....b3648b' ] }, { 'description': 'FS:[00h] shellcode', 'patterns': [ b'\x64\x8b\x1d|\x64\xa1\x00|\x64\x8b\x0d|\x64\x8b\x15|\x64\x8b\x35|\x64\x8b\x3d', '648b1d00|64a10000|648b0d00|648b1500|648b3500|648b3d00' ] }, { 'description': 'API hashing', 'patterns': [ b'\x74.\xc1.\x0d\x03|\x74.\xc1.\x07\x03', '74..c1..0d03|74..c1..0703' ] }, { 'description': 'PUSH DWORD[]/CALL[]', 'patterns': [ b'\x00\xff\x75\x00\xff\x55', '00ff7500ff55' ] }, { 'description': 'FLDZ/FSTENV [esp-12]', 'patterns': [ b'\x00\xd9\x00\xee\x00\xd9\x74\x24\x00\xf4\x00\x00', '00d900ee00d9742400f40000' ] }, { 'description': 'CALL next/POP', 'patterns': [ b'\x00\xe8\x00\x00\x00\x00(\x58|\x59|\x5a|\x5b|\x5e|\x5f|\x5d)\x00\x00', '00e800000000(58|59|5a|5b|5e|5f|5d)0000' ] }, { 'description': 'Function prolog', 'patterns': [ b'\x55\x8b\x00\xec\x83\x00\xc4|\x55\x8b\x0ec\x81\x00\xec|\x55\x8b\x00\xec\x8b|\x55\x8b\x00\xec\xe8|\x55\x8b\x00\xec\xe9', '558b00ec8300c4|558b0ec8100ec|558b00ec8b|558b00ece8|558b00ece9' ] }, ] self.log('info', "Searching for known shellcode patterns...") for entry in collection: for pattern in entry['patterns']: match = re.search(pattern, __sessions__.current.file.data) if match: offset = match.start() self.log('info', "{0} pattern matched at offset {1}".format(entry['description'], offset)) self.log('', cyan(hexdump(__sessions__.current.file.data[offset:], maxlines=15)))
def decompress(self): def usage(): print("usage: swf decompress [-d=folder]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--dump (-d)\tDump the SWF object to the destination folder (default is /tmp)") print("") try: opts, argv = getopt.getopt(self.args[1:], 'hd', ['help', 'dump']) except getopt.GetoptError as e: print(e) usage() return arg_dump = None for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-d', '--dump'): if value: arg_dump = value else: arg_dump = tempfile.gettempdir() if not __sessions__.is_set(): print_error("No session opened") return # Check if the file type is right. # TODO: this might be a bit hacky, need to verify whether malformed # Flash exploit would get a different file type. if not 'Flash' in __sessions__.current.file.type: print_error("The opened file doesn't appear to be a valid SWF object") return # Retrieve key information from the opened SWF file. header, version, size, data = self.parse_swf() # Decompressed data. decompressed = None # Check if the file is already a decompressed Flash object. if header == 'FWS': print_info("The opened file doesn't appear to be compressed") return # Check if the file is compressed with zlib. elif header == 'CWS': print_info("The opened file appears to be compressed with Zlib") # Open an handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + zlib.decompress(compressed.read()) # Check if the file is compressed with lzma. elif header == 'ZWS': print_info("The opened file appears to be compressed with Lzma") # We need an third party library to decompress this. if not HAVE_PYLZMA: print_error("Missing dependency, please install pylzma (`pip install pylzma`)") return # Open and handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress with pylzma and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + pylzma.decompress(compressed.read()) # If we obtained some decompressed data, we print it and eventually # dump it to file. if decompressed: # Print the decompressed data # TODO: this prints too much, need to find a better wayto display # this. Paginate? print(cyan(hexdump(decompressed))) if arg_dump: # Dump the decompressed SWF file to the specified directory # or to the default temporary one. dump_path = os.path.join(arg_dump, '{0}.swf'.format(get_md5(decompressed))) with open(dump_path, 'wb') as handle: handle.write(decompressed) print_info("Flash object dumped at {0}".format(dump_path)) # Directly open a session on the dumped Flash object. __sessions__.new(dump_path)
def decompress(self): def usage(): print("usage: swf decompress [-d=folder]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print( "\t--dump (-d)\tDump the SWF object to the destination folder (default is /tmp)" ) print("") try: opts, argv = getopt.getopt(self.args[1:], 'hd', ['help', 'dump']) except getopt.GetoptError as e: print(e) usage() return arg_dump = None for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-d', '--dump'): if value: arg_dump = value else: arg_dump = tempfile.gettempdir() if not __sessions__.is_set(): print_error("No session opened") return # Check if the file type is right. # TODO: this might be a bit hacky, need to verify whether malformed # Flash exploit would get a different file type. if not 'Flash' in __sessions__.current.file.type: print_error( "The opened file doesn't appear to be a valid SWF object") return # Retrieve key information from the opened SWF file. header, version, size, data = self.parse_swf() # Decompressed data. decompressed = None # Check if the file is already a decompressed Flash object. if header == 'FWS': print_info("The opened file doesn't appear to be compressed") return # Check if the file is compressed with zlib. elif header == 'CWS': print_info("The opened file appears to be compressed with Zlib") # Open an handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + zlib.decompress( compressed.read()) # Check if the file is compressed with lzma. elif header == 'ZWS': print_info("The opened file appears to be compressed with Lzma") # We need an third party library to decompress this. if not HAVE_PYLZMA: print_error( "Missing dependency, please install pylzma (`pip install pylzma`)" ) return # Open and handle on the compressed data. compressed = StringIO(data) # Skip the header. compressed.read(3) # Decompress with pylzma and reconstruct the Flash object. decompressed = 'FWS' + compressed.read(5) + pylzma.decompress( compressed.read()) # If we obtained some decompressed data, we print it and eventually # dump it to file. if decompressed: # Print the decompressed data # TODO: this prints too much, need to find a better wayto display # this. Paginate? print(cyan(hexdump(decompressed))) if arg_dump: # Dump the decompressed SWF file to the specified directory # or to the default temporary one. dump_path = os.path.join( arg_dump, '{0}.swf'.format(get_md5(decompressed))) with open(dump_path, 'wb') as handle: handle.write(decompressed) print_info("Flash object dumped at {0}".format(dump_path)) # Directly open a session on the dumped Flash object. __sessions__.new(dump_path)
def decompress(self, dump_dir): # Check if the file type is right. # TODO: this might be a bit hacky, need to verify whether malformed # Flash exploit would get a different file type. if 'Flash' not in __sessions__.current.file.type: self.log('error', "The opened file doesn't appear to be a valid SWF object") return # Retrieve key information from the opened SWF file. header, version, size, data = self.parse_swf() # Decompressed data. decompressed = None compressed = True # Check if the file is already a decompressed Flash object. if header == b'FWS': self.log('info', "The opened file doesn't appear to be compressed") decompressed = data compressed = False # Check if the file is compressed with zlib. elif header == b'CWS': self.log('info', "The opened file appears to be compressed with Zlib") # Open an handle on the compressed data. compressed = BytesIO(data) # Skip the header. compressed.read(3) # Decompress and reconstruct the Flash object. decompressed = b'FWS' + compressed.read(5) + zlib.decompress(compressed.read()) # Check if the file is compressed with lzma. elif header == b'ZWS': self.log('info', "The opened file appears to be compressed with Lzma") # We need an third party library to decompress this. if not HAVE_PYLZMA: self.log('error', "Missing dependency, please install pylzma (`pip install pylzma`)") return # Open and handle on the compressed data. compressed = BytesIO(data) # Skip the header. compressed.read(3) # Decompress with pylzma and reconstruct the Flash object. # # ZWS(LZMA) # # | 4 bytes | 4 bytes | 4 bytes | 5 bytes | n bytes | 6 bytes | # # | 'ZWS'+version | scriptLen | compressedLen | LZMA props | LZMA data | LZMA end marker | decompressed = b'FWS' + compressed.read(5) compressed.read(4) # skip compressedLen decompressed += pylzma.decompress(compressed.read()) # If we obtained some decompressed data, we print it and eventually # dump it to file. if decompressed: # Print the decompressed data # TODO: this prints too much, need to find a better wayto display # this. Paginate? self.log('', cyan(hexdump(decompressed))) if compressed and dump_dir: # Dump the decompressed SWF file to the specified directory # or to the default temporary one. dump_path = os.path.join(dump_dir, '{0}.swf'.format(get_md5(decompressed))) with open(dump_path, 'wb') as handle: handle.write(decompressed) self.log('info', "Flash object dumped at {0}".format(dump_path)) # Set the parent-child relation between CWS-FWS this_parent = __sessions__.current.file.sha256 # Directly open a session on the dumped Flash object. __sessions__.new(dump_path) db = Database() # Make sure parents is in database if not db.find(key='sha256', value=this_parent): self.log('error', "the parent file is not found in the database. ") else: db.add_parent(__sessions__.current.file.sha256, this_parent)