PyMISP/pymisp/tools/fileobject.py

82 lines
2.9 KiB
Python
Raw Normal View History

2017-07-21 18:47:10 +02:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2017-08-31 10:40:18 +02:00
from .abstractgenerator import AbstractMISPObjectGenerator
2017-07-21 18:47:10 +02:00
import os
from io import BytesIO
from hashlib import md5, sha1, sha256, sha512
import math
from collections import Counter
import warnings
2017-07-21 18:47:10 +02:00
try:
import pydeep
HAS_PYDEEP = True
except ImportError:
HAS_PYDEEP = False
try:
import magic
HAS_MAGIC = True
except ImportError:
HAS_MAGIC = False
2017-08-28 19:01:53 +02:00
class FileObject(AbstractMISPObjectGenerator):
2017-07-21 18:47:10 +02:00
def __init__(self, filepath=None, pseudofile=None, filename=None):
if not HAS_PYDEEP:
warnings.warn("Please install pydeep: pip install git+https://github.com/kbandla/pydeep.git")
2017-07-21 18:47:10 +02:00
if not HAS_MAGIC:
warnings.warn("Please install python-magic: pip install python-magic.")
2017-07-21 18:47:10 +02:00
if filepath:
self.filepath = filepath
self.filename = os.path.basename(self.filepath)
with open(filepath, 'rb') as f:
self.__pseudofile = BytesIO(f.read())
2017-07-21 18:47:10 +02:00
elif pseudofile and isinstance(pseudofile, BytesIO):
# WARNING: lief.parse requires a path
self.filepath = None
self.__pseudofile = pseudofile
2017-07-21 18:47:10 +02:00
self.filename = filename
else:
raise Exception('File buffer (BytesIO) or a path is required.')
2017-08-25 09:45:56 +02:00
# PY3 way:
# super().__init__('file')
super(FileObject, self).__init__('file')
self.__data = self.__pseudofile.getvalue()
2017-07-21 18:47:10 +02:00
self.generate_attributes()
# Mark as non_jsonable because we need to add them manually
self.update_not_jsonable('ObjectReference')
2017-07-21 18:47:10 +02:00
def generate_attributes(self):
2017-08-28 19:01:53 +02:00
self.add_attribute('filename', value=self.filename)
size = self.add_attribute('size-in-bytes', value=len(self.__data))
if int(size.value) > 0:
self.add_attribute('entropy', value=self.__entropy_H(self.__data))
self.add_attribute('md5', value=md5(self.__data).hexdigest())
self.add_attribute('sha1', value=sha1(self.__data).hexdigest())
self.add_attribute('sha256', value=sha256(self.__data).hexdigest())
self.add_attribute('sha512', value=sha512(self.__data).hexdigest())
self.add_attribute('malware-sample', value=self.filename, data=self.__pseudofile)
if HAS_MAGIC:
self.add_attribute('mimetype', value=magic.from_buffer(self.__data))
if HAS_PYDEEP:
self.add_attribute('ssdeep', value=pydeep.hash_buf(self.__data).decode())
2017-07-21 18:47:10 +02:00
def __entropy_H(self, data):
"""Calculate the entropy of a chunk of data."""
# NOTE: copy of the entropy function from pefile
if len(data) == 0:
return 0.0
occurences = Counter(bytearray(data))
entropy = 0
for x in occurences.values():
p_x = float(x) / len(data)
entropy -= p_x * math.log(p_x, 2)
return entropy