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);
+ }
}