feat: scan mods for malware (specifically Fractureiser for now) before launching an instance

This commit is contained in:
Ryan Dowling 2023-06-10 22:15:00 +10:00
parent 157d465a21
commit de45c7d2c2
No known key found for this signature in database
GPG key ID: 5539FCDB88950EFD
7 changed files with 129 additions and 3 deletions

View file

@ -3,9 +3,10 @@
This changelog only contains the changes that are unreleased. For changes for individual releases, please visit the
[releases](https://github.com/ATLauncher/ATLauncher/releases) page on GitHub.
## 3.4.28.2O
## 3.4.29.0
### New Features
- Scan mods for malware (specifically Fractureiser for now) before launching an instance
### Fixes
- Make Console sizing a bit more responsive and flexible with sizes

View file

@ -49,6 +49,7 @@ repositories {
includeGroup "com.github.RyanTheAllmighty.gettext"
includeGroup "com.github.Vatuu"
includeGroup "com.gitlab.doomsdayrs"
includeGroup "com.github.MCRcortex"
}
}
}
@ -85,6 +86,7 @@ dependencies {
implementation 'com.apollographql.apollo:apollo-runtime:2.5.14'
implementation 'com.apollographql.apollo:apollo-http-cache:2.5.14'
implementation 'com.apollographql.apollo:apollo-rx3-support:2.5.14'
implementation 'com.github.MCRcortex:nekodetector:Version-1.1-pre'
// RxJava
implementation("io.reactivex.rxjava3:rxjava:3.1.6")

View file

@ -159,6 +159,7 @@ import com.atlauncher.utils.Hashing;
import com.atlauncher.utils.Java;
import com.atlauncher.utils.ModrinthApi;
import com.atlauncher.utils.OS;
import com.atlauncher.utils.SecurityUtils;
import com.atlauncher.utils.Utils;
import com.atlauncher.utils.ZipNameMapper;
import com.google.gson.JsonArray;
@ -841,7 +842,21 @@ public class Instance extends MinecraftVersion {
}
PerformanceManager.end("Creating custom minecraft.jar");
}
progressDialog.doneTask();
if (App.settings.scanModsOnLaunch) {
PerformanceManager.start("Scanning mods for Fractureiser");
progressDialog.setLabel(GetText.tr("Scanning mods for Fractureiser"));
List<Path> foundInfections = SecurityUtils.scanForFractureiser(this.getModPathsFromFilesystem());
PerformanceManager.end("Scanning mods for Fractureiser");
if (foundInfections.size() != 0) {
LogManager.error("Infections have been found in your mods. See the below list of paths");
foundInfections.forEach(p -> LogManager.error(p.toAbsolutePath().toString()));
return false;
}
}
progressDialog.doneTask();
PerformanceManager.end();
@ -937,7 +952,7 @@ public class Instance extends MinecraftVersion {
}
ProgressDialog<Boolean> prepareDialog = new ProgressDialog<>(GetText.tr("Preparing For Launch"),
LWJGLManager.shouldUseLegacyLWJGL(this) ? 8 : 7,
9,
GetText.tr("Preparing For Launch"));
prepareDialog.addThread(new Thread(() -> {
LogManager.info("Preparing for launch!");
@ -3069,6 +3084,33 @@ public class Instance extends MinecraftVersion {
return launcher.version;
}
private List<Path> getModPathsFromFilesystem() {
return getModPathsFromFilesystem(Arrays.asList(ROOT.resolve("mods"),
ROOT.resolve("resourcepacks"),
ROOT.resolve("shaderpacks"),
ROOT.resolve("jarmods")));
}
public List<Path> getModPathsFromFilesystem(List<Path> paths) {
List<Path> files = new ArrayList<>();
for (Path path : paths) {
if (!Files.exists(path)) {
continue;
}
try (Stream<Path> stream = Files.list(path)) {
files.addAll(stream
.filter(file -> !Files.isDirectory(file) && Utils.isAcceptedModFile(file))
.collect(Collectors.toList()));
} catch (IOException e) {
LogManager.logStackTrace("Error getting mod paths", e);
}
}
return files;
}
public void scanMissingMods() {
scanMissingMods(App.launcher.getParent());
}

View file

@ -81,6 +81,7 @@ public class Settings {
public boolean useNativeFilePicker = OS.isMac();
public boolean useRecycleBin = true;
public boolean enableArmSupport = true;
public boolean scanModsOnLaunch = true;
// Mods
public ModPlatform defaultModPlatform = ModPlatform.CURSEFORGE;

View file

@ -75,6 +75,7 @@ public class GeneralSettingsTab extends AbstractSettingsTab {
private final JCheckBox useNativeFilePicker;
private final JCheckBox useRecycleBin;
private JCheckBox enableArmSupport;
private JCheckBox scanModsOnLaunch;
public GeneralSettingsTab() {
// Language
@ -537,6 +538,25 @@ public class GeneralSettingsTab extends AbstractSettingsTab {
enableArmSupport.setSelected(App.settings.enableArmSupport);
add(enableArmSupport, gbc);
}
// Enable scanning mods on launch
gbc.gridx = 0;
gbc.gridy++;
gbc.insets = UIConstants.LABEL_INSETS;
gbc.anchor = GridBagConstraints.BASELINE_TRAILING;
JLabelWithHover scanModsOnLaunchLabel = new JLabelWithHover(GetText.tr("Scan Mods On Launch?"), HELP_ICON,
new HTMLBuilder().center().split(100)
.text(GetText.tr(
"This will scan the mods in instances before launching to ensure they do not contain malware or have been modified since installing."))
.build());
add(scanModsOnLaunchLabel, gbc);
gbc.gridx++;
gbc.insets = UIConstants.CHECKBOX_FIELD_INSETS;
gbc.anchor = GridBagConstraints.BASELINE_LEADING;
scanModsOnLaunch = new JCheckBox();
scanModsOnLaunch.setSelected(App.settings.scanModsOnLaunch);
add(scanModsOnLaunch, gbc);
}
@SuppressWarnings("unchecked")

View file

@ -0,0 +1,60 @@
/*
* ATLauncher - https://github.com/ATLauncher/ATLauncher
* Copyright (C) 2013-2022 ATLauncher
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.atlauncher.utils;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.jar.JarFile;
import com.atlauncher.managers.LogManager;
import me.cortex.jarscanner.Detector;
public class SecurityUtils {
public static List<Path> scanForFractureiser(List<Path> paths) {
Function<String, String> logOutput = outputString -> {
LogManager.error(outputString);
return outputString;
};
List<Path> infectionsFound = Collections.synchronizedList(new ArrayList<>());
ExecutorService executor = Executors.newFixedThreadPool(4);
for (final Path path : paths) {
executor.submit(() -> {
LogManager.debug(String.format("Scanning %s for Fractureiser", path.toAbsolutePath().toString()));
try (JarFile scannableJarFile = new JarFile(path.toFile())) {
if (Detector.scan(scannableJarFile, path, logOutput)) {
infectionsFound.add(path);
}
} catch (Exception e) {
LogManager.error(
String.format("Failed to scan %s for Fractureiser", path.toAbsolutePath().toString()));
}
});
}
return infectionsFound;
}
}

View file

@ -1 +1 @@
3.4.28.2.Beta
3.4.29.0.Beta