Пример #1
0
def check_virus(data):
    utilities.warn("SCAN: INIT")
    try:
        import pyclamd
        try:
            pc = pyclamd.ClamdUnixSocket()
        except NameError:
            # Fix a pyclamd bug
            pyclamd.__dict__["__builtins__"]["basestring"] = str
            pc = pyclamd.ClamdUnixSocket()
    except:
        utilities.send_backtrace("", "CAN'T CONNECT TO CLAMAV")
        return None  # Not installed or not running
    utilities.warn("SCAN: START")
    try:
        if isinstance(data, bytes):
            res = pc.scan_stream(data)
        else:
            res = pc.scan_stream(HackClamd(data))
    except:
        utilities.send_backtrace("", "SCAN STREAM FAIL")
        return None  # Bug

    utilities.warn("SCAN: STOP %s" % res)
    if res:
        return repr(res)
    else:
        return ''
Пример #2
0
    def run(self):
        super(ClamAV, self).run()
        if self.args is None:
            return

        if not HAVE_CLAMD:
            self.log(
                'error',
                "Missing dependency, install requests (`pip install pyclamd`)")
            return

        if not __sessions__.is_set():
            self.log('error', 'No open session')
            return

        daemon = None
        socket = None
        socket = self.args.socket

        try:
            if socket is not None:
                daemon = pyclamd.ClamdUnixSocket(socket)
                self.log('info', 'Using socket {0} to scan'.format(socket))
            else:
                daemon = pyclamd.ClamdUnixSocket()
                socket = 'Clamav'
        except Exception as ex:
            msg = 'Daemon connection failure, {0}'.format(ex)
            self.log('error,', msg)
            return

        try:
            if daemon.ping():
                with open(__sessions__.current.file.path, 'r') as fd:
                    results = daemon.scan_stream(fd.read())
            else:
                self.log('error', "Unable to connect to the daemon")
        except Exception as ex:
            msg = 'Unable to scan with antivirus daemon, {0}'.format(ex)
            self.log('error', msg)
            return

        found = None
        name = 'not found'

        if results:
            for item in results:
                found = results[item][0]
                name = results[item][1]

        if found == 'ERROR':
            self.log(
                'error',
                "Check permissions of the binary folder, {0}".format(name))
        else:
            self.log('info', "Daemon {0} returns: {1}".format(socket, name))
Пример #3
0
    def each(self, target):
        self.results = {'analysis': []}

        if self._clam is None:
            if len(self.filename) > 0:
                self._clam = pyclamd.ClamdUnixSocket(filename=self.filename)
            elif len(self.server) > 0 and self.port > 0:
                try:
                    self._clam = pyclamd.ClamdNetworkSocket(host=self.server,
                                                            port=self.port)
                except:
                    return False
            else:
                return False

            if not self._clam.ping():
                return False

        res = None
        with open(target) as f:
            res = self._clam.scan_stream(f.read())
        if not res:
            return False

        status, name = res['stream']
        self.add_tag(self._tag)
        self.results['analysis'].append((self._MALWARE_KEYWORD, name))
        self.add_probable_name(name)

        return True
Пример #4
0
def virus_scan(input_file):
    try:
        cd = pyclamd.ClamdUnixSocket()
        # test if server is reachable
        cd.ping()
    except pyclamd.ConnectionError:
        # if failed, test for network socket
        cd = pyclamd.ClamdNetworkSocket()
    try:
        cd.ping()
    except pyclamd.ConnectionError:
        raise ValueError(
            'could not connect to clamd server either by unix or network socket'
        )

    scan_results = cd.scan_file(input_file)
    if scan_results is not None:
        send_mail('Django Virus Found',
                  'Virus found in file uploaded',
                  '*****@*****.**',
                  ['*****@*****.**'],
                  fail_silently=False)
        return True
    else:
        return False
Пример #5
0
def virus_scan(input_file):
    try:
        cd = pyclamd.ClamdUnixSocket()
        # test if server is reachable
        cd.ping()
    except pyclamd.ConnectionError:
        # if failed, test for network socket
        cd = pyclamd.ClamdNetworkSocket()
    try:
        cd.ping()
    except pyclamd.ConnectionError:
        raise ValueError(
            'could not connect to clamd server either by unix or network socket'
        )

    scan_results = cd.scan_stream(input_file.read())
    if scan_results is not None:
        #print 'Virus found:', scan_results
        send_mail('Django Virus Scanner Results',
                  'Virus scanner returned - {0}'.format(scan_results, ),
                  '*****@*****.**',
                  ['*****@*****.**'],
                  fail_silently=False)
        raise ValidationError(
            'Virus scanner returned %(value)s',
            params={'value': scan_results},
        )
