def eval_list(self, value_file, ioc_list): if self.__bypass: return evltResult.UNDEF # private attribute for child class rc = self.getRemoteCommand() wd = self.getWD() result = {} ioc_list = self.filter_ioc_list(ioc_list) if len(ioc_list) == 0: return result file_name, file_content = self.file_from_ioc_list(ioc_list) self.log('Loading file %s' % file_name, logging.DEBUG) with open(value_file, 'w') as f: f.write(file_content) if self.__confidential: raise NotImplementedError # Local SQLITE3 instance # TODO: do it # sqlite3loc = os.path.join(LOCAL_ANALYSIS_DIR, 'sqlite3.exe') # dbloc = os.path.join(self.dirname, self.__dbName) # localcommand = 'type "%s" | "%s" "%s"' % (value_file, sqlite3loc, dbloc) # res = os.popen(localcommand).read().replace('\r', '').replace('\n', '') else: rc.dropFile(value_file, file_name, True, False) file_identifier = '%s.%s' % (threadname, ioc_list[0].document.lower()) results_filename = '%s.tar.gz' % (file_identifier) # self.log('Running the sql file %s' % file_name, logging.DEBUG) rc.execCommand('type %s | sqlite3 %s' % (file_name, self.__dbName), wd) # self.log('Compressing results from %s' % file_identifier, logging.DEBUG) rc.execCommand('getresults.bat %s' % (file_identifier), wd) # self.log('Downloading results from %s' % results_filename, logging.DEBUG) # TODO: find a clean way to get the localanalysis directory extract_dir = os.path.join( os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'resources', 'localanalysis') rc.getFile(results_filename, os.path.join(extract_dir, results_filename)) rc.deleteFile(results_filename) self.log( 'Extracting results from %s' % os.path.join(extract_dir, results_filename), logging.DEBUG) tarname = os.path.join(extract_dir, results_filename) tar = tarfile.open(tarname, 'r:gz') # 'r|gz' might be used for better perf & stream-mode reading ? self.log('Found %s' % tar.getnames(), logging.DEBUG) for member in tar.getmembers(): f = tar.extractfile(member) tmp_data = f.read() tmp_id = member.name.split('.')[2] tmp_db_ioc_id = member.name.split('.')[3] ret = evltResult.TRUE res_data = None if tmp_data == '': ret = evltResult.UNDEF elif tmp_data == '0\n' or tmp_data == '\x01\n': ret = evltResult.FALSE elif tmp_data[:1] == '\x01': res_data = [ e.decode(sys.stdout.encoding) for e in tmp_data.splitlines()[1:] ] result[tmp_id] = { 'res': evltResult._str(ret), 'iocid': tmp_db_ioc_id, 'data': res_data } tar.close() if not self.__keepFiles: os.remove(tarname) return result
def eval(self, valueFile, iocList=None): if iocList is not None: return self.eval_list(valueFile, iocList) if self.getIOC() is None: return AttributeError if self.__bypass: return evltResult.UNDEF # private attribute for child class ioc = self.getIOC() rc = self.getRemoteCommand() wd = self.getWD() select = ioc.select.replace('%s/' % ioc.document, '') self.log('IOC : %s' % (ioc), logging.DEBUG) # Hey, I don't know how to search for that if (ioc.search.lower() not in self.__evalList)\ or (ioc.condition not in conditionList.keys()): self.log( '%s/%s is not in evaluation list' % (ioc.search, ioc.condition), logging.WARNING) return (evltResult.UNDEF, None) if select and select.lower() not in self.__evalList: self.log( 'Could not select %s (not in evaluation list)' % (ioc.select), logging.WARNING) select = '' category = ioc.search.replace('%s/' % ioc.document, '') conditionTerm = conditionList[ioc.condition] # Escape '\' not using REGEX condition = conditionTerm % self.escapeValue( ioc.value ) if ioc.condition != 'regex' else conditionTerm % ioc.value # Craft query # > selecting count by default, otherwise selecting the user defined element # SELECT COUNT * FROM <table> WHERE <index> LIKE <value> (default example) # SELECT FilePath FROM <table> WHERE <index> LIKE <value> (user defined example) querySelect = 'COUNT(*)' if not select else ('`%s`' % select) queryStart = 'SELECT %s FROM %s WHERE ' % (querySelect, self.__tableName) queryVariable = '`%(index)s` %(clause)s' % { 'index': category, 'clause': (condition) } queryEnd = ';' if not select else ' UNION SELECT CHAR(1);' query = queryStart + queryVariable + queryEnd # Load PCRE for REGEX support loadext = 'SELECT load_extension("pcre.so");\n' queryContent = query res = '' retryCount = 15 # Sometimes, queries may return "" (empty result) # Happens randomly, so just retry until it does not happen anymore while res == '' and retryCount > 0: self.log('query=%s' % query, logging.DEBUG) f = open(valueFile, 'w') f.write(loadext) f.write(queryContent) f.close() if self.__confidential: # Local SQLITE3 instance sqlite3loc = os.path.join(LOCAL_ANALYSIS_DIR, 'sqlite3.exe') dbloc = os.path.join(self.dirname, self.__dbName) localcommand = 'type "%s" | "%s" "%s"' % (valueFile, sqlite3loc, dbloc) res = os.popen(localcommand).read().replace('\r', '').replace( '\n', '') else: rc.dropFile(valueFile, 'query.sql', True, False) res = rc.execCommand( 'type query.sql | sqlite3 %s' % self.__dbName, wd) rc.deleteFile('query.sql') self.log('query returned "%s"' % res, logging.DEBUG) retryCount -= 1 ret = evltResult.TRUE if res == '': ret = evltResult.UNDEF elif res == '0' or res == '\x01': ret = evltResult.FALSE resData = res.splitlines()[1:] if select else None return (evltResult._str(ret), resData)