diff --git a/src/main/java/me/cortex/jarscanner/Gui.java b/src/main/java/me/cortex/jarscanner/Gui.java index b119a07..342e28d 100644 --- a/src/main/java/me/cortex/jarscanner/Gui.java +++ b/src/main/java/me/cortex/jarscanner/Gui.java @@ -83,7 +83,7 @@ private static void createAndDisplayGui() { }; Results run = Main.run(4, searchDir, true, logOutput); - Main.outputRunResults(run, logOutput); + Main.outputRunResults(run, logOutput, null); textArea.append("Done scanning!"); } catch (Exception ex) { if (ex instanceof InterruptedException || ex instanceof RejectedExecutionException) { diff --git a/src/main/java/me/cortex/jarscanner/Main.java b/src/main/java/me/cortex/jarscanner/Main.java index 6381066..a5ceca8 100644 --- a/src/main/java/me/cortex/jarscanner/Main.java +++ b/src/main/java/me/cortex/jarscanner/Main.java @@ -33,7 +33,7 @@ public class Main { * Main method. Checks arguments and scans the specified directory for malicious code signatures. Outputs the * results of the scan to the console. * - * @param args the command line arguments (number of threads, directory to scan, and whether to emit walk errors) + * @param args the command line arguments (number of threads, directory to scan, whether to emit walk errors, and whether to output machine-readable CSV) */ public static void main(String[] args) { // Check arguments @@ -45,16 +45,32 @@ public static void main(String[] args) { int nThreads = Integer.parseInt(args[0]); Path dirToCheck = new File(args[1]).toPath(); boolean emitWalkErrors = false; + boolean machineReadableOutput = false; if (args.length > 2) { emitWalkErrors = Boolean.parseBoolean(args[2]); } + if (args.length > 3) { + machineReadableOutput = Boolean.parseBoolean(args[3]); + } + // Create log output function Function logOutput = outputString -> { System.out.println(outputString); return outputString; }; + // Create CSV logging function + Function logCSV = null; + + //make this not null if CSV output requested + if(machineReadableOutput) { + logCSV = outputString -> { + System.err.println(outputString); + return outputString; + }; + } + // Output scan start logOutput.apply("Starting scan..."); @@ -65,22 +81,26 @@ public static void main(String[] args) { } catch (IOException e) { logOutput.apply("An error occurred while scanning the directory: " + dirToCheck); e.printStackTrace(); + System.exit(1); //exit code for actual errors, distinct from detections } catch (InterruptedException e) { logOutput.apply("An error occurred while waiting for the scan to complete."); e.printStackTrace(); + System.exit(1); } // Output scan completion and results - outputRunResults(results, logOutput); + outputRunResults(results, logOutput, logCSV); } /** * Output the results of a scan to the specified log output function. * * @param results the resulting from {@link #run(int, Path, boolean, Function)}. - * @param logOutput the function to use for logging output + * @param logOutput the function to use for logging human-readable output + * @param logCSV the function to use for logging machine-readable CSV output, pass null for no CSV output + * */ - public static void outputRunResults(Results results, Function logOutput) { + public static void outputRunResults(Results results, Function logOutput, Function logCSV) { if (results == null) { logOutput.apply("Scan failed. Unable to display results."); } else { @@ -106,6 +126,18 @@ public static void outputRunResults(Results results, Function lo logOutput.apply(Constants.ANSI_RED + "[" + stage2InfectionNumber + "] " + Constants.ANSI_WHITE + stage2Infection + Constants.ANSI_RESET); } } + if(logCSV != null) //if CSV output isn't wanted, just pass in null + { + for (int i = 0; i < stage1Detections.size(); i++) { + String stage1Infection = stage1Detections.get(i); + logCSV.apply("1," + stage1Infection); + } + for (int i = 0; i < stage2Detections.size(); i++) { + String stage2Infection = stage2Detections.get(i); + logCSV.apply("2," + stage2Infection); + } + } + System.exit(2); //nonzero exit code to indicate infections found } } }