Пример #6
0
    def get_clamav(self):
        """Get ClamAV signatures matches.
        Requires pyclamd module. Additionally if running with apparmor, an exception must be made.
        apt-get install clamav clamav-daemon clamav-freshclam clamav-unofficial-sigs -y
        pip3 install -U pyclamd
        systemctl enable clamav-daemon
        systemctl start clamav-daemon
        usermod -a -G cuckoo clamav
        echo "/opt/CAPEv2/storage/** r," | sudo tee -a /etc/apparmor.d/local/usr.sbin.clamd
        @return: matched ClamAV signatures.
        """
        matches = []

        if HAVE_CLAMAV and os.path.getsize(self.file_path) > 0:
            try:
                cd = pyclamd.ClamdUnixSocket()
                results = cd.allmatchscan(self.file_path)
                if results:
                    for entry in results[self.file_path]:
                        if entry[0] == "FOUND" and entry[1] not in matches:
                            matches.append(entry[1])
            except ConnectionError as e:
                log.warning("failed to connect to clamd socket")
            except Exception as e:
                log.warning("failed to scan file with clamav {0}".format(e))
            finally:
                return matches
        return matches
Пример #7
0
 def _get_connection(self):
     """
     :return: A different connection for each time you call the method.
              Thought about having a connection pool, but it doesn't make
              much sense; plus it adds complexity due to the threads.
     """
     return pyclamd.ClamdUnixSocket(filename=self._clamd_socket)
Пример #8
0
    def _run(self, scanObject, result, depth, args):
        '''
        Arguments:
        unix_socket     -- Path to the clamd unix socket (str)
        max_bytes       -- Maximum number of bytes to scan (0 is unlimited) (int)
        timeout         -- Max number of seconds to scan (float)

        Returns:
        Flags           -- Virus name hits
        Metadata        -- Unix socket or daemon errors
        '''
        moduleResult = []

        # Defualt max of 20 MB
        default_max_bytes = 20000000
        # Default timeout of 10.0 seconds
        default_timeout = 10.0
        # Default clamd unix socket
        default_unix_socket = '/var/run/clamav/clamd.sock'

        unix_socket = str(get_option(args, 'unixsocket', 'scanclamavunixsocket', default_unix_socket))
        max_bytes = int(get_option(args, 'maxbytes', 'scanclamavmaxbytes', default_max_bytes))
        timeout = float(get_option(args, 'timeout', 'scanclamavtimeout', default_timeout))

        if timeout < 0.01:
            timeout = default_timeout

        # Connect to daemon
        try:
            clam = pyclamd.ClamdUnixSocket(filename=unix_socket, timeout=timeout)
        except IOError:
            logging.debug('IOError: Cannot connect to clamd unix socket file')
            scanObject.addMetadata(self.module_name, 'Error', 'IOError: clamd socket')
            return moduleResult

        errmsg = None
        try:
            # Scan the buffer with clamav
            if max_bytes <= 0:
                clam_result = clam.scan_stream(scanObject.buffer)
            else:
                clam_result = clam.scan_stream(str(buffer(scanObject.buffer, 0, max_bytes)))

            # Process a result
            if clam_result:
                status, virusname = clam_result['stream']
                scanObject.addFlag("%s:%s" % (self.flag_prefix, str(virusname)))
        except ValueError as e:
            errmsg = "ValueError (BufferTooLong): %s" % e
        except IOError as e:
            errmsg = "IOError (ScanError): %s" % e
        except Exception as e:
            errmsg = "Unexpected error: %s" % e

        if errmsg:
            logging.debug(errmsg)
            scanObject.addMetadata(self.module_name, 'Error', errmsg)

        return moduleResult
Пример #9
0
    def Connect(self):
        self.daemon = None
        self.socket = self.args.socket
        try:
            if self.socket is not None:
                self.daemon = pyclamd.ClamdUnixSocket(self.socket)
                self.log('info',
                         'Using socket {0} to scan'.format(self.socket))
            else:
                self.daemon = pyclamd.ClamdUnixSocket()
                self.socket = 'Clamav'

            return self.daemon.ping()
        except Exception as ex:
            msg = 'Daemon connection failure, {0}'.format(ex)
            self.log('error,', msg)
            return False
Пример #10
0
def get_clam():
    """Establish connection with Clamd
    :return: pyclamd socket object
    There is no try/except here as we want this error to propagate up.
    """
    socket = os.getenv('CLAMD_SOCK', default='/var/run/clamav/clamd.ctl')
    csock = pyclamd.ClamdUnixSocket(socket)
    csock.ping()
    return csock
