From 02e668e4b07a5d5c30582949699ad6d81ad18d37 Mon Sep 17 00:00:00 2001 From: Optic_Fusion1 <37254722+OpticFusion1@users.noreply.github.com> Date: Wed, 17 Feb 2021 00:11:15 -0500 Subject: [PATCH] Changes Bumps version Adds a new detection method (currently only detects qlutch) --- MCAntiMalware-Core/pom.xml | 2 +- .../database/AntiMalwareDatabase.java | 24 + .../mcantimalware/scanner/Scanner.java | 423 +++++++++--------- 3 files changed, 240 insertions(+), 209 deletions(-) diff --git a/MCAntiMalware-Core/pom.xml b/MCAntiMalware-Core/pom.xml index 29e90fa9..d32bf58c 100644 --- a/MCAntiMalware-Core/pom.xml +++ b/MCAntiMalware-Core/pom.xml @@ -12,7 +12,7 @@ MCAntiMalware jar - 8.4.4 + 8.5 diff --git a/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/database/AntiMalwareDatabase.java b/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/database/AntiMalwareDatabase.java index 74aa50ab..370ee533 100644 --- a/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/database/AntiMalwareDatabase.java +++ b/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/database/AntiMalwareDatabase.java @@ -239,6 +239,30 @@ public boolean isWebsiteBlacklisted(String website) { return a(isWebsiteBlacklisted, website); } + private final String isFileNameBlacklisted = "SELECT count(*) FROM BlacklistedFileNames WHERE Name LIKE ?"; + + public boolean isFileNameBlacklisted(String fileName){ + return a(isFileNameBlacklisted, fileName); + } + + private final String fileNameToCheckResult = "SELECT type, platform, family, variant FROM BlacklistedFileNames INNER JOIN MalwareChecks ON BlacklistedFileNames.MalwareID = MalwareChecks._rowid_ WHERE Name = ?"; + + public CheckResult blacklistedFileNameToCheckResult(String fileName) { + try { + PreparedStatement pSt = connection.prepareStatement(fileNameToCheckResult); + pSt.setString(1, fileName); + try (ResultSet rs = pSt.executeQuery()) { + if (rs.next()) { + return new CheckResult(rs.getString("platform"), rs.getString("type"), rs.getString("family"), + rs.getString("variant")); + } + } + } catch (SQLException ex) { + logger.exception(ex); + } + return null; + } + //TOOD: Come up with a proper name for the method and "a" parameter private boolean a(String query, String a) { try { diff --git a/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/scanner/Scanner.java b/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/scanner/Scanner.java index 210b6f53..dbd1b9f5 100644 --- a/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/scanner/Scanner.java +++ b/MCAntiMalware-Core/src/main/java/optic_fusion1/mcantimalware/scanner/Scanner.java @@ -19,6 +19,7 @@ import optic_fusion1.mcantimalware.check.CacheContainer; import optic_fusion1.mcantimalware.check.CheckManager; import optic_fusion1.mcantimalware.check.CheckResult; +import optic_fusion1.mcantimalware.database.AntiMalwareDatabase; import optic_fusion1.mcantimalware.logging.CustomLogger; import optic_fusion1.mcantimalware.notification.NotificationHandler; import optic_fusion1.mcantimalware.utils.FileSizeComparator; @@ -28,213 +29,219 @@ public abstract class Scanner implements Runnable { - private static final Queue SCANNABLE_FILES = new ConcurrentLinkedQueue<>(); - private ThreadPoolExecutor executorService; - protected final Main main; - protected final CustomLogger logger; - protected final File scanDirectory; - protected final CheckManager checkManager; - protected final CommandLineParser commandLineParser; - private NotificationHandler notificationHandler; - - public Scanner(Main main, File scanDirectory) { - this.main = main; - this.logger = main.getLogger(); - checkManager = main.getCheckManager(); - commandLineParser = main.getCommandLineParser(); - this.scanDirectory = scanDirectory; - notificationHandler = main.getNotificationHandler(); - } - - @Override - public void run() { - try { - Path file = SCANNABLE_FILES.remove(); - if (file == null) { - return; - } - scanFile(file); - } catch (Exception e) { - logger.exception(e); - } - if (SCANNABLE_FILES.size() % 100 == 0) { - System.out.println(I18n.tl("remaining_files", SCANNABLE_FILES.size())); - } - } - - public void scanFiles() { - FileSizeComparator comparator = new FileSizeComparator(); - logger.info(I18n.tl("scan_start")); - try { - Files.walk(scanDirectory.toPath()).filter(Files::isRegularFile).sorted(comparator) - .forEachOrdered(this::addFileToQueue); - } catch (IOException e) { - logger.exception(e); - } - } - - private void scanDirectory(Path directory) { - if (!Files.isDirectory(directory)) { - scanFile(directory); - return; - } - try { - Files.list(directory).forEach((path) -> { - if (path.getFileSystem().isOpen()) { - if (Files.isDirectory(path)) { - scanDirectory(path); - } else { - scanFile(path); - } - } - }); - } catch (IOException e) { - logger.exception(e); - } - } - - private void scanFile(Path file) { - if (Files.isDirectory(file)) { - scanDirectory(file); - return; - } - String fileName = file.getFileName().toString(); - if (!fileName.endsWith(".jar") && !fileName.endsWith(".zip") && !fileName.endsWith(".rar")) { - return; - } - try { - if (Files.size(file) == 0) { - return; - } - } catch (IOException e) { - logger.exception(e); - return; - } - try (FileSystem fs = Utils.fileSystemForZip(file)) { - if (fs == null) { - return; - } - Path rootFolder = fs.getRootDirectories().iterator().next(); - - if (commandLineParser.shouldScanZippedFiles()) { - if (fileName.endsWith(".zip") || fileName.endsWith(".rar")) { - scanDirectory(rootFolder); - return; - } - } - WhitelistResult result = isFileWhitelisted(file); - if (result == WhitelistResult.INVALID_FILE || result == WhitelistResult.WHITELISTED) { - return; - } - CacheContainer ccc = new CacheContainer(); - for (BaseCheck check : checkManager.getChecks()) { - List results; - try { - results = check.process(rootFolder, file, ccc); - if (results != null && !results.isEmpty()) { - results.stream().forEachOrdered(checkResult -> { - sendNotification(file, checkResult); - }); - } - } catch (Exception e) { - logger.exception(e); - continue; - } - check.reset(); - } - } catch (IOException ex) { - logger.exception(ex); - } catch (ZipError zip) { - logger.warn("[ERR] Zip File " + file.toString() + " can't be read!"); - } - } - - public enum WhitelistResult { - INVALID_FILE, NOT_WHITELISTED, WHITELISTED; - } - - private WhitelistResult isFileWhitelisted(Path file) { - try { - if (file == null || Files.size(file) == 0) { - return WhitelistResult.INVALID_FILE; - } - String fileChecksum = DigestUtils.sha1Hex(Files.newInputStream(file)); - WhitelistResult result = isChecksumWhitelisted(fileChecksum); - if (result == WhitelistResult.WHITELISTED && commandLineParser.shouldPrintNotInfectedMessages()) { - logger.info(I18n.tl("probably_safe_whitelist", file.getFileName().toString())); - } - return result; - } catch (IOException e) { - logger.exception(e); - } - return WhitelistResult.NOT_WHITELISTED; - } - - public void addFileToQueue(Path file) { - if (Files.isDirectory(file)) { - addDirectoryToQueue(file); - return; - } - SCANNABLE_FILES.add(file); - if (executorService == null) { - executorService = new ThreadPoolExecutor(4, Math.max(Runtime.getRuntime().availableProcessors(), 4), 10, - TimeUnit.SECONDS, new ArrayBlockingQueue<>(50000)); - executorService.allowCoreThreadTimeOut(true); - } - executorService.execute(this); - } - - public void addDirectoryToQueue(Path dir) { - if (!Files.isDirectory(dir)) { - return; - } - try { - Files.list(dir).forEach(this::addFileToQueue); - } catch (IOException e) { - logger.exception(e); - } - } - - public boolean awaitTermination(int time, TimeUnit unit) { - try { - return executorService.awaitTermination(time, unit); - } catch (InterruptedException e) { - } - return false; - } - - private WhitelistResult isChecksumWhitelisted(String checksum) { - return main.getDatabase().isChecksumWhitelisted(checksum) ? WhitelistResult.WHITELISTED - : WhitelistResult.NOT_WHITELISTED; - } - - public enum Status { - SCANNING, WAITING, NOT_RUNNING; - } - - public Status getStatus() { - if (executorService == null) { - return Status.NOT_RUNNING; - } else if (executorService.getTaskCount() == 0) { - return Status.WAITING; - } else { - return Status.SCANNING; - } - } - - public File getScanDirectory() { - return scanDirectory; - } - - public Main getMain() { - return main; - } - - public void sendNotification(Path path, CheckResult result) { - // TODO: Make these translatable - Objects.requireNonNull(path, "Path cannot be null"); - Objects.requireNonNull(result, "CheckResult cannot be null"); - notificationHandler.sendNotification(path, result); - } + private static final Queue SCANNABLE_FILES = new ConcurrentLinkedQueue<>(); + private ThreadPoolExecutor executorService; + protected final Main main; + protected final CustomLogger logger; + protected final File scanDirectory; + protected final CheckManager checkManager; + protected final CommandLineParser commandLineParser; + private NotificationHandler notificationHandler; + private AntiMalwareDatabase database; + + public Scanner(Main main, File scanDirectory) { + this.main = main; + database = main.getDatabase(); + this.logger = main.getLogger(); + checkManager = main.getCheckManager(); + commandLineParser = main.getCommandLineParser(); + this.scanDirectory = scanDirectory; + notificationHandler = main.getNotificationHandler(); + } + + @Override + public void run() { + try { + Path file = SCANNABLE_FILES.remove(); + if (file == null) { + return; + } + scanFile(file); + } catch (Exception e) { + logger.exception(e); + } + if (SCANNABLE_FILES.size() % 100 == 0) { + System.out.println(I18n.tl("remaining_files", SCANNABLE_FILES.size())); + } + } + + public void scanFiles() { + FileSizeComparator comparator = new FileSizeComparator(); + logger.info(I18n.tl("scan_start")); + try { + Files.walk(scanDirectory.toPath()).filter(Files::isRegularFile).sorted(comparator) + .forEachOrdered(this::addFileToQueue); + } catch (IOException e) { + logger.exception(e); + } + } + + private void scanDirectory(Path directory) { + if (!Files.isDirectory(directory)) { + scanFile(directory); + return; + } + try { + Files.list(directory).forEach((path) -> { + if (path.getFileSystem().isOpen()) { + if (Files.isDirectory(path)) { + scanDirectory(path); + } else { + scanFile(path); + } + } + }); + } catch (IOException e) { + logger.exception(e); + } + } + + private void scanFile(Path file) { + if (Files.isDirectory(file)) { + scanDirectory(file); + return; + } + String fileName = file.getFileName().toString(); + if (!fileName.endsWith(".jar") && !fileName.endsWith(".zip") && !fileName.endsWith(".rar")) { + return; + } + if(database.isFileNameBlacklisted(fileName)){ + sendNotification(file.toAbsolutePath(), database.blacklistedFileNameToCheckResult(fileName)); + return; + } + try { + if (Files.size(file) == 0) { + return; + } + } catch (IOException e) { + logger.exception(e); + return; + } + try (FileSystem fs = Utils.fileSystemForZip(file)) { + if (fs == null) { + return; + } + Path rootFolder = fs.getRootDirectories().iterator().next(); + + if (commandLineParser.shouldScanZippedFiles()) { + if (fileName.endsWith(".zip") || fileName.endsWith(".rar")) { + scanDirectory(rootFolder); + return; + } + } + WhitelistResult result = isFileWhitelisted(file); + if (result == WhitelistResult.INVALID_FILE || result == WhitelistResult.WHITELISTED) { + return; + } + CacheContainer ccc = new CacheContainer(); + for (BaseCheck check : checkManager.getChecks()) { + List results; + try { + results = check.process(rootFolder, file, ccc); + if (results != null && !results.isEmpty()) { + results.stream().forEachOrdered(checkResult -> { + sendNotification(file, checkResult); + }); + } + } catch (Exception e) { + logger.exception(e); + continue; + } + check.reset(); + } + } catch (IOException ex) { + logger.exception(ex); + } catch (ZipError zip) { + logger.warn("[ERR] Zip File " + file.toString() + " can't be read!"); + } + } + + public enum WhitelistResult { + INVALID_FILE, NOT_WHITELISTED, WHITELISTED; + } + + private WhitelistResult isFileWhitelisted(Path file) { + try { + if (file == null || Files.size(file) == 0) { + return WhitelistResult.INVALID_FILE; + } + String fileChecksum = DigestUtils.sha1Hex(Files.newInputStream(file)); + WhitelistResult result = isChecksumWhitelisted(fileChecksum); + if (result == WhitelistResult.WHITELISTED && commandLineParser.shouldPrintNotInfectedMessages()) { + logger.info(I18n.tl("probably_safe_whitelist", file.getFileName().toString())); + } + return result; + } catch (IOException e) { + logger.exception(e); + } + return WhitelistResult.NOT_WHITELISTED; + } + + public void addFileToQueue(Path file) { + if (Files.isDirectory(file)) { + addDirectoryToQueue(file); + return; + } + SCANNABLE_FILES.add(file); + if (executorService == null) { + executorService = new ThreadPoolExecutor(4, Math.max(Runtime.getRuntime().availableProcessors(), 4), 10, + TimeUnit.SECONDS, new ArrayBlockingQueue<>(50000)); + executorService.allowCoreThreadTimeOut(true); + } + executorService.execute(this); + } + + public void addDirectoryToQueue(Path dir) { + if (!Files.isDirectory(dir)) { + return; + } + try { + Files.list(dir).forEach(this::addFileToQueue); + } catch (IOException e) { + logger.exception(e); + } + } + + public boolean awaitTermination(int time, TimeUnit unit) { + try { + return executorService.awaitTermination(time, unit); + } catch (InterruptedException e) { + } + return false; + } + + private WhitelistResult isChecksumWhitelisted(String checksum) { + return main.getDatabase().isChecksumWhitelisted(checksum) ? WhitelistResult.WHITELISTED + : WhitelistResult.NOT_WHITELISTED; + } + + public enum Status { + SCANNING, WAITING, NOT_RUNNING; + } + + public Status getStatus() { + if (executorService == null) { + return Status.NOT_RUNNING; + } else if (executorService.getTaskCount() == 0) { + return Status.WAITING; + } else { + return Status.SCANNING; + } + } + + public File getScanDirectory() { + return scanDirectory; + } + + public Main getMain() { + return main; + } + + public void sendNotification(Path path, CheckResult result) { + // TODO: Make these translatable + Objects.requireNonNull(path, "Path cannot be null"); + Objects.requireNonNull(result, "CheckResult cannot be null"); + notificationHandler.sendNotification(path, result); + } }