package burp.zn.dirbuster; import burp.IBurpExtenderCallbacks; import burp.zn.gui.DirbusterPanel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.swing.*; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class DirbusterHandler { private static final String START = "Start"; private static final String STOP = "Stop"; private int counter; private DirbusterPanel panel; private JFileChooser fileChooser; private ThreadPoolExecutor executor; private IBurpExtenderCallbacks callbacks; private boolean isWorking = false; public DirbusterHandler(DirbusterPanel panel, IBurpExtenderCallbacks callbacks) { this.panel = panel; this.callbacks = callbacks; this.fileChooser = panel.getFileChooser(); /** * Set event handler for Dirbuster start button * Each gui handler must run in new thread */ panel.getBtnStart().addActionListener(e1 -> new Thread(() -> { if (isWorking) { DirbusterHandler.this.onCancelClick(); } else { DirbusterHandler.this.onStartClick(); } }).start()); /** * Browse button handler */ panel.getBtnBrowse().addActionListener(e -> new Thread(() -> { int returnVal = fileChooser.showOpenDialog(panel.getRootPanel()); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); panel.getTbxPathToFile().setText(file.getPath()); } }).start()); } /** * Start Button Handler */ private void onStartClick() { /** * Check dictionary file exist and change btn text */ File file = this.fileChooser.getSelectedFile() != null ? this.fileChooser.getSelectedFile() : new File(panel.getTbxPathToFile().getText()); if (!file.exists()) { /** * Any kinds of logging */ callbacks.issueAlert("DirBuster dictionary file is Null"); callbacks.printError("DirBuster dictionary file is Null"); callbacks.printOutput("DirBuster dictionary file is Null"); return; } panel.getBtnStart().setText(STOP); try { /** * Finally start buster */ this.runDirBuster(file.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } } /** * Dirbuster Executor * * @throws IOException */ public void runDirBuster(String filePath) throws IOException { /** * New thread pool with max count from panel */ this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Integer.valueOf(panel.getTbxMaxThreads().getText())); this.counter = 0; this.isWorking = true; /** * Using Lambdas and streams, is easier to make better performance in IO (because of parallel), * easy for use and more pretty code */ Files.lines(Paths.get(filePath)) .skip(13) .limit(3500) .parallel() .forEach(this::checkHost); this.onCancelClick(); } /** * Handle new line */ private void checkHost(String filePath) { Future<?> future = executor.submit(new DirbusterThread(getURL(filePath), callbacks, panel)); try { panel.getLblCount().setText("Count of bustered dirs: " + String.valueOf(counter++)); /** * New feature with thread timeout from the panel */ future.get(Integer.valueOf(panel.getTbxTimeout().getText()), TimeUnit.MILLISECONDS); } catch (Exception ex) { future.cancel(true); } } public URL getURL(String line) { String host = panel.getTbxHost().getText() + "/" + line + panel.getTbxFileExtention().getText(); try { return new URL(host); } catch (MalformedURLException e) { e.printStackTrace(); return null; } } /** * Stop Button Handler */ private void onCancelClick() { isWorking = false; panel.getBtnStart().setText(START); executor.shutdownNow(); } public boolean isWorking() { return isWorking; } }