Пример #11
0
    def clean_file(self):
        file = self.cleaned_data.get('file', '')

        #check a file in form for viruses
        if file and settings.ANTI_VIRUS:
            from tempfile import mkstemp
            import pyclamd
            import os
            
            #Raise an error if ANTI_VIRUS server not reachable
            try:
                 cd = pyclamd.ClamdUnixSocket()
                 # test if server is reachable
                 cd.ping()
            except pyclamd.ConnectionError:
                 # if failed, test for network socket
                 cd = pyclamd.ClamdNetworkSocket()
                 try:
                     cd.ping()
                 except pyclamd.ConnectionError:
                     raise forms.ValidationError('Could not connect to clamd server either by unix or network socket.')
            
        #The AV is working so scan the file.
        
        #Create a temporary file name
        tmp_fn = str(uuid.uuid4())
        
        #get the data from the file.
        data = self.files['file']

        #Save the temp file.
        path = default_storage.save(tmp_fn, ContentFile(data.read()))
        
        #Uncommenting the next line will write a test virus instead of file in form. 
        #path = default_storage.save(tmp_fn, ContentFile(cd.EICAR()))
        
        tmp_path = str(os.path.join(settings.MEDIA_ROOT, path))
         
        #scan for viruses    
        if cd.scan_file(tmp_path) is not None:
            #A virus was found. 
            #Delete the tmp file
            os.remove(tmp_path)
            #Raise Validation Error
            raise forms.ValidationError("A virus was detected in this file and therefore it was rejected.")
            
        #remove the temp file since this is just a clean
        os.remove(tmp_path)       
    
        #Make sure the file is a valid SSA DMF
        if not valid_dmf(file):
            raise forms.ValidationError("The files does not appear to be a valid DMF.")
        
        
        
        
        return file
Пример #12
0
    def scan(self, path):
        cs = pyclamd.ClamdUnixSocket(filename=self.socket)
        try:
            result_ = cs.scan_file(path)
            if result_:
                self._results.update(result_)
        except Exception as e:
            logging.error(e)

        return self._results
Пример #13
0
def _connect_clam():
    try:
        clamScanner = pyclamd.ClamdUnixSocket()
        clamScanner.ping()
    except ConnectionError:
        clamScanner = pyclamd.ClamdNetworkSocket()
        try:
            clamScanner.ping()
        except ConnectionError:
            raise ValueError("Unable to connect to clamd")
    return clamScanner
Пример #14
0
    def clean(self, data, initial=None):
        f = super(yatsFileField, self).clean(initial or data)
        if f is None:
            return None
        elif not data and initial:
            return initial

        if settings.FILE_UPLOAD_VIRUS_SCAN and pyclamd:
            # virus scan
            try:
                if not hasattr(pyclamd, 'scan_stream'):
                    cd = pyclamd.ClamdUnixSocket()
                else:
                    pyclamd.init_network_socket('localhost', 3310)
                    cd = pyclamd

                # We need to get a file object for clamav. We might have a path or we might
                # have to read the data into memory.
                if hasattr(data, 'temporary_file_path'):
                    chmod(data.temporary_file_path(), 0664)
                    result = cd.scan_file(data.temporary_file_path())
                else:
                    if hasattr(data, 'read'):
                        result = cd.scan_stream(data.read())
                    else:
                        result = cd.scan_stream(data['content'])
            except:
                from socket import gethostname
                raise ValidationError(
                    self.error_messages['virus_engine_error'] % gethostname())

            if result:
                msg = ' '.join(result[result.keys()[0]]).replace('FOUND ', '')
                raise ValidationError(self.error_messages['virus_found'] % msg)

        hasher = hashlib.md5()
        # We need to get a file object for clamav. We might have a path or we might
        # have to read the data into memory.
        if hasattr(data, 'temporary_file_path'):
            with open(data.temporary_file_path(), 'rb') as afile:
                buf = afile.read()
                hasher.update(buf)
            self.hash = hasher.hexdigest()
        else:
            if hasattr(data, 'read'):
                data.seek(0)
                buf = data.read()
                hasher.update(buf)
            else:
                hasher.update(data['content'].read())
        f.hash = hasher.hexdigest()

        return f
Пример #15
0
    def __init__(self, **kwargs):

        self._mail_nr = kwargs.get("mail_nr", 0)

        self._x_virus_name = kwargs.get("x_virus_name", X_VIRUS_NAME)
        self._x_virus = kwargs.get("x_virus", X_VIRUS)
        self._x_virus_scan_error = kwargs.get("x_virus_scan_error",
                                              X_VIRUS_SCAN_ERROR)

        self._tmp_path = kwargs.get("tmp_path", TMP_PATH)

        self._regex = re.compile("\.[A-Za-z]{3,4}\.exe")
        self._cd = pyclamd.ClamdUnixSocket()
