package com.it_jaros.jscanner; import java.util.BitSet; import java.util.List; import java.util.stream.Collectors; public class App { private static Thread shutdownHook; public static void main(String[] args) { try { run(args); } catch (Exception e) { System.out.printf("ERROR: %s", e.getMessage()); } } private static void run(String[] args) throws Exception { ScanOptions options = parseOptions(args); if (options == null) return; try (Scanner scanner = new Scanner(options)) { Scan scan = scanner.createScan(options); addShutdownHook(scan, scanner, options); scanner.runScan(scan); printScanResults(scan, options); } finally { removeShutdownHook(); } } private static ScanOptions parseOptions(String[] args) { CliParser cliParser = new CliParser(); try { return cliParser.parseArgs(args); } catch (IllegalArgumentException e) { System.out.printf("Error while parsing arguments: %s", e.getMessage()); System.out.println(); } cliParser.usageAndExit(1); return null; } /** * Allows us to handle signal int events * Prints intermediate result * * @param scan * @param scanner * @param scanOptions */ private static void addShutdownHook(Scan scan, Scanner scanner, ScanOptions scanOptions) { shutdownHook = new Thread(() -> { System.err.println("\nCtrl-C received."); scanner.cancel(); printScanResults(scan, scanOptions); }); Runtime.getRuntime().addShutdownHook(shutdownHook); } private static void removeShutdownHook() { if (shutdownHook == null) { return; } try { Runtime.getRuntime().removeShutdownHook(shutdownHook); } catch (IllegalStateException ignored) { // JVM is already shutting down } } public static void printScanResults(Scan scan, ScanOptions scanOptions) { printScanResults(scan.getResults(), scan.getPeakConcurrentConnects(), scanOptions); } private static void printScanResults(List result, int max, ScanOptions options) { printStats(max); result.forEach((ScanResult r) -> printPortsResults(r, options.showFilteredPorts())); } private static void printStats(int max) { System.out.println("--------------------"); System.out.println("Stats:"); System.out.println("Peak concurrent connects: " + max); System.out.println("--------------------"); } private static void printPortsResults(ScanResult result, boolean showFilteredPorts) { if (result.openPorts().isEmpty() && (!showFilteredPorts || result.filteredPorts().isEmpty())) { return; } System.out.println(result.host()); if (!result.openPorts().isEmpty()) { System.out.printf("\t (%d) open:\t%s%n", result.openPorts().cardinality(), map(result.openPorts(), result.bannerRecognition())); } if (showFilteredPorts && !result.filteredPorts().isEmpty()) { System.out.printf("\t (%d) filtered:\t%s%n", result.filteredPorts().cardinality(), map(result.filteredPorts())); } System.out.println(); } private static String map(BitSet ports) { return ports.stream().mapToObj(String::valueOf).collect(Collectors.joining(",")); } private static String map(BitSet ports, java.util.HashMap bannerRecognition) { return ports.stream().mapToObj(port -> { ServiceType serviceType = bannerRecognition.getOrDefault(port, ServiceType.UNKNOWN); if (serviceType == ServiceType.UNKNOWN) { return String.valueOf(port); } return port + "/" + serviceType.name().toLowerCase(); }).collect(Collectors.joining(",")); } }