Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve stage 2 detection #50

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 58 additions & 35 deletions src/main/java/me/cortex/jarscanner/Detector.java
Original file line number Diff line number Diff line change
Expand Up @@ -303,61 +303,84 @@ public static boolean scanClass(byte[] clazz) {
}

/**
* Checks for signs of stage 2 infection and returns a list of files that are flagged as suspicious.
* Checks for signs of stage 2 infection and returns a list of files that are
* flagged as suspicious.
* Based on:
* https://github.com/fractureiser-investigation/fractureiser#am-i-infected
* https://prismlauncher.org/news/cf-compromised-alert/#automated-script
*/
public static List<String> checkForStage2() {
public static List<String> checkForStage2(Function<String, String> output) {
// Create list to store suspicious files found
List<String> suspiciousFilesFound = new ArrayList<>();

// windows checks
Path windowsStartupDirectory = (Objects.isNull(System.getenv("APPDATA"))
? Paths.get(System.getProperty("user.home"), "AppData", "Roaming")
: Paths.get(System.getenv("APPDATA"), new String[0]))
.resolve(Paths.get("Microsoft", "Windows", "Start Menu", "Programs", "Startup"));
boolean windows = Files.isDirectory(windowsStartupDirectory, new LinkOption[0])
&& Files.isWritable(windowsStartupDirectory);

String[] maliciousFiles = {
".ref",
"client.jar",
"lib.dll",
"libWebGL64.jar",
"run.bat"
};
Path userHome = Paths.get(System.getProperty("user.home"));

String os = System.getProperty("os.name").toLowerCase();
boolean windows = os.contains("windows");

File dataFolder;

if (windows) {
// only checking for the folder because the file can be renamed
File edgeFolder = new File(System.getenv("APPDATA") + "\\Microsoft Edge");
if (edgeFolder.exists()) {
suspiciousFilesFound.add(edgeFolder.getAbsolutePath());
}
Path windowsAppData = Paths.get(userHome.toString(), "AppData");
dataFolder = Paths.get(windowsAppData.toString(), "Local", "Microsoft Edge").toFile();

File startFolder = new File("Microsoft\\Windows\\Start Menu\\Programs\\Startup");
// get all files in the startup folder, and check if they match the malicious
Path windowsStartupDirectory = Paths.get(windowsAppData.toString(), "Roaming", "Microsoft", "Windows",
"Start Menu", "Programs", "Startup");

File startFolder = windowsStartupDirectory.toFile();
// check for run.bat (or a shortcut to it)
if (startFolder.exists() && startFolder.isDirectory()) {
File[] startFiles = startFolder.listFiles();

for (int i = 0; i < startFiles.length; i++) {

for (int j = 0; j < maliciousFiles.length; j++) {
if (startFiles[i].getName().equals(maliciousFiles[j])) {
suspiciousFilesFound.add(startFiles[i].getAbsolutePath());
}
for (File startFile : startFiles) {
if (startFile.getName().contains("run.bat")) {
suspiciousFilesFound.add(startFile.getAbsolutePath());
}
}
}

// check for known registry key used to start run.bat
String err = "Couldn't run reg.exe! Please check HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\t manually";
String regKey = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\t";
try {
Process regQuery = Runtime.getRuntime()
.exec("reg.exe query " + regKey);
regQuery.waitFor();

int returnCode = regQuery.exitValue();
if (returnCode == 0) {
suspiciousFilesFound.add(regKey);
}
} catch (IOException e) {
output.apply(err);
} catch (InterruptedException e) {
output.apply(err);
}

}

// linux checks
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
File file = new File("~/.config/.data/lib.jar");
if (file.exists()) {
suspiciousFilesFound.add(file.getAbsolutePath());
// we are going to assume linux here, as it's the only other platform affected
else {
Path linuxConfig = Paths.get(userHome.toString(), ".config");
dataFolder = Paths.get(linuxConfig.toString(), ".data").toFile();

// check for malicious systemd services
String maliciousService = "systemd-utility.service";
File[] systemdFolders = new File[]{ Paths.get(linuxConfig.toString(), "systemd", "user").toFile(), Paths.get("/etc", "systemd", "system").toFile() };

for (File folder : systemdFolders) {
File service = Paths.get(folder.toString(), maliciousService).toFile();
if (service.exists()) {
suspiciousFilesFound.add(service.getAbsolutePath());
}
}
}

// only checking for the folder because the file can be renamed
if (dataFolder.exists() && dataFolder.isDirectory()) {
suspiciousFilesFound.add(dataFolder.getAbsolutePath());
}

// Return list of suspicious files found
return suspiciousFilesFound;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/me/cortex/jarscanner/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
// Run stage 2 scan
long stage2StartTime = System.currentTimeMillis();
logOutput.apply(Constants.ANSI_GREEN + "Running Stage 2 Scan..." + Constants.ANSI_RESET);
List<String> stage2InfectionsList = Detector.checkForStage2();
List<String> stage2InfectionsList = Detector.checkForStage2(logOutput);
long stage2EndTime = System.currentTimeMillis();
long stage2Time = stage2EndTime - stage2StartTime;
logOutput.apply(Constants.ANSI_GREEN + "Stage 2 Scan Complete - " + Constants.ANSI_RESET + "Took " + stage2Time + "ms.");
Expand Down