Пример #16
0
    def _run(self, scanObject, result, depth, args):
        """
        Arguments:
        unixsocket     -- Path to the clamd unix socket (str)
        maxbytes       -- Maximum number of bytes to scan (0 is unlimited) (int)

        Returns:
        Flags           -- Virus name hits
        Metadata        -- Unix socket or daemon errors
        """
        moduleResult = []

        unix_socket = str(
            get_option(args, 'unixsocket', 'scanclamavunixsocket',
                       '/var/run/clamav/clamd.ctl'))
        max_bytes = int(
            get_option(args, 'maxbytes', 'scanclamavmaxbytes', 20000000))

        # Connect to daemon
        if not self.clam:
            try:
                self.clam = pyclamd.ClamdUnixSocket(filename=unix_socket)
            except IOError:
                logging.debug(
                    'IOError: Cannot connect to clamd unix socket file')
                scanObject.addMetadata(self.module_name, 'Error',
                                       'IOError: clamd socket')
                raise

        try:
            # Scan the buffer with clamav
            if max_bytes <= 0:
                clam_result = self.clam.scan_stream(scanObject.buffer)
            else:
                clam_result = self.clam.scan_stream(
                    str(buffer(scanObject.buffer, 0, max_bytes)))

            # Process a result
            if clam_result:
                status, virusname = clam_result['stream']
                scanObject.addFlag("%s:%s" %
                                   (self.flag_prefix, str(virusname)))
        except ValueError as e:
            scanObject.addMetadata(self.module_name, 'Error',
                                   'ValueError (BufferTooLong): %s' % str(e))
        except IOError as e:
            scanObject.addMetadata(self.module_name, 'Error',
                                   'IOError (ScanError): %s' % str(e))

        return moduleResult
Пример #17
0
    def _connect(self):
        """
        Connect to clam server

        """
        self.clamd_lock.acquire()
        if self.daemon == 'network':
            self.clamd = pyclamd.ClamdNetworkSocket(host=self.host,
                                                    port=self.port,
                                                    timeout=self.timeout)
        else:
            self.clamd = pyclamd.ClamdUnixSocket(filename=self.socket,
                                                 timeout=self.timeout)
        self.clamd_lock.release()
Пример #18
0
def get_clam():
    """Establish connection with Clamd
    :return: pyclamd socket object
    """
    socket = os.getenv('CLAMD_SOCK', default='/run/clamav/clamd.sock')
    csock = None
    try:
        csock = pyclamd.ClamdUnixSocket(socket)
        csock.ping()
    except Exception as e:
        logging.error(f'Failed to ping clamav deamon over socket: {socket}')
        logging.error(f'Error: {e}')
        raise
    return csock
Пример #19
0
    def save(self, *args, **kwargs):
        super(Document, self).save(*args, **kwargs)
        try:
            cd = pyclamd.ClamdUnixSocket()
            # test if server is reachable
            cd.ping()
        except pyclamd.ConnectionError:
            # if failed, test for network socket
            cd = pyclamd.ClamdNetworkSocket()
        try:
            cd.ping()
        except pyclamd.ConnectionError:
            raise ValueError(
                'could not connect to clamd server either by unix or network socket'
            )

        scan_results = cd.scan_file(self.file.path)
        if scan_results is not None:
            send_mail('Django Virus Found',
                      'Virus found in file uploaded',
                      '*****@*****.**',
                      ['*****@*****.**'],
                      fail_silently=False)
            return True


#            super(photo, self).save(*args, **kwargs) # have to save object first to get the file in the right place
        try:
            im = Image.open(self.file.path)
            if im.verify() == True:
                self.is_photo = True
                # image rotation code from http://stackoverflow.com/a/11543365/2731298
                e = None
                if hasattr(im, '_getexif'):  # only present in JPEGs
                    for orientation in list(ExifTags.TAGS.keys()):
                        if ExifTags.TAGS[orientation] == 'Orientation':
                            break
                    e = im._getexif()  # returns None if no EXIF data
                if e is not None:
                    exif = dict(list(e.items()))
                    orientation = exif.get(orientation, None)
                    if orientation == 3: im = im.transpose(Image.ROTATE_180)
                    elif orientation == 6: im = im.transpose(Image.ROTATE_270)
                    elif orientation == 8: im = im.transpose(Image.ROTATE_90)

    #            im.thumbnail((1024,1024))
                im.save(self.file.path)
        except:
            return False
