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 ''
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))
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
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
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}, )
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
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)
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
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
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
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
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
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
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
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()
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
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()
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
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
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, })
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
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' )
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()
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
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)
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)
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
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
#!/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]
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)