Beispiel #1
0
    def new(self, path=None, misp_event=None):
        if not path and not misp_event:
            print_error("You have to open a session on a path or on a misp event.")
            return

        session = Session()

        total = len(self.sessions)
        session.id = total + 1

        if path:
            if self.is_set() and misp_event is None and self.current.misp_event:
                session.misp_event = self.current.misp_event

            # Open a section on the given file.
            session.file = File(path)
            # Try to lookup the file in the database. If it is already present
            # we get its database ID, file name, and tags.
            row = Database().find(key='sha256', value=session.file.sha256)
            if row:
                session.file.id = row[0].id
                session.file.name = row[0].name
                session.file.tags = ', '.join(tag.to_dict()['tag'] for tag in row[0].tag)

                if row[0].parent:
                    session.file.parent = '{0} - {1}'.format(row[0].parent.name, row[0].parent.sha256)
                session.file.children = Database().get_children(row[0].id)

            print_info("Session opened on {0}".format(path))

        if misp_event:
            if self.is_set() and path is None and self.current.file:
                session.file = self.current.file
            refresh = False
            if (self.current is not None and self.current.misp_event is not None and
                    self.current.misp_event.event.id is not None and
                    self.current.misp_event.event.id == misp_event.event.id):
                refresh = True
            session.misp_event = misp_event
            if refresh:
                print_info("Session on MISP event {0} refreshed.".format(misp_event.event.id))
            elif not misp_event.event.id:
                print_info("Session opened on a new local MISP event.")
            else:
                print_info("Session opened on MISP event {0}.".format(misp_event.event.id))

        if session.file:
            # Loop through all existing sessions and check whether there's another
            # session open on the same file and delete it. This is to avoid
            # duplicates in sessions.
            # NOTE: in the future we might want to remove this if sessions have
            # unique attributes (for example, an history just for each of them).
            for entry in self.sessions:
                if entry.file and entry.file.sha256 == session.file.sha256:
                    self.sessions.remove(entry)

        # Add new session to the list.
        self.sessions.append(session)
        # Mark the new session as the current one.
        self.current = session
Beispiel #2
0
def store_sample(file_object):
    sha256 = file_object.sha256

    if not sha256:
        print_error("No hash")
        return None

    folder = os.path.join(
        __project__.get_path(),
        'binaries',
        sha256[0],
        sha256[1],
        sha256[2],
        sha256[3]
    )

    if not os.path.exists(folder):
        os.makedirs(folder, 0o750)

    file_path = os.path.join(folder, sha256)

    if not os.path.exists(file_path):
        with open(file_path, 'wb') as stored:
            for chunk in file_object.get_chunks():
                stored.write(chunk)
    else:
        print_warning("File exists already")
        return None

    return file_path