Пример #20
0
def attach(request, session_id):
    session = get_object_or_404(Session, uuid=session_id)
    session._request = request
    if request.method == 'POST':
        # Old versions of IE doing iframe uploads would present a Save dialog on JSON responses.
        content_type = 'text/plain' if request.POST.get('X-Requested-With', '') == 'IFrame' else 'application/json'
        try:
            f = request.FILES['attachment']
            file_uploaded.send(sender=f, request=request, session=session)
            # Copy the Django attachment (which may be a file or in memory) over to a temp file.
            temp_dir = getattr(settings, 'ATTACHMENT_TEMP_DIR', None)
            if temp_dir is not None and not os.path.exists(temp_dir):
                os.makedirs(temp_dir)
            fd, path = tempfile.mkstemp(dir=temp_dir)
            with os.fdopen(fd, 'wb') as fp:
                for chunk in f.chunks():
                    fp.write(chunk)
            # After attached file is placed in a temporary file and ATTACHMENTS_CLAMD is active scan it for viruses:
            if getattr(settings, 'ATTACHMENTS_CLAMD', False):
                import pyclamd
                cd = pyclamd.ClamdUnixSocket()
                virus = cd.scan_file(path)
                if virus is not None:
                    # if ATTACHMENTS_QUARANTINE_PATH is set, move the offending file to the quaranine, otherwise delete
                    if getattr(settings, 'ATTACHMENTS_QUARANTINE_PATH', False):
                        quarantine_path = os.path.join(getattr(settings, 'ATTACHMENTS_QUARANTINE_PATH'), os.path.basename(path))
                        os.rename(path, quarantine_path)
                    else:
                        os.remove(path)
                    raise VirusFoundException('**WARNING** virus %s found in the file %s, could not upload!' % (virus[path][1], f.name))
            session.uploads.create(file_path=path, file_name=f.name, file_size=f.size)
            for key, value in request.POST.items():
                if session.data:
                    session.data.update({key: value})
                else:
                    session.data = {key: value}
            session.save()
            return JsonResponse({'ok': True, 'file_name': f.name, 'file_size': f.size}, content_type=content_type)
        except VirusFoundException as ex:
            logger.exception(str(ex))
            return JsonResponse({'ok': False, 'error': force_text(ex)}, content_type=content_type)
        except Exception as ex:
            logger.exception('Error attaching file to session %s', session_id)
            return JsonResponse({'ok': False, 'error': force_text(ex)}, content_type=content_type)
    else:
        return render(request, session.template, {
            'session': session,
        })
Пример #21
0
def virusscan(fn, method='socket', socket='/tmp/clamd.socket'):
    out = {}
    if method != 'socket':
        raise NotImplementedError
    else:
        clam = pyclamd.ClamdUnixSocket(filename=socket)
        vers = clam.version().split('/')
        out['virusScannerVersion'] = vers[0]
        out['virusScannerSignatureVersion'] = vers[1]
        out['virusScannerSignatureDate'] = dateutil.parser.parse(
            vers[2]).strftime("%Y-%m-%dT%H:%M:%S")
        vscan = clam.scan_file(fn)
        if vscan is None:
            out['virusFound'] = 'false'
        else:
            out['virusFound'] = 'true'
            out['virusSignature'] = vscan[fn][1]
    return out
Пример #22
0
def get_clam():
    try:
        clam = pyclamd.ClamdUnixSocket()

        # test if server is reachable
        clam.ping()

        return clam
    except pyclamd.ConnectionError:
        # if failed, test for network socket
        try:
            cd = pyclamd.ClamdNetworkSocket()
            cd.ping()
            return cd
        except pyclamd.ConnectionError:
            raise ValueError(
                'could not connect to clamd server either by unix or network socket'
            )
Пример #23
0
    def run(self, obj, config):
        clamd_sock_path = str(config['clamd_sock_path'])
        clamd_host_name = str(config['clamd_host_name'])
        clamd_host_port = int(config['clamd_host_port'])
        clamd_force_reload = config['clamd_force_reload']

        try:
            self._debug('Attempting Unix socket connection to clamd')
            cd = pyclamd.ClamdUnixSocket(clamd_sock_path)
            cd.ping()
        except pyclamd.ConnectionError:
            try:
                self._debug('Attempting Network connection to clamd')
                cd = pyclamd.ClamdNetworkSocket(clamd_host_name,
                                                clamd_host_port)
                cd.ping()
            except pyclamd.ConnectionError:
                logger.error(
                    "clamd: Can\'t connect to Clamd\'s network socket.")
                self._error(
                    "clamd: Can\'t connect to Clamd\'s network socket.")
                return

        if clamd_force_reload:
            self._debug(cd.reload())
        cd_version = cd.version()
        self._debug(cd_version)
        try:
            output = cd.scan_stream(obj.filedata.read())
        except pyclamd.BufferTooLongError:
            logger.error("clamd: BufferTooLongError.")
            self._error("clamd: BufferTooLongError.")
            return
        except pyclamd.ConnectionError:
            logger.error("clamd: Can\'t connect to Clamd\'s socket.")
            self._error("clamd: Can\'t connect to Clamd\'s  socket.")
            return

        if output:
            out = output['stream']
            self._add_result('clamd', out[1], {'Status': out[0]})
            obj.add_bucket_list(out[1], self.current_task.user)
            obj.save(self.current_task.user)
            obj.reload()
Пример #24
0
def virus_scan(input_file):
    try:
        cd = pyclamd.ClamdUnixSocket()
        # test if server is reachable
        cd.ping()
    except pyclamd.ConnectionError:
        # if failed, test for network socket
        cd = pyclamd.ClamdNetworkSocket()
    try:
        cd.ping()
    except pyclamd.ConnectionError:
        raise ValueError('could not connect to clamd server either by unix or network socket')

    scan_results = cd.scan_file(input_file)
    if scan_results is not None:
        print 'Virus found:', scan_results[0]
        return True
    else:
        return False
Пример #25
0
def check():
    # Check with pyclamd if file is infected
    daemon = pyclamd.ClamdUnixSocket()
    virus_name = "root/Desktop/pyRAT/" + file_name
    results = daemon.scan_file(virus_name)

    if results:
        raise_frame(f4)
        rm(scan)
        process = subprocess.Popen(['clamscan', file_name],
                                   stdout=subprocess.PIPE)
        stdout = process.communicate()[0]
        Label(f4, text='Payload scanned:  {}'.format(stdout)).place(x=2, y=5)

        tkMessageBox.showinfo("File infected!!!", "MALWARE : %s" % results)
        Label(
            f4,
            text="Now we have to hide the payload in order to bypass the AVs!"
        ).place(x=2, y=240)
        enc = Button(root,
                     text="Hide payload",
                     bg='lightblue',
                     state=ACTIVE,
                     command=lambda: [peCloak(), rm(enc)])
        enc.place(relx=0.5, rely=0.96, anchor=CENTER)

    else:
        tkMessageBox.showinfo(
            "Awesome!!!",
            "File is clean. Wait and see the ClamAV's results... ")
        raise_frame(f4)
        process = subprocess.Popen(['clamscan', file_name],
                                   stdout=subprocess.PIPE)
        stdout = process.communicate()[0]
        Label(f4, text='Payload scanned: {}'.format(stdout)).place(x=2, y=5)
        Label(f4, text="Adios amigos!").place(x=2, y=240)

        adios = Button(root,
                       text="Quit",
                       bg='lightblue',
                       state=ACTIVE,
                       command=quit)
        adios.place(relx=0.5, rely=0.96, anchor=CENTER)
Пример #26
0
def scan(filelist, conf=DEFAULTCONF):
    results = []

    try:
        clamScanner = pyclamd.ClamdUnixSocket()
        clamScanner.ping()
    except:
        clamScanner = pyclamd.ClamdNetworkSocket()
        try:
            clamScanner.ping()
        except:
            raise ValueError("Unable to connect to clamd")

    # Scan each file from filelist for virus
    for f in filelist:
        output = clamScanner.scan_file(f)
        if output is None:
            continue

        if list(output.values())[0][0] == 'ERROR':
            with open(f, 'rb') as file_handle:
                try:
                    output = clamScanner.scan_stream(file_handle.read())
                except pyclamd.BufferTooLongError:
                    continue

        if output is None:
            continue

        if list(output.values())[0][0] == 'FOUND':
            results.append((f, list(output.values())[0][1]))
        elif list(output.values())[0][0] == 'ERROR':
            print('ClamAV: ERROR:', list(output.values())[0][1])

    # Set metadata tags
    metadata = {
        'Name': "ClamAV",
        'Type': "Antivirus",
        'Version': clamScanner.version()
    }

    return (results, metadata)
Пример #27
0
    def conn(self):
        connected = False
        try:
            self.clamObj = pyclamd.ClamdUnixSocket()
            self.clamObj.ping()
            connected = True

        except pyclamd.ConnectionError as e:
            print(e)
            print("trying ClamdNetworkSocket")

            try:
                self.clamObj = pyclamd.ClamdNetworkSocket()
                self.clamObj.ping()
                connected = True
            except pyclamd.ConnectionError as e:
                # todo: can chain an email here
                print(e)
                print(
                    "could not connect to clamd server either by unix or network socket"
                )
        return connected