Beispiel #3
0
    def add_note(self, sha256, title, body):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode("Non ASCII character(s) in Notes not supported on Python2.\n"
                                                "Please use Python >= 3.4".format(err), "error")

        malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
        if not malware_entry:
            return

        try:
            new_note = Note(title, body)
            malware_entry.note.append(new_note)
            session.commit()
            self.added_ids.setdefault("note", []).append(new_note.id)
        except SQLAlchemyError as e:
            print_error("Unable to add note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #4
0
def store_sample(file_object):
    sha256 = file_object.sha256

    if not sha256:
        print_error("No hash")
        return None

    folder = os.path.join(
        __project__.get_path(),
        'binaries',
        sha256[0],
        sha256[1],
        sha256[2],
        sha256[3]
    )

    if not os.path.exists(folder):
        os.makedirs(folder, 0o750)

    file_path = os.path.join(folder, sha256)

    if not os.path.exists(file_path):
        with open(file_path, 'wb') as stored:
            for chunk in file_object.get_chunks():
                stored.write(chunk)
    else:
        print_warning("File exists already")
        return None

    return file_path
Beispiel #5
0
def logo():
    print("""         _
        (_)
   _   _ _ ____  _____  ____
  | | | | |  _ \| ___ |/ ___)
   \ V /| | |_| | ____| |
    \_/ |_|  __/|_____)_| v{}
          |_|
    """.format(__version__))

    db = Database()
    count = db.get_sample_count()

    try:
        db.find('all')
    except Exception:
        print_error("You need to update your Viper database. Run 'python update.py -d'")
        sys.exit()

    if __project__.name:
        name = __project__.name
    else:
        name = 'default'

    print(magenta("You have " + bold(count)) +
          magenta(" files in your " + bold(name)) +
          magenta(" repository"))
    def add_malwarevt(self, sha256, scan_id, permalink, resource, verbose_msg,
                      scan_date, positives, total):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode(
                    "Non ASCII character(s) in Notes not supported on Python2.\n"
                    "Please use Python >= 3.4".format(err), "error")

        malware_entry = session.query(Malware).filter(
            Malware.sha256 == sha256).first()
        if not malware_entry:
            return False

        try:
            new_malwarevt = MalwareVT(scan_id, permalink, resource,
                                      verbose_msg, scan_date, positives, total)
            malware_entry.malwarevt.append(new_malwarevt)
            session.commit()
            self.added_ids.setdefault("malwarevt", []).append(new_malwarevt.id)
        except SQLAlchemyError as e:
            print_error("Unable to add virus total register: {0}".format(e))
            session.rollback()
    def add_malwareanalysismacros(self, sha256, type, keyword, description):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode(
                    "Non ASCII character(s) in Notes not supported on Python2.\n"
                    "Please use Python >= 3.4".format(err), "error")

        malware_entry = session.query(Malware).filter(
            Malware.sha256 == sha256).first()
        if not malware_entry:
            return False

        try:
            new_malwareanalysismacros = MalwareAnalysisMacros(
                type, keyword, description)
            malware_entry.malwareanalysismacros.append(
                new_malwareanalysismacros)
            session.commit()
            self.added_ids.setdefault("malwareanalysismacros",
                                      []).append(new_malwareanalysismacros.id)
        except SQLAlchemyError as e:
            print_error("Unable to add malware analysis macros: {0}".format(e))
            session.rollback()
    def add_malwarevtsc(self, sha256, antivirus, detected, version, result,
                        update):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode(
                    "Non ASCII character(s) in Notes not supported on Python2.\n"
                    "Please use Python >= 3.4".format(err), "error")

        malware_entry = session.query(Malware).filter(
            Malware.sha256 == sha256).first()
        if not malware_entry:
            return False

        try:
            new_malwarevtsc = MalwareVTSc(antivirus, detected, version, result,
                                          update)
            malware_entry.malwarevtsc.append(new_malwarevtsc)
            session.commit()
            self.added_ids.setdefault("malwarevtsc",
                                      []).append(new_malwarevtsc.id)
        except SQLAlchemyError as e:
            print_error("Unable to add malware scan: {0}".format(e))
            session.rollback()
Beispiel #9
0
    def delete_tag(self, tag_name, sha256):
        session = self.Session()

        try:
            # First remove the tag from the sample
            malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
            tag = session.query(Tag).filter(Tag.tag == tag_name).first()
            try:
                malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
                malware_entry.tag.remove(tag)
                session.commit()
            except:
                print_error("Tag {0} does not exist for this sample".format(tag_name))

            # If tag has no entries drop it
            count = len(self.find("tag", tag_name))
            if count == 0:
                session.delete(tag)
                session.commit()
                print_warning("Tag {0} has no additional entries dropping from Database".format(tag_name))
        except SQLAlchemyError as e:
            print_error("Unable to delete tag: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #10
0
def download(url, tor=False):
    def create_connection(address, timeout=None, source_address=None):
        sock = socks.socksocket()
        sock.connect(address)
        return sock

    if tor:
        if not HAVE_SOCKS:
            print_error("Missing dependency, install socks (`pip install SocksiPy`)")
            return None

        socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9050)
        socket.socket = socks.socksocket
        socket.create_connection = create_connection

    try:
        req = Request(url)
        req.add_header('User-agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)')
        res = urlopen(req)

        data = res.read()
    except HTTPError as e:
        print_error(e)
    except URLError as e:
        if tor and e.reason.errno == 111:
            print_error("Connection refused, maybe Tor is not running?")
        else:
            print_error(e)
    except Exception as e:
        print_error("Failed download: {0}".format(e))
    else:
        return data
Beispiel #11
0
def remove_sample(file_path):
    if os.path.exists(file_path):
        os.remove(file_path)
        print("Deleted the file from storage: {0}".format(file_path))
    else:
        print_error("File Doesnt exists: {0}".format(file_path))
    return True
Beispiel #12
0
 def is_attached_file(self, quiet=False):
     if not self.is_set():
         if not quiet:
             print_error("No session opened")
         return False
     if not self.current.file:
         if not quiet:
             print_error("Not attached to a file")
         return False
     return True
Beispiel #13
0
 def is_attached_misp(self, quiet=False):
     if not self.is_set():
         if not quiet:
             print_error("No session opened")
         return False
     if not self.current.misp_event:
         if not quiet:
             print_error("Not attached to a MISP event")
         return False
     return True
Beispiel #14
0
    def find(self, key, value=None, offset=0):
        session = self.Session()
        offset = int(offset)
        rows = None

        if key == 'all':
            rows = session.query(Malware).all()
        elif key == 'ssdeep':
            ssdeep_val = str(value)
            rows = session.query(Malware).filter(Malware.ssdeep.contains(ssdeep_val)).all()
        elif key == 'any':
            prefix_val = str(value)
            rows = session.query(Malware).filter(Malware.name.startswith(prefix_val) |
                                                 Malware.md5.startswith(prefix_val) |
                                                 Malware.sha1.startswith(prefix_val) |
                                                 Malware.sha256.startswith(prefix_val) |
                                                 Malware.type.contains(prefix_val) |
                                                 Malware.mime.contains(prefix_val)).all()
        elif key == 'latest':
            if value:
                try:
                    value = int(value)
                except ValueError:
                    print_error("You need to specify a valid number as a limit for your query")
                    return None
            else:
                value = 5
            
            rows = session.query(Malware).order_by(Malware.id.desc()).limit(value).offset(offset)
        elif key == 'md5':
            rows = session.query(Malware).filter(Malware.md5 == value).all()
        elif key == 'sha1':
            rows = session.query(Malware).filter(Malware.sha1 == value).all()
        elif key == 'sha256':
            rows = session.query(Malware).filter(Malware.sha256 == value).all()
        elif key == 'tag':
            rows = session.query(Malware).filter(self.tag_filter(value)).all()
        elif key == 'name':
            if '*' in value:
                value = value.replace('*', '%')
            else:
                value = '%{0}%'.format(value)

            rows = session.query(Malware).filter(Malware.name.like(value)).all()
        elif key == 'note':
            value = '%{0}%'.format(value)
            rows = session.query(Malware).filter(Malware.note.any(Note.body.like(value))).all()
        elif key == 'type':
            rows = session.query(Malware).filter(Malware.type.like('%{0}%'.format(value))).all()
        elif key == 'mime':
            rows = session.query(Malware).filter(Malware.mime.like('%{0}%'.format(value))).all()
        else:
            print_error("No valid term specified")

        return rows
Beispiel #15
0
    def edit_note(self, note_id, body):
        session = self.Session()

        try:
            session.query(Note).get(note_id).body = body
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to update note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #16
0
    def edit_note(self, note_id, body):
        session = self.Session()

        try:
            session.query(Note).get(note_id).body = body
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to update note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #17
0
    def delete_note(self, note_id):
        session = self.Session()

        try:
            note = session.query(Note).get(note_id)
            session.delete(note)
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to delete note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #18
0
    def delete_parent(self, malware_sha256):
        session = self.Session()

        try:
            malware = session.query(Malware).filter(Malware.sha256 == malware_sha256).first()
            malware.parent = None
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to delete parent: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #19
0
    def delete_analysis(self, analysis_id):
        session = self.Session()

        try:
            analysis = session.query(Analysis).get(analysis_id)
            session.delete(analysis)
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to delete analysis: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #20
0
    def add_analysis(self, sha256, cmd_line, results):
        results = json.dumps(results)
        session = self.Session()

        malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
        if not malware_entry:
            return
        try:
            malware_entry.analysis.append(Analysis(cmd_line, results))
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to store analysis: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #21
0
    def add_note(self, sha256, title, body):
        session = self.Session()

        malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
        if not malware_entry:
            return

        try:
            malware_entry.note.append(Note(title, body))
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to add note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #22
0
    def add_analysis(self, sha256, cmd_line, results):
        results = json.dumps(results)
        session = self.Session()

        malware_entry = session.query(Malware).filter(Malware.sha256 == sha256).first()
        if not malware_entry:
            return
        try:
            malware_entry.analysis.append(Analysis(cmd_line, results))
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to store analysis: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #23
0
    def add_note(self, sha256, title, body):
        session = self.Session()

        malware_entry = session.query(Malware).filter(
            Malware.sha256 == sha256).first()
        if not malware_entry:
            return

        try:
            malware_entry.note.append(Note(title, body))
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to add note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #24
0
 def tag_filter(self, value):
     if not value:
         return None
     if "|" in value and "&" in value:
         print_error("Do not use &' and '|' at the same time.")
         return None
     if "|" in value:
         filt = Malware.tag.any(Tag.tag.in_(value.lower().split("|")))
     elif "&" in value:
         tags = []
         for tt in value.lower().split("&"):
             tags.append(Malware.tag.any(Tag.tag == tt))
         filt = and_(*tags)
     else:
         filt = Malware.tag.any(Tag.tag == value.lower())
     return filt
    def update_malware_olevba(self, id, type_olevba):
        session = self.Session()
        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode(
                    "Non ASCII character(s) in Notes not supported on Python2.\n"
                    "Please use Python >= 3.4".format(err), "error")

        try:
            session.query(Malware).get(id).type_olevba = type_olevba
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to update type olevba: {0}".format(e))
            session.rollback()
Beispiel #26
0
    def edit_note(self, note_id, body):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode("Non ASCII character(s) in Notes not supported on Python2.\n"
                                                "Please use Python >= 3.4".format(err), "error")

        try:
            session.query(Note).get(note_id).body = body
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to update note: {0}".format(e))
            session.rollback()
        finally:
            session.close()
Beispiel #27
0
    def delete_file(self, id):
        session = self.Session()

        try:
            malware = session.query(Malware).get(id)
            if not malware:
                print_error("The opened file doesn't appear to be in the database, have you stored it yet?")
                return False

            session.delete(malware)
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to delete file: {0}".format(e))
            session.rollback()
            return False
        finally:
            session.close()

        return True
Beispiel #28
0
def autorun_module(file_hash):
    if not file_hash:
        return

    if not __sessions__.is_set():
        __sessions__.new(get_sample_path(file_hash))

    for cmd_line in cfg.autorun.commands.split(','):
        split_commands = cmd_line.split(';')

        for split_command in split_commands:
            split_command = split_command.strip()

            if not split_command:
                continue

            root, args = parse_commands(split_command)

            try:
                if root in __modules__:
                    print_info("Running command \"{0}\"".format(split_command))

                    module = __modules__[root]['obj']()
                    module.set_commandline(args)
                    module.run()

                    if cfg.modules.store_output and __sessions__.is_set():
                        Database().add_analysis(file_hash, split_command,
                                                module.output)

                    if cfg.autorun.verbose:
                        print_output(module.output)

                    del (module.output[:])
                else:
                    print_error(
                        "\"{0}\" is not a valid command. Please check your viper.conf file."
                        .format(cmd_line))
            except:
                print_error(
                    "Viper was unable to complete the command {0}".format(
                        cmd_line))
Beispiel #29
0
    def add(self, obj, name=None, tags=None, parent_sha=None, notes_body=None, notes_title=None):
        session = self.Session()

        if not name:
            name = obj.name

        if parent_sha:
            parent_sha = session.query(Malware).filter(Malware.sha256 == parent_sha).first()

        if isinstance(obj, File):
            try:
                malware_entry = Malware(md5=obj.md5,
                                        crc32=obj.crc32,
                                        sha1=obj.sha1,
                                        sha256=obj.sha256,
                                        sha512=obj.sha512,
                                        size=obj.size,
                                        type=obj.type,
                                        mime=obj.mime,
                                        ssdeep=obj.ssdeep,
                                        name=name,
                                        parent=parent_sha)
                session.add(malware_entry)
                session.commit()
                self.added_ids.setdefault("malware", []).append(malware_entry.id)
            except IntegrityError:
                session.rollback()
                malware_entry = session.query(Malware).filter(Malware.md5 == obj.md5).first()
            except SQLAlchemyError as e:
                print_error("Unable to store file: {0}".format(e))
                session.rollback()
                return False

        if tags:
            self.add_tags(sha256=obj.sha256, tags=tags)

        if notes_body and notes_title:
            self.add_note(sha256=obj.sha256, title=notes_title, body=notes_body)

        return True
Beispiel #30
0
    def find(self, key, value=None, offset=0):
        session = self.Session()
        offset = int(offset)
        rows = None

        if key == 'all':
            rows = session.query(Malware).options(subqueryload(Malware.tag)).all()
        elif key == 'ssdeep':
            ssdeep_val = str(value)
            rows = session.query(Malware).filter(Malware.ssdeep.contains(ssdeep_val)).all()
        elif key == 'any':
            prefix_val = str(value)
            rows = session.query(Malware).filter(Malware.name.startswith(prefix_val) |
                                                 Malware.md5.startswith(prefix_val) |
                                                 Malware.sha1.startswith(prefix_val) |
                                                 Malware.sha256.startswith(prefix_val) |
                                                 Malware.type.contains(prefix_val) |
                                                 Malware.mime.contains(prefix_val)).all()
        elif key == 'latest':
            if value:
                try:
                    value = int(value)
                except ValueError:
                    print_error("You need to specify a valid number as a limit for your query")
                    return None
            else:
                value = 5

            rows = session.query(Malware).order_by(Malware.id.desc()).limit(value).offset(offset)
        elif key == 'md5':
            rows = session.query(Malware).filter(Malware.md5 == value).all()
        elif key == 'sha1':
            rows = session.query(Malware).filter(Malware.sha1 == value).all()
        elif key == 'sha256':
            rows = session.query(Malware).filter(Malware.sha256 == value).all()
        elif key == 'tag':
            rows = session.query(Malware).filter(self.tag_filter(value)).all()
        elif key == 'name':
            if not value:
                print_error("You need to specify a valid file name pattern (you can use wildcards)")
                return None

            if '*' in value:
                value = value.replace('*', '%')
            else:
                value = '%{0}%'.format(value)

            rows = session.query(Malware).filter(Malware.name.like(value)).all()
        elif key == 'note':
            value = unicode(value, "utf-8")
            value = u'%{0}%'.format(value)
            rows = session.query(Malware).filter(Malware.note.any(Note.body.like(value))).all()
        elif key == 'type':
            rows = session.query(Malware).filter(Malware.type.like('%{0}%'.format(value))).all()
        elif key == 'mime':
            rows = session.query(Malware).filter(Malware.mime.like('%{0}%'.format(value))).all()
        else:
            print_error("No valid term specified")

        return rows
Beispiel #31
0
def check_and_deploy_yara_rules():
    """Yara: check whether rule path exist - if not copy default set of rules to directory"""
    yara_rules_path = os.path.join(__project__.base_path, "yara")
    if os.path.exists(yara_rules_path):
        print_info("Using Yara rules from directory: {}".format(yara_rules_path))
    else:
        # Prio 1: rules if Viper was installed with pip
        yara_path_setup_utils = os.path.join(VIPER_ROOT, DIST_DIR_YARA_RULES)

        # Prio 2: rules if Viper was checkout from repo
        yara_path_repo = os.path.join(VIPER_ROOT, "data", "yara")

        if os.path.exists(yara_path_setup_utils):
            print_warning("Yara rule directory not found - copying default "
                          "rules ({}) to: {}".format(yara_path_setup_utils, yara_rules_path))

            shutil.copytree(yara_path_setup_utils, yara_rules_path)
        elif os.path.exists(yara_path_repo):
            print_warning("Yara rule directory not found - copying default "
                          "rules ({}) to: {}".format(yara_path_repo, yara_rules_path))
            shutil.copytree(yara_path_repo, yara_rules_path)
        else:
            print_error("No default Yara rules found")
    def update_malwarevt(self, resource, scan_date, positives, total):
        session = self.Session()

        if sys.version_info < (3, 0):
            # on Python2 make sure to only handle ASCII
            try:
                title.decode('ascii')
                body.decode('ascii')
            except UnicodeError as err:
                raise Python2UnsupportedUnicode(
                    "Non ASCII character(s) in Notes not supported on Python2.\n"
                    "Please use Python >= 3.4".format(err), "error")

        malwarevt_id = session.query(MalwareVT).filter(
            MalwareVT.resource == resource)
        try:
            session.query(MalwareVT).get(malwarevt_id).scan_date = scan_date
            session.query(MalwareVT).get(malwarevt_id).positives = positives
            session.query(MalwareVT).get(malwarevt_id).total = total
            session.commit()
        except SQLAlchemyError as e:
            print_error("Unable to update virus total register: {0}".format(e))
            session.rollback()
Beispiel #33
0
def autorun_module(file_hash):
    if not file_hash:
        return

    if not __sessions__.is_set():
        __sessions__.new(get_sample_path(file_hash))

    for cmd_line in cfg.autorun.commands.split(','):
        split_commands = cmd_line.split(';')

        for split_command in split_commands:
            split_command = split_command.strip()

            if not split_command:
                continue

            root, args = parse_commands(split_command)

            try:
                if root in __modules__:
                    print_info("Running command \"{0}\"".format(split_command))

                    module = __modules__[root]['obj']()
                    module.set_commandline(args)
                    module.run()
                    
                    if cfg.modules.store_output and __sessions__.is_set():
                        Database().add_analysis(file_hash, split_command, module.output)
                    
                    if cfg.autorun.verbose:
                        print_output(module.output)

                    del(module.output[:])
                else:
                    print_error("\"{0}\" is not a valid command. Please check your viper.conf file.".format(cmd_line))
            except:
                print_error("Viper was unable to complete the command {0}".format(cmd_line))
Beispiel #34
0
def config(data):
    key = 'C\x00O\x00N\x00F\x00I\x00G'

    config_coded = extract_config(data)
    config_raw = rc4crypt(config_coded, key)

    # 1.3.x - Not implemented yet.
    if len(config_raw) == 0xe10:
        print_warning("Detected XtremeRAT 1.3.x, not supported yet")
        config = None
    # 2.9.x - Not a stable extract.
    elif len(config_raw) == 0x1390 or len(config_raw) == 0x1392:
        config = v29(config_raw)
    # 3.1 & 3.2
    elif len(config_raw) == 0x5Cc:
        config = v32(config_raw)
    # 3.5
    elif len(config_raw) == 0x7f0:
        config = v35(config_raw)
    else:
        print_error("No known XtremeRAT version detected")
        config = None

    return config
Beispiel #35
0
def config(data):
    key = 'C\x00O\x00N\x00F\x00I\x00G'

    config_coded = extract_config(data)
    config_raw = rc4crypt(config_coded, key)

    # 1.3.x - Not implemented yet.
    if len(config_raw) == 0xe10:
        print_warning("Detected XtremeRAT 1.3.x, not supported yet")
        config = None
    # 2.9.x - Not a stable extract.
    elif len(config_raw) == 0x1390 or len(config_raw) == 0x1392:
        config = v29(config_raw)
    # 3.1 & 3.2
    elif len(config_raw) == 0x5Cc:
        config = v32(config_raw)
    # 3.5
    elif len(config_raw) == 0x7f0:
        config = v35(config_raw)
    else:
        print_error("No known XtremeRAT version detected")
        config = None

    return config
Beispiel #36
0
def download(url, tor=False):
    s = requests.Session()
    s.headers.update({'User-agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'})
    proxies = {}
    if tor:
        proxies = {'http': 'socks5://{}:{}'.format('127.0.0.1', 9050),
                   'https': 'socks5://{}:{}'.format('127.0.0.1', 9050)}
    try:
        res = s.get(url, proxies=proxies)
        res.raise_for_status()
    except ConnectionError as e:
        if tor:
            print_error("Connection refused, maybe Tor is not running?")
        print_error(e)
    except Exception as e:
        print_error("Failed download: {0}".format(e))
    else:
        return res.content
Beispiel #37
0
def download(url, tor=False):
    s = requests.Session()
    s.headers.update({
        'User-agent':
        'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'
    })
    proxies = {}
    if tor:
        proxies = {
            'http': 'socks5://{}:{}'.format('127.0.0.1', 9050),
            'https': 'socks5://{}:{}'.format('127.0.0.1', 9050)
        }
    try:
        res = s.get(url, proxies=proxies)
        res.raise_for_status()
    except ConnectionError as e:
        if tor:
            print_error("Connection refused, maybe Tor is not running?")
        print_error(e)
    except Exception as e:
        print_error("Failed download: {0}".format(e))
    else:
        return res.content
Beispiel #38
0
    def start(self):
        # log start
        log.info('Starting viper-cli')

        # Logo.
        logo()

        # Setup shell auto-complete.
        def complete(text, state):
            # filesystem path completion only makes sense for a few commands/modules
            fs_path_completion = False

            # clean up user input so far (no leading/trailing/duplicate spaces)
            line = " ".join(readline.get_line_buffer().split())
            words = line.split(" ")  # split words; e.g. store -f /tmp -> ['store', '-f', '/tmp']

            if words[0] in [i for i in self.cmd.commands]:
                # handle completion for commands

                # enable filesystem path completion for certain commands (e.g. export, store)
                if words[0] in [x for x in self.cmd.commands if self.cmd.commands[x]["fs_path_completion"]]:
                    fs_path_completion = True

                options = [key for key in self.cmd.commands[words[0]]["parser_args"]]

                # enable tab completion for projects --switch
                if words[0] == "projects":
                    if "--switch" in words or "-s" in words:
                        options += get_project_list()

                        # enable tab completion for copy (list projects)
                if words[0] == "copy":
                    options += get_project_list()

                completions = [i for i in options if i.startswith(text) and i not in words]

            elif words[0] in [i for i in __modules__]:
                # handle completion for modules
                if len(words) == 1:
                    # only the module name is give so far - present all args and the subparsers (if any)
                    options = [key for key in __modules__[words[0]]["parser_args"]]
                    options += [key for key in __modules__[words[0]]["subparser_args"]]

                elif len(words) == 2:
                    # 1 complete word and one either complete or incomplete that specifies the subparser or an arg
                    if words[1] in list(__modules__[words[0]]["parser_args"]):
                        # full arg for a module is given
                        options = [key for key in __modules__[words[0]]["parser_args"]]

                    elif words[1] in list(__modules__[words[0]]["subparser_args"]):
                        # subparser is specified - get all subparser args
                        options = [key for key in __modules__[words[0]]["subparser_args"][words[1]]]

                    else:
                        options = [key for key in __modules__[words[0]]["parser_args"]]
                        options += [key for key in __modules__[words[0]]["subparser_args"]]

                else:  # more that 2 words
                    if words[1] in list(__modules__[words[0]]["subparser_args"]):
                        # subparser is specified - get all subparser args
                        options = [key for key in __modules__[words[0]]["subparser_args"][words[1]]]
                    else:
                        options = [key for key in __modules__[words[0]]["parser_args"]]

                completions = [i for i in options if i.startswith(text) and i not in words]

            else:
                # initial completion for both commands and modules
                completions = [i for i in self.cmd.commands if i.startswith(text)]
                completions += [i for i in __modules__ if i.startswith(text)]

            if state < len(completions):
                return completions[state]

            if fs_path_completion:
                # completion for paths only if it makes sense
                if text.startswith("~"):
                    text = "{0}{1}".format(expanduser("~"), text[1:])
                return (glob.glob(text + '*') + [None])[state]

            return

        # Auto-complete on tabs.
        readline.set_completer_delims(' \t\n;')
        readline.parse_and_bind('tab: complete')
        readline.set_completer(complete)

        # Save commands in history file.
        def save_history(path):
            readline.write_history_file(path)

        # If there is an history file, read from it and load the history
        # so that they can be loaded in the shell.
        # Now we are storing the history file in the local project folder
        history_path = os.path.join(__project__.path, 'history')

        if os.path.exists(history_path):
            readline.read_history_file(history_path)

        readline.set_history_length(10000)

        # Register the save history at program's exit.
        atexit.register(save_history, path=history_path)

        # Main loop.
        while self.active:
            # If there is an open session, we include the path to the opened
            # file in the shell prompt.
            # TODO: perhaps this block should be moved into the session so that
            # the generation of the prompt is done only when the session's
            # status changes.
            prefix = ''
            if __project__.name:
                prefix = bold(cyan(__project__.name)) + ' '

            if __sessions__.is_set():
                stored = ''
                filename = ''
                if __sessions__.current.file:
                    filename = __sessions__.current.file.name
                    if not Database().find(key='sha256', value=__sessions__.current.file.sha256):
                        stored = magenta(' [not stored]', True)

                misp = ''
                if __sessions__.current.misp_event:
                    misp = ' [MISP'
                    if __sessions__.current.misp_event.event.id:
                        misp += ' {}'.format(__sessions__.current.misp_event.event.id)
                    else:
                        misp += ' New Event'
                    if __sessions__.current.misp_event.off:
                        misp += ' (Offline)'
                    misp += ']'

                prompt = (prefix + cyan('viper ', True) +
                          white(filename, True) + blue(misp, True) + stored + cyan(' > ', True))
            # Otherwise display the basic prompt.
            else:
                prompt = prefix + cyan('viper > ', True)

            # force str (Py3) / unicode (Py2) for prompt
            if sys.version_info <= (3, 0):
                prompt = prompt.encode('utf-8')
            else:
                prompt = str(prompt)

            # Wait for input from the user.
            try:
                data = input(prompt).strip()
            except KeyboardInterrupt:
                print("")
            # Terminate on EOF.
            except EOFError:
                self.stop()
                print("")
                continue
            # Parse the input if the user provided any.
            else:
                # If there are recognized keywords, we replace them with
                # their respective value.
                data = self.keywords(data)
                # Skip if the input is empty.
                if not data:
                    continue

                # Check for output redirection
                # If there is a > in the string, we assume the user wants to output to file.
                if '>' in data:
                    data, console_output['filename'] = data.split('>', 1)
                    if ';' in console_output['filename']:
                        console_output['filename'], more_commands = console_output['filename'].split(';', 1)
                        data = '{};{}'.format(data, more_commands)
                    print("Writing output to {0}".format(console_output['filename'].strip()))

                # If the input starts with an exclamation mark, we treat the
                # input as a bash command and execute it.
                # At this point the keywords should be replaced.
                if data.startswith('!'):
                    os.system(data[1:])
                    continue

                # Try to split commands by ; so that you can sequence multiple
                # commands at once.
                # For example:
                # viper > find name *.pdf; open --last 1; pdf id
                # This will automatically search for all PDF files, open the first entry
                # and run the pdf module against it.
                split_commands = data.split(';')
                for split_command in split_commands:
                    split_command = split_command.strip()
                    if not split_command:
                        continue

                    # If it's an internal command, we parse the input and split it
                    # between root command and arguments.
                    root, args = self.parse(split_command)

                    # Check if the command instructs to terminate.
                    if root in ('exit', 'quit'):
                        self.stop()
                        continue

                    try:
                        # If the root command is part of the embedded commands list we
                        # execute it.
                        if root in self.cmd.commands:
                            self.cmd.commands[root]['obj'](*args)
                            del(self.cmd.output[:])
                        # If the root command is part of loaded modules, we initialize
                        # the module and execute it.
                        elif root in __modules__:
                            module = __modules__[root]['obj']()
                            module.set_commandline(args)
                            module.run()

                            if cfg.modules.store_output and __sessions__.is_set():
                                try:
                                    Database().add_analysis(__sessions__.current.file.sha256, split_command, module.output)
                                except Exception:
                                    pass
                            del(module.output[:])
                        else:
                            print("Command not recognized.")
                    except KeyboardInterrupt:
                        pass
                    except Exception:
                        print_error("The command {0} raised an exception:".format(bold(root)))
                        traceback.print_exc()

                console_output['filename'] = None   # reset output to stdout
Beispiel #39
0
    def find(self, key, value=None, offset=0):
        session = self.Session()
        offset = int(offset)
        rows = None

        if key == "all":
            rows = session.query(Malware).all()
        elif key == "ssdeep":
            ssdeep_val = str(value)
            rows = session.query(Malware).filter(Malware.ssdeep.contains(ssdeep_val)).all()
        elif key == "any":
            prefix_val = str(value)
            rows = (
                session.query(Malware)
                .filter(
                    Malware.name.startswith(prefix_val)
                    | Malware.md5.startswith(prefix_val)
                    | Malware.sha1.startswith(prefix_val)
                    | Malware.sha256.startswith(prefix_val)
                    | Malware.type.contains(prefix_val)
                    | Malware.mime.contains(prefix_val)
                )
                .all()
            )
        elif key == "latest":
            if value:
                try:
                    value = int(value)
                except ValueError:
                    print_error("You need to specify a valid number as a limit for your query")
                    return None
            else:
                value = 5

            rows = session.query(Malware).order_by(Malware.id.desc()).limit(value).offset(offset)
        elif key == "md5":
            rows = session.query(Malware).filter(Malware.md5 == value).all()
        elif key == "sha1":
            rows = session.query(Malware).filter(Malware.sha1 == value).all()
        elif key == "sha256":
            rows = session.query(Malware).filter(Malware.sha256 == value).all()
        elif key == "tag":
            rows = session.query(Malware).filter(Malware.tag.any(Tag.tag == value.lower())).all()
        elif key == "name":
            if "*" in value:
                value = value.replace("*", "%")
            else:
                value = "%{0}%".format(value)

            rows = session.query(Malware).filter(Malware.name.like(value)).all()
        elif key == "note":
            value = "%{0}%".format(value)
            rows = session.query(Malware).filter(Malware.note.any(Note.body.like(value))).all()
        elif key == "type":
            rows = session.query(Malware).filter(Malware.type.like("%{0}%".format(value))).all()
        elif key == "mime":
            rows = session.query(Malware).filter(Malware.mime.like("%{0}%".format(value))).all()
        else:
            print_error("No valid term specified")

        return rows
Beispiel #40
0
    def start(self):
        # Logo.
        logo()

        # Setup shell auto-complete.
        def complete(text, state):
            # Try to autocomplete commands.
            cmds = [i for i in self.cmd.commands if i.startswith(text)]
            if state < len(cmds):
                return cmds[state]

            # Try to autocomplete modules.
            mods = [i for i in __modules__ if i.startswith(text)]
            if state < len(mods):
                return mods[state]

            # Then autocomplete paths.
            if text.startswith("~"):
                text = "{0}{1}".format(expanduser("~"), text[1:])
            return (glob.glob(text+'*')+[None])[state]

        # Auto-complete on tabs.
        readline.set_completer_delims(' \t\n;')
        readline.parse_and_bind('tab: complete')
        readline.set_completer(complete)

        # Save commands in history file.
        def save_history(path):
            readline.write_history_file(path)

        # If there is an history file, read from it and load the history
        # so that they can be loaded in the shell.
        # Now we are storing the history file in the local project folder
        history_path = os.path.join(__project__.path, 'history')

        if os.path.exists(history_path):
            readline.read_history_file(history_path)

        # Register the save history at program's exit.
        atexit.register(save_history, path=history_path)

        # Main loop.
        while self.active:
            # If there is an open session, we include the path to the opened
            # file in the shell prompt.
            # TODO: perhaps this block should be moved into the session so that
            # the generation of the prompt is done only when the session's
            # status changes.
            prefix = ''
            if __project__.name:
                prefix = bold(cyan(__project__.name)) + ' '

            if __sessions__.is_set():
                stored = ''
                filename = ''
                if __sessions__.current.file:
                    filename = __sessions__.current.file.name
                    if not Database().find(key='sha256', value=__sessions__.current.file.sha256):
                        stored = magenta(' [not stored]', True)

                misp = ''
                if __sessions__.current.misp_event:
                    misp = '[MISP'
                    if __sessions__.current.misp_event.event.id:
                        misp += ' {}'.format(__sessions__.current.misp_event.event.id)
                    else:
                        misp += ' New Event'
                    if __sessions__.current.misp_event.off:
                        misp += ' (Offline)'
                    misp += ']'

                prompt = (prefix + cyan('viper ', True) +
                          white(filename, True) + blue(misp, True) + stored + cyan(' > ', True))
            # Otherwise display the basic prompt.
            else:
                prompt = prefix + cyan('viper > ', True)

            # Wait for input from the user.
            try:
                data = input(prompt).strip()
            except KeyboardInterrupt:
                print("")
            # Terminate on EOF.
            except EOFError:
                self.stop()
                print("")
                continue
            # Parse the input if the user provided any.
            else:
                # If there are recognized keywords, we replace them with
                # their respective value.
                data = self.keywords(data)
                # Skip if the input is empty.
                if not data:
                    continue

                # Check for output redirection
                # If there is a > in the string, we assume the user wants to output to file.
                if '>' in data:
                    data, console_output['filename'] = data.split('>')
                    print("Writing output to {0}".format(console_output['filename'].strip()))


                # If the input starts with an exclamation mark, we treat the
                # input as a bash command and execute it.
                # At this point the keywords should be replaced.
                if data.startswith('!'):
                    os.system(data[1:])
                    continue

                # Try to split commands by ; so that you can sequence multiple
                # commands at once.
                # For example:
                # viper > find name *.pdf; open --last 1; pdf id
                # This will automatically search for all PDF files, open the first entry
                # and run the pdf module against it.
                split_commands = data.split(';')
                for split_command in split_commands:
                    split_command = split_command.strip()
                    if not split_command:
                        continue

                    # If it's an internal command, we parse the input and split it
                    # between root command and arguments.
                    root, args = self.parse(split_command)

                    # Check if the command instructs to terminate.
                    if root in ('exit', 'quit'):
                        self.stop()
                        continue

                    try:
                        # If the root command is part of the embedded commands list we
                        # execute it.
                        if root in self.cmd.commands:
                            self.cmd.commands[root]['obj'](*args)
                            del(self.cmd.output[:])
                        # If the root command is part of loaded modules, we initialize
                        # the module and execute it.
                        elif root in __modules__:
                            module = __modules__[root]['obj']()
                            module.set_commandline(args)
                            module.run()

                            if cfg.modules.store_output and __sessions__.is_set():
                                try:
                                    Database().add_analysis(__sessions__.current.file.sha256, split_command, module.output)
                                except:
                                    pass
                            del(module.output[:])
                        else:
                            print("Command not recognized.")
                    except KeyboardInterrupt:
                        pass
                    except Exception:
                        print_error("The command {0} raised an exception:".format(bold(root)))
                        traceback.print_exc()

                console_output['filename'] = None   # reset output to stdout