Пример #28
0
def run_plugin(dump_obj, plugin_obj, params=None, user_pk=None):
    """
    Execute a single plugin on a dump with optional params.
    If success data are sent to elastic.
    """
    logging.info("[dump {} - plugin {}] start".format(dump_obj.pk,
                                                      plugin_obj.pk))
    try:
        ctx = contexts.Context()
        constants.PARALLELISM = constants.Parallelism.Off
        _ = framework.import_files(volatility3.plugins, True)
        automagics = automagic.available(ctx)
        plugin_list = framework.list_plugins()
        json_renderer = ReturnJsonRenderer
        seen_automagics = set()
        for amagic in automagics:
            if amagic in seen_automagics:
                continue
            seen_automagics.add(amagic)
        plugin = plugin_list.get(plugin_obj.name)
        base_config_path = "plugins"
        file_name = os.path.abspath(dump_obj.upload.path)
        single_location = "file:" + pathname2url(file_name)
        ctx.config["automagic.LayerStacker.single_location"] = single_location
        automagics = automagic.choose_automagic(automagics, plugin)
        if ctx.config.get("automagic.LayerStacker.stackers", None) is None:
            ctx.config[
                "automagic.LayerStacker.stackers"] = stacker.choose_os_stackers(
                    plugin)
        # LOCAL DUMPS REQUIRES FILES
        local_dump = plugin_obj.local_dump

        # ADD PARAMETERS, AND IF LOCAL DUMP ENABLE ADD DUMP TRUE BY DEFAULT
        plugin_config_path = interfaces.configuration.path_join(
            base_config_path, plugin.__name__)
        if params:
            # ADD PARAMETERS TO PLUGIN CONF
            for k, v in params.items():
                if v != "":
                    extended_path = interfaces.configuration.path_join(
                        plugin_config_path, k)
                    ctx.config[extended_path] = v

                if k == "dump" and v:
                    # IF DUMP TRUE HAS BEEN PASS IT'LL DUMP LOCALLY
                    local_dump = True

        if not params and local_dump:
            # IF ADMIN SET LOCAL DUMP ADD DUMP TRUE AS PARAMETER
            extended_path = interfaces.configuration.path_join(
                plugin_config_path, "dump")
            ctx.config[extended_path] = True

        logging.debug("[dump {} - plugin {}] params: {}".format(
            dump_obj.pk, plugin_obj.pk, ctx.config))

        file_list = []
        if local_dump:
            # IF PARAM/ADMIN DUMP CREATE FILECONSUMER
            local_path = "{}/{}/{}".format(settings.MEDIA_ROOT, dump_obj.index,
                                           plugin_obj.name)
            if not os.path.exists(local_path):
                os.mkdir(local_path)
            file_handler = file_handler_class_factory(output_dir=local_path,
                                                      file_list=file_list)
        else:
            local_path = None
            file_handler = file_handler_class_factory(output_dir=None,
                                                      file_list=file_list)

        # #####################
        # ## YARA
        # if not file or rule selected and exists default use that
        if plugin_obj.name in [
                "yarascan.YaraScan", "windows.vadyarascan.VadYaraScan"
        ]:
            if not params:
                has_file = False
            else:
                has_file = False
                for k, v in params.items():
                    if k in ["yara_file", "yara_compiled_file", "yara_rules"]:
                        if v is not None and v != "":
                            has_file = True

            if not has_file:
                rule = CustomRule.objects.get(user__pk=user_pk, default=True)
                if rule:
                    extended_path = interfaces.configuration.path_join(
                        plugin_config_path, "yara_compiled_file")
                    ctx.config[extended_path] = "file:{}".format(rule.path)

            logging.error("[dump {} - plugin {}] params: {}".format(
                dump_obj.pk, plugin_obj.pk, ctx.config))

        try:
            # RUN PLUGIN
            constructed = plugins.construct_plugin(
                ctx,
                automagics,
                plugin,
                base_config_path,
                MuteProgress(),
                file_handler,
            )
        except exceptions.UnsatisfiedException as excp:
            # LOG UNSATISFIED ERROR
            result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)
            result.result = 3
            result.description = "\n".join([
                excp.unsatisfied[config_path].description
                for config_path in excp.unsatisfied
            ])
            result.save()
            send_to_ws(dump_obj, result, plugin_obj.name)

            logging.error("[dump {} - plugin {}] unsatisfied".format(
                dump_obj.pk, plugin_obj.pk))

            return 0
        try:
            runned_plugin = constructed.run()
        except Exception as excp:
            # LOG GENERIC ERROR [VOLATILITY]
            fulltrace = traceback.TracebackException.from_exception(
                excp).format(chain=True)
            result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)
            result.result = 4
            result.description = "\n".join(fulltrace)
            result.save()
            send_to_ws(dump_obj, result, plugin_obj.name)
            logging.error("[dump {} - plugin {}] generic error".format(
                dump_obj.pk, plugin_obj.pk))
            return 0

        # RENDER OUTPUT IN JSON AND PUT IT IN ELASTIC
        json_data, error = json_renderer().render(runned_plugin)

        logging.debug("DATA: {}".format(json_data))
        logging.debug("ERROR: {}".format(error))
        logging.debug("CONFIG: {}".format(ctx.config))

        if len(json_data) > 0:

            # IF DUMP STORE FILE ON DISK
            if local_dump and file_list:
                for file_id in file_list:
                    output_path = "{}/{}".format(local_path,
                                                 file_id.preferred_filename)
                    with open(output_path, "wb") as f:
                        f.write(file_id.getvalue())

                # RUN CLAMAV ON ALL FOLDER
                if plugin_obj.clamav_check:
                    cd = pyclamd.ClamdUnixSocket()
                    match = cd.multiscan_file(local_path)
                    match = {} if not match else match
                else:
                    match = {}

                result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)

                # BULK CREATE EXTRACTED DUMP FOR EACH DUMPED FILE
                ExtractedDump.objects.bulk_create([
                    ExtractedDump(
                        result=result,
                        path="{}/{}".format(local_path,
                                            file_id.preferred_filename),
                        sha256=hash_checksum("{}/{}".format(
                            local_path, file_id.preferred_filename))[0],
                        md5=hash_checksum("{}/{}".format(
                            local_path, file_id.preferred_filename))[1],
                        clamav=(match["{}/{}".format(
                            local_path,
                            file_id.preferred_filename,
                        )][1] if "{}/{}".format(local_path,
                                                file_id.preferred_filename)
                                in match.keys() else None),
                    ) for file_id in file_list
                ])

                # RUN VT AND REGIPY AS DASK SUBTASKS
                if plugin_obj.vt_check or plugin_obj.regipy_check:
                    dask_client = get_client()
                    secede()
                    tasks = []
                    for file_id in file_list:
                        if plugin_obj.vt_check:
                            task = dask_client.submit(
                                run_vt,
                                result.pk,
                                "{}/{}".format(local_path,
                                               file_id.preferred_filename),
                            )
                            tasks.append(task)
                        if plugin_obj.regipy_check:
                            task = dask_client.submit(
                                run_regipy,
                                result.pk,
                                "{}/{}".format(local_path,
                                               file_id.preferred_filename),
                            )
                            tasks.append(task)
                    _ = dask_client.gather(tasks)
                    rejoin()

            es = Elasticsearch(
                [settings.ELASTICSEARCH_URL],
                request_timeout=60,
                timeout=60,
                max_retries=10,
                retry_on_timeout=True,
            )
            helpers.bulk(
                es,
                gendata(
                    "{}_{}".format(dump_obj.index, plugin_obj.name.lower()),
                    json_data,
                    {
                        "orochi_dump":
                        dump_obj.name,
                        "orochi_plugin":
                        plugin_obj.name.lower(),
                        "orochi_os":
                        dump_obj.get_operating_system_display(),
                        "orochi_createdAt":
                        datetime.datetime.now().replace(
                            microsecond=0).isoformat(),
                    },
                ),
            )

            # set max_windows_size on new created index
            es.indices.put_settings(
                index="{}_{}".format(dump_obj.index, plugin_obj.name.lower()),
                body={
                    "index": {
                        "max_result_window": settings.MAX_ELASTIC_WINDOWS_SIZE
                    }
                },
            )

            # EVERYTHING OK
            result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)
            result.result = 2
            result.description = error
            result.save()

            logging.debug("[dump {} - plugin {}] sent to elastic".format(
                dump_obj.pk, plugin_obj.pk))
        else:
            # OK BUT EMPTY
            result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)
            result.result = 1
            result.description = error
            result.save()

            logging.debug("[dump {} - plugin {}] empty".format(
                dump_obj.pk, plugin_obj.pk))
        send_to_ws(dump_obj, result, plugin_obj.name)
        return 0

    except Exception as excp:
        # LOG GENERIC ERROR [ELASTIC]
        fulltrace = traceback.TracebackException.from_exception(excp).format(
            chain=True)
        result = Result.objects.get(plugin=plugin_obj, dump=dump_obj)
        result.result = 4
        result.description = "\n".join(fulltrace)
        result.save()
        send_to_ws(dump_obj, result, plugin_obj.name)
        logging.error("[dump {} - plugin {}] generic error".format(
            dump_obj.pk, plugin_obj.pk))
        return 0
Пример #29
0
#!/usr/bin/env python
import pyclamd
import logging
import sys
# setup logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

clam_instance = None
try:
    clam_instance = pyclamd.ClamdUnixSocket('/var/run/clamd.scan/clamd.sock')
    clam_instance.ping()
except Exception, e:
    logger.error("Error while establishing connection with Clamd daemon")
    sys.exit(1)
if clam_instance:
    r = clam_instance.scan_file('/home/joshi/bootstrap-4.0.0-dist.zip')
    # if no virus, response is None. Otherwise virus information is returned in response.
    print r is None

# eicar test
# create eicar file
void = open('/home/joshi/eicar', 'wb').write(clam_instance.EICAR())

r = clam_instance.scan_file('/home/joshi/eicar')
#Out[16]: {'/home/joshi/eicar': ('FOUND', 'Eicar-Test-Signature')}

print r['/home/joshi/eicar']
#('FOUND', 'Eicar-Test-Signature')

print r['/home/joshi/eicar'][0]
Пример #30
0
logger = logging.getLogger(__name__)

ANTIVIRUS_ON = settings.CLAMAV['enabled']

if ANTIVIRUS_ON:
    try:
        import pyclamd

        if settings.CLAMAV['socket'] is None:
            host, port = settings.CLAMAV['address'].split(':')
            logger.info("Connecting to clamd via tcp socket...")
            clam = pyclamd.ClamdNetworkSocket(host=str(host), port=int(port))
        else:
            logger.info("Connecting to clamd via unix socket...")
            clam = pyclamd.ClamdUnixSocket(filename=settings.CLAMAV['socket'])
        clam.ping()
        logger.info("Clamd connection established")

    except Exception as err:
        logger.warn('Problem with ClamAV: {}'.format(str(err)))
        clam = None


def is_infected(stream):
    """
    Create tmp file and scan it with ClamAV
    Returns
        True, 'Virus name' - if virus detected
        False, '' - if not virus detected
        None, '' - status unknown (pyclamd not installed)