Projects STRLCPY LoggerPlusPlus Commits 0b0da49c
🤬
  • ■ ■ ■ ■ ■ ■
    build.gradle
    1  -apply plugin: 'java'
     1 +plugins {
     2 + id 'java'
     3 + id "io.freefair.lombok" version "6.5.1"
     4 +}
     5 + 
     6 +sourceCompatibility = JavaVersion.VERSION_17
     7 +targetCompatibility = JavaVersion.VERSION_17
    2 8   
    3  -sourceCompatibility = 15
    4  -targetCompatibility = 15
    5 9   
    6 10  repositories {
    7 11   mavenCentral()
    skipped 3 lines
    11 15  }
    12 16   
    13 17  dependencies {
    14  - compileOnly 'net.portswigger.burp.extender:burp-extender-api:2.3'
    15  -// compileOnly 'net.portswigger.burp.extender:montoya-api:0.9.5'
    16  - compileOnly 'org.projectlombok:lombok:1.18.24'
    17  - annotationProcessor 'org.projectlombok:lombok:1.18.24'
     18 + implementation 'net.portswigger.burp.extensions:montoya-api:0.10.1'
     19 + implementation 'org.swinglabs:swingx:1.6.1'
     20 + implementation 'com.github.CoreyD97:BurpExtenderUtilities:896a540db7'
     21 + implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.15.2'
     22 + implementation 'org.apache.httpcomponents:httpclient:4.5.13'
     23 + implementation 'org.apache.commons:commons-text:1.10.0'
    18 24   
    19  - implementation 'org.swinglabs:swingx:1.6.1'
    20  - implementation 'com.github.CoreyD97:BurpExtenderUtilities:e800fd2d'
    21  - implementation 'com.google.code.gson:gson:2.8.2'
    22  - implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.5.2'
    23  - implementation 'org.apache.httpcomponents:httpclient:4.5.6'
    24  - implementation 'org.apache.commons:commons-text:1.7'
    25  - implementation 'org.apache.logging.log4j:log4j-core:2.17.1'
     25 + implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
     26 + testCompileOnly files("${System.properties['user.home']}/BurpSuitePro/burpsuite_pro.jar")
    26 27  }
    27 28   
    28 29  jar {
    skipped 16 lines
  • ■ ■ ■ ■
    gradle/wrapper/gradle-wrapper.properties
    1 1  distributionBase=GRADLE_USER_HOME
    2 2  distributionPath=wrapper/dists
    3  -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
     3 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
    4 4  zipStoreBase=GRADLE_USER_HOME
    5 5  zipStorePath=wrapper/dists
    6 6   
  • ■ ■ ■ ■ ■ ■
    src/main/java/burp/BurpExtender.java
    1  -//
    2  -// Burp Suite Logger++
    3  -//
    4  -// Released as open source by NCC Group Plc - https://www.nccgroup.trust/
    5  -//
    6  -// Developed by Soroush Dalili (@irsdl)
    7  -//
    8  -// Project link: http://www.github.com/nccgroup/BurpSuiteLoggerPlusPlus
    9  -//
    10  -// Released under AGPL see LICENSE for more information
    11  -//
    12  - 
    13  -package burp;
    14  - 
    15  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    16  - 
    17  - 
    18  -public class BurpExtender extends LoggerPlusPlus
    19  -{
    20  - public static void main(String [] args){
    21  - System.out.println("You have built the Logger++. You shall play with the jar file now!");
    22  - }
    23  -}
    24  - 
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/LoggerContextMenuFactory.java
    1 1  package com.nccgroup.loggerplusplus;
    2 2   
    3  -import burp.IContextMenuFactory;
    4  -import burp.IContextMenuInvocation;
     3 +import burp.api.montoya.core.Range;
     4 +import burp.api.montoya.http.message.HttpMessage;
     5 +import burp.api.montoya.ui.contextmenu.ContextMenuEvent;
     6 +import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
     7 +import burp.api.montoya.ui.contextmenu.MessageEditorHttpRequestResponse;
    5 8  import com.nccgroup.loggerplusplus.filter.colorfilter.ColorFilter;
    6 9  import com.nccgroup.loggerplusplus.filter.logfilter.LogFilter;
    7 10  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    skipped 11 lines
    19 22   
    20 23  import static com.nccgroup.loggerplusplus.util.Globals.PREF_COLOR_FILTERS;
    21 24   
    22  -public class LoggerContextMenuFactory implements IContextMenuFactory {
    23  - 
    24  - private final LoggerPlusPlus loggerPlusPlus;
     25 +public class LoggerContextMenuFactory implements ContextMenuItemsProvider {
    25 26  
    26  - public LoggerContextMenuFactory(LoggerPlusPlus loggerPlusPlus){
    27  - this.loggerPlusPlus = loggerPlusPlus;
     27 + public LoggerContextMenuFactory(){
    28 28   }
    29 29   
    30 30   @Override
    31  - public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
    32  - if(invocation == null) return null;
     31 + public List<JMenuItem> provideMenuItems(ContextMenuEvent event) {
    33 32   JMenuItem filterMenu = new JMenu("Logger++");
    34 33   
    35  - if (invocation.getSelectedMessages().length == 0 ||
    36  - invocation.getSelectionBounds()[0] == invocation.getSelectionBounds()[1]) {
    37  - return null;
    38  - }
     34 + //We're handling a message editor context menu
     35 + //And we have a selection
     36 + MessageEditorHttpRequestResponse requestResponse = event.messageEditorRequestResponse().orElseThrow();
     37 + Range selectedRange = requestResponse.selectionOffsets().orElseThrow();
     38 + HttpMessage target;
    39 39   
    40 40   final LogEntryField context;
    41 41   final byte[] selectedBytes;
    42  - switch (invocation.getInvocationContext()){
    43  - case IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST:
    44  - case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST: {
     42 + switch (event.invocationType()){
     43 + case MESSAGE_EDITOR_REQUEST:
     44 + case MESSAGE_VIEWER_REQUEST: {
     45 + target = requestResponse.getRequestResponse().httpRequest();
    45 46   try {
    46  - byte[] msg = invocation.getSelectedMessages()[0].getRequest();
    47  - if (LoggerPlusPlus.callbacks.getHelpers().analyzeRequest(msg).getBodyOffset() > invocation.getSelectionBounds()[0]) {
     47 + if (selectedRange.startIndexInclusive() <= target.bodyOffset()) {
    48 48   context = LogEntryField.REQUEST_HEADERS;
    49 49   } else {
    50 50   context = LogEntryField.REQUEST_BODY;
    51 51   }
    52  - selectedBytes = Arrays.copyOfRange(invocation.getSelectedMessages()[0].getRequest(),
    53  - invocation.getSelectionBounds()[0],invocation.getSelectionBounds()[1]);
     52 + selectedBytes = Arrays.copyOfRange(target.asBytes().getBytes(), selectedRange.startIndexInclusive(),
     53 + selectedRange.endIndexExclusive());
    54 54   }catch (NullPointerException nPException){ return null; }
    55 55   break;
    56 56   }
    57 57   
    58  - case IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_RESPONSE:
    59  - case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE: {
     58 + case MESSAGE_EDITOR_RESPONSE:
     59 + case MESSAGE_VIEWER_RESPONSE: {
     60 + target = requestResponse.getRequestResponse().httpResponse();
    60 61   try {
    61  - byte[] msg = invocation.getSelectedMessages()[0].getResponse();
    62  - if (LoggerPlusPlus.callbacks.getHelpers().analyzeRequest(msg).getBodyOffset() > invocation.getSelectionBounds()[0]) {
     62 + if (selectedRange.startIndexInclusive() <= target.bodyOffset()) {
    63 63   context = LogEntryField.RESPONSE_HEADERS;
    64 64   } else {
    65 65   context = LogEntryField.RESPONSE_BODY;
    66 66   }
    67  - selectedBytes = Arrays.copyOfRange(invocation.getSelectedMessages()[0].getResponse(),
    68  - invocation.getSelectionBounds()[0], invocation.getSelectionBounds()[1]);
     67 + selectedBytes = Arrays.copyOfRange(target.asBytes().getBytes(), selectedRange.startIndexInclusive(),
     68 + selectedRange.endIndexExclusive());
    69 69   } catch (NullPointerException nPException) {
    70 70   return null;
    71 71   }
    skipped 3 lines
    75 75   return null;
    76 76   }
    77 77   
    78  - if (selectedBytes != null) System.out.println(new String(selectedBytes));
    79  - 
    80  - final LogTable logTable = loggerPlusPlus.getLogViewController().getLogTableController().getLogTable();
     78 + final LogTable logTable = LoggerPlusPlus.instance.getLogViewController().getLogTableController().getLogTable();
    81 79   String selectedText = StringEscapeUtils.escapeJava(new String(selectedBytes));
    82 80   
    83 81   JMenuItem useAsFilter = new JMenuItem(new AbstractAction("Use Selection As LogFilter") {
    84 82   @Override
    85 83   public void actionPerformed(ActionEvent actionEvent) {
    86  - loggerPlusPlus.getLogViewController().getLogFilterController().setFilter(context.getFullLabel() +
     84 + LoggerPlusPlus.instance.getLogViewController().getLogFilterController().setFilter(context.getFullLabel() +
    87 85   " CONTAINS \"" + selectedText + "\"");
    88 86   }
    89 87   });
    skipped 5 lines
    95 93   JMenuItem andFilter = new JMenuItem(new AbstractAction("AND") {
    96 94   @Override
    97 95   public void actionPerformed(ActionEvent actionEvent) {
    98  - loggerPlusPlus.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " && "
     96 + LoggerPlusPlus.instance.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " && "
    99 97   + "" + context.getFullLabel() + " CONTAINS \"" + selectedText + "\"");
    100 98   }
    101 99   });
    skipped 1 lines
    103 101   JMenuItem andNotFilter = new JMenuItem(new AbstractAction("AND NOT") {
    104 102   @Override
    105 103   public void actionPerformed(ActionEvent actionEvent) {
    106  - loggerPlusPlus.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " && !("
     104 + LoggerPlusPlus.instance.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " && !("
    107 105   + "" + context.getFullLabel() + " CONTAINS \"" + selectedText + "\")");
    108 106   }
    109 107   });
    skipped 1 lines
    111 109   JMenuItem orFilter = new JMenuItem(new AbstractAction("OR") {
    112 110   @Override
    113 111   public void actionPerformed(ActionEvent actionEvent) {
    114  - loggerPlusPlus.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " || "
     112 + LoggerPlusPlus.instance.getLogViewController().getLogFilterController().setFilter(logTable.getCurrentFilter().toString() + " || "
    115 113   + context.getFullLabel() + " CONTAINS \"" + selectedText + "\"");
    116 114   }
    117 115   });
    skipped 8 lines
    126 124   public void actionPerformed(ActionEvent actionEvent) {
    127 125   try {
    128 126   ColorFilter colorFilter = new ColorFilter();
    129  - colorFilter.setFilter(new LogFilter(loggerPlusPlus.getLibraryController(),
     127 + colorFilter.setFilter(new LogFilter(LoggerPlusPlus.instance.getLibraryController(),
    130 128   context.getFullLabel() + " CONTAINS \"" + selectedText + "\""));
    131  - HashMap<UUID,ColorFilter> colorFilters = loggerPlusPlus.getPreferencesController().getPreferences().getSetting(PREF_COLOR_FILTERS);
     129 + HashMap<UUID,ColorFilter> colorFilters = LoggerPlusPlus.instance.getPreferencesController().getPreferences().getSetting(PREF_COLOR_FILTERS);
    132 130   colorFilters.put(colorFilter.getUUID(), colorFilter);
    133  - new ColorFilterDialog(loggerPlusPlus.getLibraryController()).setVisible(true);
     131 + new ColorFilterDialog(LoggerPlusPlus.instance.getLibraryController()).setVisible(true);
    134 132   } catch (ParseException e) {
    135 133   return;
    136 134   }
    skipped 7 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/LoggerPlusPlus.java
    1 1  package com.nccgroup.loggerplusplus;
    2 2   
    3  -import burp.IBurpExtender;
    4  -import burp.IBurpExtenderCallbacks;
    5  -import burp.IExtensionStateListener;
     3 +import burp.api.montoya.BurpExtension;
     4 +import burp.api.montoya.MontoyaApi;
    6 5  import com.coreyd97.BurpExtenderUtilities.DefaultGsonProvider;
    7 6  import com.coreyd97.BurpExtenderUtilities.IGsonProvider;
    8 7  import com.nccgroup.loggerplusplus.exports.ExportController;
    skipped 7 lines
    16 15  import com.nccgroup.loggerplusplus.reflection.ReflectionController;
    17 16  import com.nccgroup.loggerplusplus.util.Globals;
    18 17  import com.nccgroup.loggerplusplus.util.userinterface.LoggerMenu;
     18 +import lombok.Getter;
     19 +import lombok.extern.log4j.Log4j2;
    19 20  import org.apache.logging.log4j.Level;
    20 21   
    21 22  import javax.swing.*;
    22 23  import java.awt.*;
    23  -import java.net.URL;
    24 24  import java.util.Arrays;
    25 25  import java.util.List;
    26 26   
    skipped 2 lines
    29 29  /**
    30 30   * Created by corey on 07/09/17.
    31 31   */
    32  -public class LoggerPlusPlus implements IBurpExtender, IExtensionStateListener {
     32 +@Log4j2
     33 +@Getter
     34 +public class LoggerPlusPlus implements BurpExtension {
     35 + 
     36 + private static String NAME = "Logger++";
     37 + 
     38 + public static LoggingController loggingController;
    33 39   public static LoggerPlusPlus instance;
    34  - public static IBurpExtenderCallbacks callbacks;
     40 + public static MontoyaApi montoya;
     41 + public static IGsonProvider gsonProvider = new DefaultGsonProvider();
    35 42   
    36  - private final IGsonProvider gsonProvider;
    37  - private LoggingController loggingController;
    38 43   private LogProcessor logProcessor;
    39 44   private ExportController exportController;
    40 45   private PreferencesController preferencesController;
    skipped 7 lines
    48 53   //UX
    49 54   private LoggerMenu loggerMenu;
    50 55   
    51  - 
    52  - public LoggerPlusPlus(){
    53  - this.gsonProvider = new DefaultGsonProvider();
     56 + public LoggerPlusPlus() {
     57 + LoggerPlusPlus.instance = this;
    54 58   }
    55 59   
    56 60   @Override
    57  - public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
    58  - {
     61 + public void initialize(MontoyaApi montoya) {
     62 + //Woohoo! Montoya!
     63 + LoggerPlusPlus.montoya = montoya;
     64 + montoya.extension().setName(NAME);
     65 + montoya.extension().registerUnloadingHandler(this::unloadExtension);
    59 66   
    60  - //Fix Darcula's issue with JSpinner UI.
    61  - try {
    62  - Class spinnerUI = Class.forName("com.bulenkov.darcula.ui.DarculaSpinnerUI");
    63  - UIManager.put("com.bulenkov.darcula.ui.DarculaSpinnerUI", spinnerUI);
    64  - Class sliderUI = Class.forName("com.bulenkov.darcula.ui.DarculaSliderUI");
    65  - UIManager.put("com.bulenkov.darcula.ui.DarculaSliderUI", sliderUI);
    66  - } catch (ClassNotFoundException e) {
    67  - //Darcula is not installed.
    68  - }
     67 + //TODO Set Logging Level from prefs
     68 + loggingController = new LoggingController(gsonProvider, montoya);
     69 + log.info("Logging configured");
    69 70   
    70  - //Burp Specific
    71  - LoggerPlusPlus.instance = this;
    72  - LoggerPlusPlus.callbacks = callbacks;
    73  - callbacks.setExtensionName("Logger++");
    74  - LoggerPlusPlus.callbacks.registerExtensionStateListener(LoggerPlusPlus.this);
    75  - 
    76  - loggingController = new LoggingController(gsonProvider);
    77  - preferencesController = new PreferencesController(this);
     71 + preferencesController = new PreferencesController(montoya);
    78 72   preferencesController.getPreferences().addSettingListener((source, settingName, newValue) -> {
    79 73   if (settingName.equals(Globals.PREF_LOG_LEVEL)) {
    80 74   loggingController.setLogLevel((Level) newValue);
    81 75   }
    82 76   });
    83 77   reflectionController = new ReflectionController(preferencesController.getPreferences());
    84  - exportController = new ExportController(this, preferencesController.getPreferences());
    85  - libraryController = new FilterLibraryController(this, preferencesController);
    86  - logViewController = new LogViewController(this, libraryController);
    87  - logProcessor = new LogProcessor(this, logViewController.getLogTableController(), exportController);
    88  - grepperController = new GrepperController(this, logViewController.getLogTableController(), preferencesController);
    89  - contextMenuFactory = new LoggerContextMenuFactory(this);
     78 + exportController = new ExportController(preferencesController.getPreferences());
     79 + libraryController = new FilterLibraryController(preferencesController);
     80 + logViewController = new LogViewController(libraryController);
     81 + logProcessor = new LogProcessor(logViewController.getLogTableController(), exportController);
     82 + grepperController = new GrepperController(logViewController.getLogTableController(), preferencesController);
     83 + contextMenuFactory = new LoggerContextMenuFactory();
     84 + mainViewController = new MainViewController();
    90 85   
    91  - mainViewController = new MainViewController(this);
    92 86   
    93  - LoggerPlusPlus.callbacks.registerContextMenuFactory(contextMenuFactory);
     87 + montoya.userInterface().registerContextMenuItemsProvider(contextMenuFactory);
     88 + montoya.userInterface().registerSuiteTab(NAME, mainViewController.getUiComponent());
    94 89   
     90 + montoya.http().registerHttpHandler(logProcessor.getHttpHandler());
     91 + montoya.proxy().registerResponseHandler(logProcessor.getProxyHttpResponseHandler());
    95 92   
    96  - SwingUtilities.invokeLater(() -> {
    97  - 
    98  - LoggerPlusPlus.callbacks.addSuiteTab(mainViewController);
    99  - 
    100  - //Add menu item to Burp's frame menu.
    101  - JFrame rootFrame = (JFrame) SwingUtilities.getWindowAncestor(mainViewController.getUiComponent());
    102  - try{
    103  - JMenuBar menuBar = rootFrame.getJMenuBar();
    104  - loggerMenu = new LoggerMenu(LoggerPlusPlus.this);
    105  - menuBar.add(loggerMenu, menuBar.getMenuCount() - 1);
    106  - }catch (NullPointerException nPException){
    107  - loggerMenu = null;
    108  - }
    109  - });
     93 + //Add menu item to Burp's frame menu.
     94 + JFrame rootFrame = (JFrame) SwingUtilities.getWindowAncestor(mainViewController.getUiComponent());
     95 + try{
     96 + JMenuBar menuBar = rootFrame.getJMenuBar();
     97 + loggerMenu = new LoggerMenu(LoggerPlusPlus.this);
     98 + menuBar.add(loggerMenu, menuBar.getMenuCount() - 1);
     99 + }catch (NullPointerException nPException){
     100 + loggerMenu = null;
     101 + }
    110 102   
    111 103   }
    112 104   
    113  - @Override
    114  - public void extensionUnloaded() {
     105 + public void unloadExtension() {
    115 106   if(loggerMenu != null && loggerMenu.getParent() != null){
    116 107   loggerMenu.getParent().remove(loggerMenu);
    117 108   }
    skipped 9 lines
    127 118   
    128 119   //Null out static variables so not leftover.
    129 120   LoggerPlusPlus.instance = null;
    130  - LoggerPlusPlus.callbacks = null;
    131 121   }
    132 122   
    133  - public static boolean isUrlInScope(URL url){
     123 + public static boolean isUrlInScope(String url){
    134 124   return (!(Boolean) instance.getPreferencesController().getPreferences().getSetting(PREF_RESTRICT_TO_SCOPE)
    135  - || callbacks.isInScope(url));
    136  - }
    137  - 
    138  - 
    139  - public LogViewController getLogViewController() {
    140  - return logViewController;
    141  - }
    142  - 
    143  - public IGsonProvider getGsonProvider() {
    144  - return gsonProvider;
    145  - }
    146  - 
    147  - public GrepperController getGrepperController() {
    148  - return grepperController;
    149  - }
    150  - 
    151  - public MainViewController getMainViewController() {
    152  - return mainViewController;
    153  - }
    154  - 
    155  - public FilterLibraryController getLibraryController() {
    156  - return libraryController;
    157  - }
    158  - 
    159  - public LoggingController getLoggingController() {
    160  - return loggingController;
    161  - }
    162  - 
    163  - public PreferencesController getPreferencesController() {
    164  - return preferencesController;
    165  - }
    166  - 
    167  - public LogProcessor getLogProcessor() {
    168  - return logProcessor;
    169  - }
    170  - 
    171  - public ReflectionController getReflectionController() {
    172  - return reflectionController;
    173  - }
    174  - 
    175  - public LoggerMenu getLoggerMenu() {
    176  - return loggerMenu;
     125 + || montoya.scope().isInScope(url));
    177 126   }
    178 127   
    179 128   public List<LogEntry> getLogEntries(){
    180 129   return logViewController.getLogTableController().getLogTableModel().getData();
    181  - }
    182  - 
    183  - public ExportController getExportController() {
    184  - return exportController;
    185 130   }
    186 131   
    187 132   public Frame getLoggerFrame() {
    skipped 9 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/MainViewController.java
    1 1  package com.nccgroup.loggerplusplus;
    2 2   
    3  -import burp.ITab;
    4 3  import com.coreyd97.BurpExtenderUtilities.PopOutPanel;
    5 4  import com.nccgroup.loggerplusplus.about.AboutPanel;
    6 5  import com.nccgroup.loggerplusplus.help.HelpPanel;
    skipped 2 lines
    9 8  import javax.swing.*;
    10 9  import java.awt.*;
    11 10   
    12  -public class MainViewController implements ITab {
     11 +public class MainViewController {
    13 12  
    14  - private final LoggerPlusPlus loggerPlusPlus;
    15 13   private final JTabbedPane tabbedPane;
    16 14   private final PopOutPanel popOutWrapper;
    17 15   
    18  - public MainViewController(LoggerPlusPlus loggerPlusPlus) {
    19  - this.loggerPlusPlus = loggerPlusPlus;
     16 + public MainViewController() {
    20 17   this.tabbedPane = new JTabbedPane();
     18 + LoggerPlusPlus loggerPlusPlus = LoggerPlusPlus.instance;
    21 19   tabbedPane.addTab("View Logs", null, loggerPlusPlus.getLogViewController().getLogViewPanel(), null);
    22 20   tabbedPane.addTab("Filter Library", null, loggerPlusPlus.getLibraryController().getFilterLibraryPanel(), null);
    23 21   tabbedPane.addTab("Grep Values", null, loggerPlusPlus.getGrepperController().getGrepperPanel(), null);
    skipped 3 lines
    27 25   this.popOutWrapper = new PopOutPanel(tabbedPane, Globals.APP_NAME);
    28 26   }
    29 27   
    30  - @Override
    31  - public String getTabCaption() {
    32  - return Globals.APP_NAME;
    33  - }
    34  - 
    35  - @Override
    36 28   public Component getUiComponent() {
    37 29   return popOutWrapper;
    38 30   }
    skipped 10 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/AutomaticLogExporter.java
    skipped 2 lines
    3 3  import com.coreyd97.BurpExtenderUtilities.Preferences;
    4 4  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    5 5   
    6  -import javax.swing.*;
    7  - 
    8 6  public abstract class AutomaticLogExporter extends LogExporter {
    9 7   
    10 8   protected AutomaticLogExporter(ExportController exportController, Preferences preferences){
    skipped 29 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/Base64Exporter.java
    skipped 38 lines
    39 39   protected Void doInBackground() throws Exception {
    40 40   super.doInBackground();
    41 41   try (FileWriter fileWriter = new FileWriter(file, false)) {
    42  - Gson gson = exportController.getLoggerPlusPlus().getGsonProvider().getGson();
     42 + Gson gson = LoggerPlusPlus.gsonProvider.getGson();
    43 43   ArrayList<JsonObject> jsonEntries = new ArrayList<>();
    44 44   Base64.Encoder encoder = Base64.getEncoder();
    45 45   for (LogEntry entry : entries) {
    46 46   JsonObject jsonEntry = new JsonObject();
    47 47   if (includeRequest) {
    48 48   jsonEntry.addProperty("request",
    49  - encoder.encodeToString(entry.getRequest()));
     49 + encoder.encodeToString(entry.getRequestBytes()));
    50 50   }
    51 51   
    52 52   if (includeResponse) {
    53 53   jsonEntry.addProperty("response",
    54  - encoder.encodeToString(entry.getResponse()));
     54 + encoder.encodeToString(entry.getResponseBytes()));
    55 55   }
    56 56   jsonEntries.add(jsonEntry);
    57 57   }
    skipped 57 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/CSVExporterControlPanel.java
    skipped 1 lines
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Alignment;
    4 4  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
     5 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 6  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 7   
    7 8  import javax.swing.*;
    skipped 11 lines
    19 20   
    20 21   JButton manualSaveButton = new JButton("Export as CSV");
    21 22   manualSaveButton.addActionListener(actionEvent -> {
    22  - final List<LogEntry> entries = csvExporter.getExportController().getLoggerPlusPlus().getLogEntries();
     23 + final List<LogEntry> entries = LoggerPlusPlus.instance.getLogEntries();
    23 24   csvExporter.exportEntries(entries);
    24 25   });
    25 26   
    skipped 41 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/ElasticExporter.java
    skipped 7 lines
    8 8  import com.nccgroup.loggerplusplus.logentry.LogEntryField;
    9 9  import com.nccgroup.loggerplusplus.logentry.Status;
    10 10  import com.nccgroup.loggerplusplus.util.Globals;
     11 +import lombok.extern.log4j.Log4j2;
    11 12  import org.apache.commons.lang3.StringUtils;
    12 13  import org.apache.http.Header;
    13 14  import org.apache.http.HttpHost;
    skipped 26 lines
    40 41   
    41 42  import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
    42 43   
     44 +@Log4j2
    43 45  public class ElasticExporter extends AutomaticLogExporter implements ExportPanelProvider, ContextMenuExportProvider {
    44 46   
    45 47   RestHighLevelClient httpClient;
    skipped 49 lines
    95 97   
    96 98   if (!StringUtils.isBlank(filterString)) {
    97 99   try {
    98  - logFilter = new LogFilter(exportController.getLoggerPlusPlus().getLibraryController(), filterString);
     100 + logFilter = new LogFilter(LoggerPlusPlus.instance.getLibraryController(), filterString);
    99 101   } catch (ParseException ex) {
    100 102   logger.error("The log filter configured for the Elastic exporter is invalid!", ex);
    101 103   }
    skipped 95 lines
    197 199   builder.field(field.getFullLabel(), value);
    198 200   }
    199 201   }catch (Exception e){
    200  - LoggerPlusPlus.callbacks.printError("ElasticExporter: " + value);
    201  - LoggerPlusPlus.callbacks.printError("ElasticExporter: " + e.getMessage());
     202 + log.error("ElasticExporter: " + value);
     203 + log.error("ElasticExporter: " + e.getMessage());
    202 204   throw e;
    203 205   }
    204 206   }
    skipped 19 lines
    224 226   IndexRequest request = buildIndexRequest(logEntry);
    225 227   httpBulkBuilder.add(request);
    226 228   } catch (Exception e) {
    227  - LoggerPlusPlus.callbacks.printError("Could not build elastic export request for entry: " + e.getMessage());
     229 + log.error("Could not build elastic export request for entry: " + e.getMessage());
    228 230   //Could not build index request. Ignore it?
    229 231   }
    230 232   }
    skipped 2 lines
    233 235   BulkResponse bulkResponse = httpClient.bulk(httpBulkBuilder, RequestOptions.DEFAULT);
    234 236   if (bulkResponse.hasFailures()) {
    235 237   for (BulkItemResponse bulkItemResponse : bulkResponse.getItems()) {
    236  - LoggerPlusPlus.callbacks.printError(bulkItemResponse.getFailureMessage());
     238 + log.error(bulkItemResponse.getFailureMessage());
    237 239   }
    238 240   }
    239 241   connectFailedCounter = 0;
    skipped 35 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/ElasticExporterConfigDialog.java
    skipped 220 lines
    221 221   String logFilter = preferences.getSetting(PREF_ELASTIC_FILTER);
    222 222   
    223 223   if (!StringUtils.isBlank(logFilter)) {
    224  - FilterLibraryController libraryController = elasticExporter.getExportController()
    225  - .getLoggerPlusPlus().getLibraryController();
     224 + FilterLibraryController libraryController = LoggerPlusPlus.instance.getLibraryController();
    226 225   try {
    227 226   new LogFilter(libraryController, logFilter);
    228 227   } catch (ParseException ex) {
    skipped 13 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/ExportController.java
    1 1  package com.nccgroup.loggerplusplus.exports;
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Preferences;
    4  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 4  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 5   
    7 6  import java.util.ArrayList;
    skipped 2 lines
    10 9  import java.util.List;
    11 10   
    12 11  public class ExportController {
    13  - 
    14  - private final LoggerPlusPlus loggerPlusPlus;
    15 12   private final Preferences preferences;
    16 13   private final HashMap<Class<? extends LogExporter>, LogExporter> exporters;
    17 14   private final List<AutomaticLogExporter> enabledExporters;
    18 15   
    19  - public ExportController(LoggerPlusPlus loggerPlusPlus, Preferences preferences) {
    20  - this.loggerPlusPlus = loggerPlusPlus;
     16 + public ExportController(Preferences preferences) {
    21 17   this.preferences = preferences;
    22 18   
    23 19   this.exporters = new HashMap<>();
    skipped 38 lines
    62 58   for (AutomaticLogExporter exporter : this.enabledExporters) {
    63 59   exporter.exportUpdatedEntry(logEntry);
    64 60   }
    65  - }
    66  - 
    67  - public LoggerPlusPlus getLoggerPlusPlus() {
    68  - return loggerPlusPlus;
    69 61   }
    70 62  }
    71 63   
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/HARExporterControlPanel.java
    skipped 1 lines
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Alignment;
    4 4  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
     5 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 6  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 7   
    7 8  import javax.swing.*;
    skipped 6 lines
    14 15   
    15 16   JButton manualSaveButton = new JButton("Export as HAR");
    16 17   manualSaveButton.addActionListener(actionEvent -> {
    17  - final List<LogEntry> entries = harExporter.getExportController().getLoggerPlusPlus().getLogEntries();
     18 + final List<LogEntry> entries = LoggerPlusPlus.instance.getLogEntries();
    18 19   harExporter.exportEntries(entries);
    19 20   });
    20 21   
    skipped 6 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/HarSerializer.java
    1 1  package com.nccgroup.loggerplusplus.exports;
    2 2   
    3  -import burp.ICookie;
    4  -import burp.IParameter;
    5  -import burp.IRequestInfo;
    6  -import burp.IResponseInfo;
     3 +import burp.api.montoya.http.message.cookies.Cookie;
     4 +import burp.api.montoya.http.message.headers.HttpHeader;
     5 +import burp.api.montoya.http.message.params.HttpParameter;
     6 +import burp.api.montoya.http.message.params.HttpParameterType;
     7 +import burp.api.montoya.http.message.requests.HttpRequest;
    7 8  import com.google.gson.TypeAdapter;
    8 9  import com.google.gson.stream.JsonReader;
    9 10  import com.google.gson.stream.JsonWriter;
    10  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    11 11  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    12 12  import com.nccgroup.loggerplusplus.logentry.LogEntryField;
    13 13   
    skipped 46 lines
    60 60   writer.name("time").value(time);
    61 61   writer.name("request").beginObject();
    62 62   writer.name("method").value(logEntry.getMethod());
    63  - writer.name("url").value(logEntry.getUrl().toString());
     63 + writer.name("url").value(logEntry.getUrlString().toString());
    64 64   writer.name("httpVersion").value(logEntry.getRequestHttpVersion());
    65 65   writer.name("origin").value(logEntry.getOrigin());
    66 66   
    67 67   writer.name("cookies").beginArray();
    68 68   if (logEntry.isHasCookieParam()) {
    69  - List<IParameter> cookies = getRequestParametersByType(logEntry.getRequest(),
    70  - IParameter.PARAM_COOKIE);
    71  - for (IParameter cookie : cookies) {
     69 + List<HttpParameter> cookies = getRequestParametersByType(logEntry.getRequest(), HttpParameterType.COOKIE);
     70 + for (HttpParameter cookie : cookies) {
    72 71   writer.beginObject();
    73  - writer.name("name").value(cookie.getName());
    74  - writer.name("value").value(cookie.getValue());
     72 + writer.name("name").value(cookie.name());
     73 + writer.name("value").value(cookie.value());
    75 74   writer.endObject();
    76 75   }
    77 76   }
    78 77   writer.endArray(); // end request cookies array
    79 78   
    80 79   writer.name("headers").beginArray();
    81  - for (String headerString : logEntry.getRequestHeaders()) {
    82  - if (headerString.contains(":")) {
    83  - writer.beginObject();
    84  - String headerArray[] = headerString.split(":", 2);
    85  - writer.name("name").value(headerArray[0]);
    86  - writer.name("value").value(headerArray[1].trim());
    87  - writer.endObject();
    88  - }
     80 + for (HttpHeader header : logEntry.getRequestHeaders()) {
     81 + writer.beginObject();
     82 + writer.name("name").value(header.name());
     83 + writer.name("value").value(header.value());
     84 + writer.endObject();
    89 85   }
    90 86   writer.endArray(); // end request headers array
    91 87   
    92 88   writer.name("queryString").beginArray();
    93 89   if (logEntry.getUrl().getQuery() != null) {
    94  - List<IParameter> queryParams = getRequestParametersByType(logEntry.getRequest(),
    95  - IParameter.PARAM_URL);
    96  - for (IParameter queryParam : queryParams) {
     90 + for (HttpParameter queryParam : getRequestParametersByType(logEntry.getRequest(), HttpParameterType.URL)) {
    97 91   writer.beginObject();
    98  - writer.name("name").value(queryParam.getName());
    99  - writer.name("value").value(queryParam.getValue());
     92 + writer.name("name").value(queryParam.name());
     93 + writer.name("value").value(queryParam.value());
    100 94   writer.endObject();
    101 95   }
    102 96   }
    skipped 2 lines
    105 99   if (logEntry.isHasBodyParam()) {
    106 100   writer.name("postData").beginObject();
    107 101   writer.name("mimeType").value(logEntry.getRequestContentType());
    108  - List<IParameter> bodyParams = getRequestBodyParameters(logEntry.getRequest());
    109 102   writer.name("params").beginArray();
    110  - for (IParameter bodyParam : bodyParams) {
     103 + for (HttpParameter bodyParam : getRequestParametersByType(logEntry.getRequest(), HttpParameterType.BODY)) {
    111 104   writer.beginObject();
    112  - writer.name("name").value(bodyParam.getName());
    113  - writer.name("value").value(bodyParam.getValue());
     105 + writer.name("name").value(bodyParam.name());
     106 + writer.name("value").value(bodyParam.value());
    114 107   writer.endObject();
    115 108   }
    116 109   writer.endArray(); // end params array
    skipped 1 lines
    118 111   writer.endObject(); // end postData object
    119 112   }
    120 113   
    121  - writer.name("headersSize").value(logEntry.getRequest().length - logEntry.getRequestBodyLength());
     114 + writer.name("headersSize").value(logEntry.getRequestBytes().length - logEntry.getRequestBodyLength());
    122 115   writer.name("bodySize").value(logEntry.getRequestBodyLength());
    123 116   
    124 117   writer.endObject(); // end request object
    skipped 5 lines
    130 123   
    131 124   writer.name("cookies").beginArray();
    132 125   if (logEntry.isHasSetCookies()) {
    133  - List<ICookie> cookies = getResponseCookies(logEntry.getResponse());
     126 + List<Cookie> cookies = logEntry.getResponse().cookies();
    134 127   
    135  - for (ICookie cookie : cookies) {
     128 + for (Cookie cookie : cookies) {
    136 129   writer.beginObject();
    137  - writer.name("name").value(cookie.getName());
    138  - writer.name("value").value(cookie.getValue());
    139  - writer.name("path").value(cookie.getPath());
    140  - writer.name("domain").value(cookie.getDomain());
     130 + writer.name("name").value(cookie.name());
     131 + writer.name("value").value(cookie.value());
     132 + writer.name("path").value(cookie.path());
     133 + writer.name("domain").value(cookie.domain());
    141 134   writer.endObject();
    142 135   }
    143 136   }
    skipped 1 lines
    145 138   
    146 139   writer.name("headers").beginArray();
    147 140   if (logEntry.getResponseHeaders() != null) {
    148  - for (String headerString : logEntry.getResponseHeaders()) {
    149  - if (headerString.contains(":")) {
    150  - writer.beginObject();
    151  - String headerArray[] = headerString.split(":", 2);
    152  - writer.name("name").value(headerArray[0]);
    153  - writer.name("value").value(headerArray[1].trim());
    154  - writer.endObject();
    155  - }
     141 + for (HttpHeader header : logEntry.getResponseHeaders()) {
     142 + writer.beginObject();
     143 + writer.name("name").value(header.name());
     144 + writer.name("value").value(header.value());
     145 + writer.endObject();
    156 146   }
    157 147   }
    158 148   writer.endArray(); // end response headers array
    159 149   
    160 150   writer.name("redirectURL").value(String.valueOf(logEntry.getValueByKey(LogEntryField.REDIRECT_URL)));
    161  - if (logEntry.getResponse() != null) {
    162  - writer.name("headersSize").value(logEntry.getResponse().length - logEntry.getResponseBodyLength());
     151 + if (logEntry.getResponseBytes() != null) {
     152 + writer.name("headersSize").value(logEntry.getResponseBytes().length - logEntry.getResponseBodyLength());
    163 153   writer.name("bodySize").value(logEntry.getResponseBodyLength());
    164 154   } else {
    165 155   writer.name("headersSize").value(0);
    skipped 3 lines
    169 159   
    170 160   writer.name("content").beginObject(); // start content object
    171 161   writer.name("size").value(logEntry.getResponseBodyLength());
    172  - writer.name("mimeType").value(logEntry.getResponseMimeType());
     162 + writer.name("mimeType").value(logEntry.getResponseContentType());
    173 163   writer.name("text").value(String.valueOf(logEntry.getValueByKey(LogEntryField.RESPONSE_BODY)));
    174 164   writer.endObject(); //end content object
    175 165   
    skipped 19 lines
    195 185   
    196 186   }
    197 187   
    198  - private List<IParameter> getRequestParametersByType(byte[] request, byte paramType) {
    199  - IRequestInfo tempAnalyzedReq = LoggerPlusPlus.callbacks.getHelpers().analyzeRequest(request);
    200  - List<IParameter> params = tempAnalyzedReq.getParameters().stream()
    201  - .filter(iParameter -> iParameter.getType() == paramType).collect(Collectors.toList());
    202  - return params;
    203  - }
    204  - 
    205  - private List<IParameter> getRequestBodyParameters(byte[] request) {
    206  - IRequestInfo tempAnalyzedReq = LoggerPlusPlus.callbacks.getHelpers().analyzeRequest(request);
    207  - List<IParameter> params = tempAnalyzedReq.getParameters().stream()
    208  - .filter(iParameter -> iParameter.getType() != IParameter.PARAM_COOKIE
    209  - && iParameter.getType() != IParameter.PARAM_URL)
     188 + private List<HttpParameter> getRequestParametersByType(HttpRequest request, HttpParameterType paramType) {
     189 + return request.parameters().stream()
     190 + .filter(iParameter -> iParameter.type().equals(paramType))
    210 191   .collect(Collectors.toList());
    211  - return params;
    212 192   }
     193 + 
    213 194   
    214 195   @Override
    215 196   public List<LogEntry> read(JsonReader reader) throws IOException {
    216 197   // TODO Implement HAR Import logic
    217 198   return null;
    218  - }
    219  - 
    220  - private List<ICookie> getResponseCookies(byte[] responseMessage) {
    221  - IResponseInfo tempAnalyzedResp = LoggerPlusPlus.callbacks.getHelpers().analyzeResponse(responseMessage);
    222  - 
    223  - return tempAnalyzedResp.getCookies();
    224 199   }
    225 200   
    226 201  }
    skipped 1 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/JSONExporter.java
    skipped 1 lines
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Preferences;
    4 4  import com.google.gson.Gson;
     5 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 6  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 7  import com.nccgroup.loggerplusplus.util.MoreHelp;
    7 8  import com.nccgroup.loggerplusplus.util.SwingWorkerWithProgressDialog;
    skipped 33 lines
    41 42   protected Void doInBackground() throws Exception {
    42 43   super.doInBackground();
    43 44   try(FileWriter fileWriter = new FileWriter(file, false)) {
    44  - Gson gson = exportController.getLoggerPlusPlus().getGsonProvider().getGson();
     45 + Gson gson = LoggerPlusPlus.gsonProvider.getGson();
    45 46   gson.toJson(entries, fileWriter);
    46 47   }
    47 48   
    skipped 34 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/JSONExporterControlPanel.java
    skipped 1 lines
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Alignment;
    4 4  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
     5 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 6  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 7   
    7 8  import javax.swing.*;
    skipped 7 lines
    15 16   
    16 17   JButton manualSaveButton = new JButton("Export as JSON");
    17 18   manualSaveButton.addActionListener(actionEvent -> {
    18  - final List<LogEntry> entries = jsonExporter.getExportController().getLoggerPlusPlus().getLogEntries();
     19 + final List<LogEntry> entries = LoggerPlusPlus.instance.getLogEntries();
    19 20   jsonExporter.exportEntries(entries);
    20 21   });
    21 22   
    skipped 11 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filter/colorfilter/ColorFilter.java
    1 1  package com.nccgroup.loggerplusplus.filter.colorfilter;
    2 2   
    3 3  import com.nccgroup.loggerplusplus.filter.logfilter.LogFilter;
    4  -import com.nccgroup.loggerplusplus.filter.logfilter.LogFilterController;
    5 4  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    6 5  import com.nccgroup.loggerplusplus.filterlibrary.FilterLibraryController;
    7 6   
    skipped 138 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filter/parser/Filter.jj
    skipped 11 lines
    12 12   
    13 13  PARSER_BEGIN(FilterParser)
    14 14  package com.nccgroup.loggerplusplus.filter.parser;
    15  -import com.nccgroup.loggerplusplus.filter.ComparisonOperator;import com.nccgroup.loggerplusplus.filter.LogicalOperator;
     15 +import com.nccgroup.loggerplusplus.filter.LogicalOperator;
    16 16  import com.nccgroup.loggerplusplus.filter.ComparisonOperator;
    17 17  import com.nccgroup.loggerplusplus.filterlibrary.FilterLibraryController;
    18 18  import java.io.StringReader;
    skipped 31 lines
    50 50   private static void throwOperatorAmbiguityException(LogicalOperator op, LogicalOperator other) throws ParseException {
    51 51   throw new ParseException(String.format("Cannot mix operators %s, %s. Please use parenthesis to remove ambiguity.", op.getLabel(), other.getLabel()));
    52 52   }
     53 +}}
    53 54  }
    54 55   
    55 56  PARSER_END(FilterParser)
    skipped 532 lines
  • ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filter/parser/Filter.jjt
    skipped 11 lines
    12 12  PARSER_BEGIN(FilterParser)
    13 13  package com.nccgroup.loggerplusplus.filter.parser;
    14 14  import com.nccgroup.loggerplusplus.filter.ComparisonOperator;import com.nccgroup.loggerplusplus.filter.LogicalOperator;
    15  -import com.nccgroup.loggerplusplus.filter.ComparisonOperator;
    16 15  import com.nccgroup.loggerplusplus.filterlibrary.FilterLibraryController;
    17 16  import java.io.StringReader;
    18 17  import java.math.BigDecimal;
    skipped 27 lines
    46 45   private static void throwOperatorAmbiguityException(LogicalOperator op, LogicalOperator other) throws ParseException {
    47 46   throw new ParseException(String.format("Cannot mix operators %s, %s. Please use parenthesis to remove ambiguity.", op.getLabel(), other.getLabel()));
    48 47   }
     48 +}}
    49 49  }
    50 50   
    51 51  PARSER_END(FilterParser)
    skipped 453 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filterlibrary/FilterLibraryController.java
    skipped 9 lines
    10 10  import com.nccgroup.loggerplusplus.filter.tag.TagListener;
    11 11  import com.nccgroup.loggerplusplus.preferences.PreferencesController;
    12 12  import com.nccgroup.loggerplusplus.util.Globals;
     13 +import lombok.extern.log4j.Log4j2;
    13 14  import org.apache.logging.log4j.LogManager;
    14 15  import org.apache.logging.log4j.Logger;
    15 16   
    skipped 2 lines
    18 19  import java.util.HashMap;
    19 20  import java.util.UUID;
    20 21   
     22 +@Log4j2
    21 23  public class FilterLibraryController {
    22 24   
    23  - private final LoggerPlusPlus loggerPlusPlus;
    24 25   private final Preferences preferences;
    25 26   private final FilterLibraryPanel panel;
    26 27   private final ArrayList<FilterLibraryListener> listeners;
    skipped 3 lines
    30 31   private final HashMap<UUID, Tag> tagFilters;
    31 32   private final ArrayList<TagListener> tagListeners;
    32 33   
    33  - Logger logger = LogManager.getRootLogger();
    34  - 
    35  - public FilterLibraryController(LoggerPlusPlus loggerPlusPlus, PreferencesController preferencesController) {
    36  - this.loggerPlusPlus = loggerPlusPlus;
     34 + public FilterLibraryController(PreferencesController preferencesController) {
    37 35   this.preferences = preferencesController.getPreferences();
    38 36   this.listeners = new ArrayList<>();
    39 37   this.colorFilterListeners = new ArrayList<>();
    skipped 2 lines
    42 40   this.colorFilters = preferences.getSetting(Globals.PREF_COLOR_FILTERS);
    43 41   this.tagFilters = preferences.getSetting(Globals.PREF_TAG_FILTERS);
    44 42   this.panel = new FilterLibraryPanel(this);
    45  - }
    46  - 
    47  - public LoggerPlusPlus getLoggerPlusPlus() {
    48  - return loggerPlusPlus;
    49 43   }
    50 44   
    51 45   public FilterLibraryPanel getFilterLibraryPanel() {
    skipped 67 lines
    119 113   try {
    120 114   colorFilterListener.onColorFilterAdd(colorFilter);
    121 115   } catch (Exception e) {
    122  - logger.error(e);
     116 + log.error(e);
    123 117   }
    124 118   }
    125 119   saveColorFilters();
    skipped 7 lines
    133 127   try{
    134 128   listener.onColorFilterRemove(colorFilter);
    135 129   }catch (Exception e){
    136  - logger.error(e);
     130 + log.error(e);
    137 131   }
    138 132   }
    139 133   saveColorFilters();
    skipped 5 lines
    145 139   try{
    146 140   listener.onColorFilterChange(colorFilter);
    147 141   }catch (Exception e){
    148  - logger.error(e);
     142 + log.error(e);
    149 143   }
    150 144   }
    151 145   saveColorFilters();
    skipped 22 lines
    174 168   try {
    175 169   listener.onTagAdd(tag);
    176 170   } catch (Exception error) {
    177  - logger.error(error);
     171 + log.error(error);
    178 172   }
    179 173   }
    180 174   saveTags();
    skipped 7 lines
    188 182   try {
    189 183   listener.onTagRemove(tag);
    190 184   } catch (Exception error) {
    191  - logger.error(error);
     185 + log.error(error);
    192 186   }
    193 187   }
    194 188   saveTags();
    skipped 5 lines
    200 194   try {
    201 195   listener.onTagChange(tag);
    202 196   } catch (Exception e) {
    203  - logger.error(e);
     197 + log.error(e);
    204 198   }
    205 199   }
    206 200   saveTags();
    skipped 16 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filterlibrary/FilterLibraryPanel.java
    1 1  package com.nccgroup.loggerplusplus.filterlibrary;
    2 2   
    3  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    4 3  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    5 4  import com.nccgroup.loggerplusplus.filter.savedfilter.SavedFilter;
    6 5  import com.nccgroup.loggerplusplus.util.userinterface.renderer.ButtonRenderer;
    skipped 69 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/filterlibrary/FilterLibraryTableModel.java
    1 1  package com.nccgroup.loggerplusplus.filterlibrary;
    2 2   
    3  -import burp.BurpExtender;
    4 3  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 4  import com.nccgroup.loggerplusplus.filter.logfilter.LogFilter;
    6 5  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    skipped 83 lines
    90 89   if(row < 0 || row >= controller.getSavedFilters().size()) return;
    91 90   SavedFilter savedFilter = controller.getSavedFilters().get(row);
    92 91   if(col == 2){
    93  - controller.getLoggerPlusPlus().getLogViewController().getLogFilterController().setFilter(savedFilter.getFilterString());
    94  - controller.getLoggerPlusPlus().getMainViewController().getTabbedPanel().setSelectedIndex(0);
     92 + LoggerPlusPlus.instance.getLogViewController().getLogFilterController().setFilter(savedFilter.getFilterString());
     93 + LoggerPlusPlus.instance.getMainViewController().getTabbedPanel().setSelectedIndex(0);
    95 94   return;
    96 95   }
    97 96   if(col == 3){
    skipped 29 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/grepper/GrepResultsTable.java
    1 1  package com.nccgroup.loggerplusplus.grepper;
    2 2   
     3 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    3 4  import com.nccgroup.loggerplusplus.logview.logtable.LogTable;
    4 5  import org.jdesktop.swingx.JXTree;
    5 6  import org.jdesktop.swingx.JXTreeTable;
    skipped 45 lines
    51 52   public void actionPerformed(ActionEvent actionEvent) {
    52 53   LogTable table = controller.getLogTableController().getLogTable();
    53 54   table.changeSelection(table.convertRowIndexToView(index), 1, false, false);
    54  - controller.getLoggerPlusPlus().getMainViewController().getTabbedPanel().setSelectedIndex(0);
     55 + LoggerPlusPlus.instance.getMainViewController().getTabbedPanel().setSelectedIndex(0);
    55 56   }
    56 57   });
    57 58   menu.add(viewInLogs);
    skipped 167 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperController.java
    1 1  package com.nccgroup.loggerplusplus.grepper;
    2 2   
    3  -import burp.IHttpRequestResponse;
    4  -import burp.IHttpRequestResponseWithMarkers;
     3 +import burp.api.montoya.core.Annotations;
     4 +import burp.api.montoya.core.Range;
     5 +import burp.api.montoya.http.message.HttpRequestResponse;
     6 +import burp.api.montoya.http.message.MarkedHttpRequestResponse;
    5 7  import com.coreyd97.BurpExtenderUtilities.Preferences;
    6 8  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    7 9  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    skipped 12 lines
    20 22   
    21 23  public class GrepperController {
    22 24   
    23  - private final LoggerPlusPlus loggerPlusPlus;
    24 25   private final LogTableController logTableController;
    25 26   private final Preferences preferences;
    26 27   private final GrepperPanel grepPanel;
    skipped 2 lines
    29 30   
    30 31   private ExecutorService searchExecutor;
    31 32   
    32  - public GrepperController(LoggerPlusPlus loggerPlusPlus, LogTableController logTableController, PreferencesController preferencesController){
    33  - this.loggerPlusPlus = loggerPlusPlus;
     33 + public GrepperController(LogTableController logTableController, PreferencesController preferencesController){
    34 34   this.logTableController = logTableController;
    35 35   this.preferences = preferencesController.getPreferences();
    36 36   this.listeners = new ArrayList<>();
    37 37   this.remainingEntries = new AtomicInteger(0);
    38 38   this.grepPanel = new GrepperPanel(this, preferences);
    39  - }
    40  - 
    41  - public LoggerPlusPlus getLoggerPlusPlus() {
    42  - return loggerPlusPlus;
    43 39   }
    44 40   
    45 41   public LogTableController getLogTableController() {
    skipped 18 lines
    64 60   }
    65 61   }
    66 62   
    67  - public IHttpRequestResponseWithMarkers addMarkers(IHttpRequestResponse requestResponse, List<GrepResults.Match> matches) {
    68  - List<int[]> requestMarkers = new ArrayList<>(), responseMarkers = new ArrayList<>();
     63 + public MarkedHttpRequestResponse addMarkers(HttpRequestResponse requestResponse, List<GrepResults.Match> matches) {
     64 + List<Range> requestMarkers = new ArrayList<>(), responseMarkers = new ArrayList<>();
    69 65   for (GrepResults.Match match : matches) {
    70  - int[] marker = new int[]{match.startIndex, match.endIndex};
     66 + Range marker = Range.range(match.startIndex, match.endIndex);
    71 67   if (match.isRequest) requestMarkers.add(marker);
    72 68   else responseMarkers.add(marker);
    73 69   }
    74 70   
    75  - return LoggerPlusPlus.callbacks.applyMarkers(requestResponse, requestMarkers, responseMarkers);
     71 + return requestResponse.withMarkers(requestMarkers, responseMarkers);
    76 72   }
    77 73   
    78 74   public void beginSearch(final Pattern pattern, final boolean inScopeOnly, final boolean searchRequests, final boolean searchResponses) {
    skipped 1 lines
    80 76   this.searchExecutor = Executors.newFixedThreadPool(searchThreads, new NamedThreadFactory("LPP-Grepper"));
    81 77   
    82 78   new Thread(() -> {
    83  - ArrayList<LogEntry> logEntries = new ArrayList<>(loggerPlusPlus.getLogViewController().getLogTableController().getLogTableModel().getData());
     79 + ArrayList<LogEntry> logEntries = new ArrayList<>(LoggerPlusPlus.instance.getLogViewController().getLogTableController().getLogTableModel().getData());
    84 80   remainingEntries.getAndSet(logEntries.size());
    85 81   
    86 82   this.listeners.forEach(listener -> {
    skipped 10 lines
    97 93   GrepResults grepResults = null;
    98 94   if (entry != null) {
    99 95   grepResults = new GrepResults(entry);
    100  - if (entry.getRequest() != null && searchRequests) {
    101  - processMatches(grepResults, pattern, entry.getRequest(), true);
     96 + if (entry.getRequestBytes() != null && searchRequests) {
     97 + processMatches(grepResults, pattern, entry.getRequestBytes(), true);
    102 98   }
    103  - if (entry.getResponse() != null && searchResponses) {
    104  - processMatches(grepResults, pattern, entry.getResponse(), false);
     99 + if (entry.getResponseBytes() != null && searchResponses) {
     100 + processMatches(grepResults, pattern, entry.getResponseBytes(), false);
    105 101   }
    106 102   }
    107 103   return grepResults;
    skipped 20 lines
    128 124   return () -> {
    129 125   if (Thread.currentThread().isInterrupted()) return;
    130 126   GrepResults grepResults = null;
    131  - if (!inScopeOnly || LoggerPlusPlus.callbacks.isInScope(logEntry.getUrl())) {
     127 + if (!inScopeOnly || LoggerPlusPlus.isUrlInScope(logEntry.getUrlString())) {
    132 128   grepResults = processEntry(logEntry, pattern, searchRequests, searchResponses);
    133 129   }
    134 130   for (GrepperListener listener : this.listeners) {
    skipped 60 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperPanel.java
    skipped 2 lines
    3 3  import com.coreyd97.BurpExtenderUtilities.HistoryField;
    4 4  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
    5 5  import com.coreyd97.BurpExtenderUtilities.Preferences;
     6 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    6 7  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    7 8  import com.nccgroup.loggerplusplus.logview.entryviewer.RequestViewerController;
    8 9  import com.nccgroup.loggerplusplus.util.Globals;
    skipped 63 lines
    72 73   });
    73 74   
    74 75   this.grepResultsTable = new GrepResultsTable(controller);
    75  - this.requestViewerController = new RequestViewerController(preferences, false, false);
     76 + this.requestViewerController = new RequestViewerController(preferences);
    76 77   
    77 78   grepResultsTable.addTreeSelectionListener(treeSelectionEvent -> {
    78 79   TreePath selectedPath = treeSelectionEvent.getPath();
    skipped 58 lines
    137 138   try {
    138 139   pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
    139 140   } catch (PatternSyntaxException e) {
    140  - JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(controller.getLoggerPlusPlus().getMainViewController().getUiComponent()), "Pattern Syntax Invalid", "Invalid Pattern", JOptionPane.ERROR_MESSAGE);
     141 + JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(LoggerPlusPlus.instance.getMainViewController().getUiComponent()), "Pattern Syntax Invalid", "Invalid Pattern", JOptionPane.ERROR_MESSAGE);
    141 142   return;
    142 143   }
    143 144   
    skipped 58 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/imports/ImportRequestResponse.java
    1  -//
    2  -// Burp Suite Logger++
    3  -//
    4  -// Released as open source by NCC Group Plc - https://www.nccgroup.trust/
    5  -//
    6  -// Originally Developed by Soroush Dalili (@irsdl)
    7  -// Maintained by Corey Arthur (@CoreyD97)
    8  -//
    9  -// Project link: http://www.github.com/nccgroup/BurpSuiteLoggerPlusPlus
    10  -//
    11  -// Released under AGPL see LICENSE for more information
    12  -//
    13  - 
    14  -package com.nccgroup.loggerplusplus.imports;
    15  - 
    16  -import java.net.URL;
    17  - 
    18  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    19  - 
    20  -import burp.IHttpRequestResponse;
    21  -import burp.IHttpService;
    22  - 
    23  -class ImportRequestResponse implements IHttpRequestResponse {
    24  - 
    25  - private IHttpService service;
    26  - private byte[] request;
    27  - private byte[] response;
    28  - private String comment;
    29  - private String highlight;
    30  - 
    31  - ImportRequestResponse(String url, byte[] req, byte[] res) {
    32  - LoggerHttpService srv = new LoggerHttpService(url);
    33  - setHttpService(srv);
    34  - setRequest(req);
    35  - setResponse(res);
    36  - }
    37  - 
    38  - @Override
    39  - public byte[] getRequest() {
    40  - return request;
    41  - }
    42  - 
    43  - @Override
    44  - public void setRequest(byte[] message) {
    45  - request = message;
    46  - }
    47  - 
    48  - @Override
    49  - public byte[] getResponse() {
    50  - return response;
    51  - }
    52  - 
    53  - @Override
    54  - public void setResponse(byte[] message) {
    55  - response = message;
    56  - }
    57  - 
    58  - @Override
    59  - public String getComment() {
    60  - return comment;
    61  - }
    62  - 
    63  - @Override
    64  - public void setComment(String c) {
    65  - comment = c;
    66  - }
    67  - 
    68  - @Override
    69  - public String getHighlight() {
    70  - return highlight;
    71  - }
    72  - 
    73  - @Override
    74  - public void setHighlight(String color) {
    75  - highlight = color;
    76  - }
    77  - 
    78  - @Override
    79  - public IHttpService getHttpService() {
    80  - return service;
    81  - }
    82  - 
    83  - @Override
    84  - public void setHttpService(IHttpService httpService) {
    85  - service = httpService;
    86  - }
    87  - 
    88  - private static class LoggerHttpService implements IHttpService {
    89  - 
    90  - private String host;
    91  - private int port;
    92  - private String protocol;
    93  - 
    94  - LoggerHttpService(String urlS) {
    95  - URL url;
    96  - try {
    97  - url = new URL(urlS);
    98  - } catch (Exception e) {
    99  - LoggerPlusPlus.callbacks.printError("LoggerHttpService: Error Parsing URL: " + urlS);
    100  - LoggerPlusPlus.callbacks.printError(e.toString());
    101  - return;
    102  - }
    103  - 
    104  - host = url.getHost();
    105  - protocol = url.getProtocol();
    106  - port = url.getPort();
    107  - 
    108  - if ( port < 1 ) {
    109  - switch (protocol) {
    110  - case "http":
    111  - port = 80;
    112  - break;
    113  - case "https":
    114  - port = 443;
    115  - break;
    116  - }
    117  - }
    118  - }
    119  - 
    120  - @Override
    121  - public String getHost() {
    122  - return host;
    123  - }
    124  - 
    125  - @Override
    126  - public int getPort() {
    127  - return port;
    128  - }
    129  - 
    130  - @Override
    131  - public String getProtocol() {
    132  - return protocol;
    133  - }
    134  - 
    135  - }
    136  -}
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/imports/LoggerImport.java
    skipped 12 lines
    13 13   
    14 14  package com.nccgroup.loggerplusplus.imports;
    15 15   
    16  -import burp.IBurpExtenderCallbacks;
    17  -import burp.IExtensionHelpers;
    18  -import burp.IHttpRequestResponse;
     16 +import burp.api.montoya.core.ByteArray;
     17 +import burp.api.montoya.core.ToolType;
     18 +import burp.api.montoya.http.HttpService;
     19 +import burp.api.montoya.http.message.HttpRequestResponse;
     20 +import burp.api.montoya.http.message.requests.HttpRequest;
     21 +import burp.api.montoya.http.message.responses.HttpResponse;
    19 22  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    20 23  import com.nccgroup.loggerplusplus.logview.processor.EntryImportWorker;
     24 +import lombok.extern.log4j.Log4j2;
    21 25   
    22 26  import javax.swing.*;
    23 27  import java.io.BufferedReader;
    skipped 2 lines
    26 30  import java.io.IOException;
    27 31  import java.net.URL;
    28 32  import java.util.ArrayList;
     33 +import java.util.Base64;
    29 34  import java.util.Iterator;
    30 35   
     36 +@Log4j2
    31 37  public class LoggerImport {
    32 38   
    33 39   public static String getLoadFile() {
    skipped 16 lines
    50 56   try {
    51 57   reader = new BufferedReader(new FileReader(filename));
    52 58   } catch (FileNotFoundException e) {
    53  - LoggerPlusPlus.callbacks.printError("LoggerImport-readFile: Error Opening File " + filename);
     59 + log.error("LoggerImport-readFile: Error Opening File " + filename);
    54 60   return new ArrayList<String>();
    55 61   }
    56 62   try {
    skipped 2 lines
    59 65   lines.add(line);
    60 66   }
    61 67   } catch (IOException e) {
    62  - LoggerPlusPlus.callbacks.printError("LoggerImport-readFile: Error Reading Line");
     68 + log.error("LoggerImport-readFile: Error Reading Line");
    63 69   return new ArrayList<String>();
    64 70   }
    65 71   
    66 72   return lines;
    67 73   }
    68 74   
    69  - public static ArrayList<IHttpRequestResponse> importWStalker() {
     75 + public static ArrayList<HttpRequestResponse> importWStalker() {
    70 76   ArrayList<String> lines;
    71  - ArrayList<IHttpRequestResponse> requests = new ArrayList<>();
    72  - IExtensionHelpers helpers = LoggerPlusPlus.callbacks.getHelpers();
     77 + ArrayList<HttpRequestResponse> requests = new ArrayList<>();
    73 78  
    74 79   String filename = getLoadFile();
    75 80   if ( filename.length() == 0 ) { // exit if no file selected
    skipped 8 lines
    84 89   String line = i.next();
    85 90   String[] v = line.split(","); // Format: "base64(request),base64(response),url"
    86 91   
    87  - byte[] request = helpers.base64Decode(v[0]);
    88  - byte[] response = helpers.base64Decode(v[1]);
    89 92   String url = v[3];
     93 + Base64.Decoder b64Decoder = LoggerPlusPlus.montoya.utilities().base64Utils().getDecoder();
     94 + HttpService httpService = HttpService.httpService(url);
     95 + HttpRequest httpRequest = HttpRequest.httpRequest(httpService, ByteArray.byteArray(b64Decoder.decode(v[0])));
     96 + HttpResponse httpResponse = HttpResponse.httpResponse(ByteArray.byteArray(b64Decoder.decode(v[1])));
     97 + HttpRequestResponse requestResponse = HttpRequestResponse.httpRequestResponse(httpRequest, httpResponse);
    90 98   
    91  - ImportRequestResponse x = new ImportRequestResponse(url, request, response);
    92  - requests.add(x);
     99 + requests.add(requestResponse);
    93 100   
    94 101   } catch (Exception e) {
    95  - LoggerPlusPlus.callbacks.printError("LoggerImport-importWStalker: Error Parsing Content");
    96  - return new ArrayList<IHttpRequestResponse>();
     102 + log.error("LoggerImport-importWStalker: Error Parsing Content");
     103 + return new ArrayList<>();
    97 104   }
    98 105   }
    99 106   
    100 107   return requests;
    101 108   }
    102 109   
    103  - public static ArrayList<IHttpRequestResponse> importZAP() {
     110 + public static ArrayList<HttpRequestResponse> importZAP() {
    104 111   ArrayList<String> lines = new ArrayList<String>();
    105  - ArrayList<IHttpRequestResponse> requests = new ArrayList<IHttpRequestResponse>();
    106  - IExtensionHelpers helpers = LoggerPlusPlus.callbacks.getHelpers();
     112 + ArrayList<HttpRequestResponse> requests = new ArrayList<HttpRequestResponse>();
    107 113  
    108 114   String filename = getLoadFile();
    109 115   if ( filename.length() == 0 ) { // exit if no file selected
    110  - return new ArrayList<IHttpRequestResponse>();
     116 + return new ArrayList<HttpRequestResponse>();
    111 117   }
    112 118   
    113 119   lines = readFile(filename);
    skipped 25 lines
    139 145   if ( line.matches(reSeparator) || !i.hasNext() ) {
    140 146   // TODO: Remove one or two \n at the end of requestBuffer
    141 147   
    142  - byte[] req = helpers.stringToBytes(requestBuffer);
    143  - byte[] res = helpers.stringToBytes(responseBuffer);
     148 + HttpService httpService = HttpService.httpService(url);
     149 + HttpRequest httpRequest = HttpRequest.httpRequest(httpService, requestBuffer);
     150 + HttpResponse httpResponse = HttpResponse.httpResponse(responseBuffer);
     151 + HttpRequestResponse requestResponse = HttpRequestResponse.httpRequestResponse(httpRequest, httpResponse);
    144 152   
    145  - // Add IHttpRequestResponse Object
    146  - ImportRequestResponse x = new ImportRequestResponse(url, req, res);
    147  - requests.add(x);
     153 + requests.add(requestResponse);
    148 154   
    149 155   // Reset content
    150 156   isRequest = true;
    skipped 16 lines
    167 173   line = x[0] + " " + path + " " + x[2]; // fix the path in the request
    168 174   
    169 175   } catch (Exception e) {
    170  - LoggerPlusPlus.callbacks.printError("importZAP: Wrong Path Format");
     176 + log.error("importZAP: Wrong Path Format");
    171 177   return new ArrayList<>();
    172 178   }
    173 179   }
    skipped 16 lines
    190 196   return requests;
    191 197   }
    192 198   
    193  - public static boolean loadImported(ArrayList<IHttpRequestResponse> requests, Boolean sendToAutoExporters) {
     199 + public static boolean loadImported(ArrayList<HttpRequestResponse> requests, Boolean sendToAutoExporters) {
    194 200   EntryImportWorker importWorker = LoggerPlusPlus.instance.getLogProcessor().createEntryImportBuilder()
    195  - .setOriginatingTool(IBurpExtenderCallbacks.TOOL_EXTENDER)
    196  - .setEntries(requests)
     201 + .setOriginatingTool(ToolType.EXTENSIONS)
     202 + .setHttpEntries(requests)
    197 203   .setInterimConsumer(integers -> {
    198 204   //Optional
    199 205   //Outputs chunks of integers representing imported indices
    skipped 11 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java
    skipped 12 lines
    13 13   
    14 14  package com.nccgroup.loggerplusplus.logentry;
    15 15   
    16  -import burp.*;
     16 +import burp.api.montoya.core.ToolType;
     17 +import burp.api.montoya.http.HttpService;
     18 +import burp.api.montoya.http.MimeType;
     19 +import burp.api.montoya.http.message.cookies.Cookie;
     20 +import burp.api.montoya.http.message.headers.HttpHeader;
     21 +import burp.api.montoya.http.message.params.HttpParameter;
     22 +import burp.api.montoya.http.message.params.HttpParameterType;
     23 +import burp.api.montoya.http.message.requests.HttpRequest;
     24 +import burp.api.montoya.http.message.responses.HttpResponse;
    17 25  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    18 26  import com.nccgroup.loggerplusplus.filter.colorfilter.ColorFilter;
    19 27  import com.nccgroup.loggerplusplus.filter.tag.Tag;
    20 28  import com.nccgroup.loggerplusplus.logview.processor.LogProcessor;
    21  -import com.nccgroup.loggerplusplus.logview.processor.LogProcessorHelper;
    22 29  import com.nccgroup.loggerplusplus.reflection.ReflectionController;
    23 30  import com.nccgroup.loggerplusplus.util.Globals;
    24 31  import lombok.AccessLevel;
    skipped 2 lines
    27 34  import org.apache.commons.codec.digest.DigestUtils;
    28 35  import org.apache.commons.lang3.StringUtils;
    29 36   
     37 +import java.net.MalformedURLException;
    30 38  import java.net.URL;
    31  -import java.nio.charset.StandardCharsets;
    32 39  import java.text.ParseException;
    33 40  import java.util.*;
    34 41  import java.util.regex.Matcher;
    skipped 6 lines
    41 48   Status previousStatus;
    42 49   Status status = Status.UNPROCESSED;
    43 50   
    44  - @Getter(AccessLevel.NONE)
     51 + @Setter(AccessLevel.NONE)
     52 + private HttpRequest request;
    45 53   @Setter(AccessLevel.NONE)
    46  - private IHttpRequestResponse requestResponse; //Only used for request, comment and HTTP Service.
    47  - private byte[] response;
     54 + private HttpResponse response;
    48 55   
    49 56   private Integer identifier;
    50  - private int tool;
    51  - private String toolName;
     57 + private ToolType tool;
    52 58   private String hostname = "";
    53 59   private String host = ""; // TODO better name?
    54 60   private String method = "";
     61 + private String urlString;
    55 62   private URL url;
    56 63   private boolean params = false;
    57 64   private Short responseStatus = -1;
    skipped 2 lines
    60 67   private boolean hasBodyParam = false;
    61 68   private boolean hasCookieParam = false;
    62 69   private String title = "";
    63  - private String newCookies = "";
     70 + private String comment;
     71 + private List<String> newCookies = new ArrayList<>();
    64 72   private String sentCookies = "";
    65 73   private String listenerInterface = "";
    66 74   private boolean isSSL = false;
    skipped 7 lines
    74 82   private String clientIP = "";
    75 83   private boolean hasSetCookies = false;
    76 84   private String formattedResponseTime = "";
    77  - private String responseMimeType = "";
    78  - private String responseInferredMimeType = "";
     85 + private MimeType responseMimeType;
     86 + private MimeType responseInferredMimeType;
    79 87   private int responseBodyLength = -1;
    80 88   private String responseContentType = "";
    81 89   private boolean complete = false;
    skipped 10 lines
    92 100   private Date responseDateTime = new Date(0); //Zero epoch dates to prevent null. Response date pulled from response headers
    93 101   private Date requestDateTime = new Date(0); //Zero epoch dates to prevent null. Response date pulled from response headers
    94 102   private int requestResponseDelay = -1;
    95  - private List<String> responseHeaders;
    96  - private List<String> requestHeaders;
    97  - private List<IParameter> tempParameters;
     103 + private List<HttpHeader> responseHeaders;
     104 + private List<HttpHeader> requestHeaders;
    98 105   private List<String> parameters;
    99 106   private List<String> reflectedParameters;
    100 107   
    101 108   private LogEntry() {
    102  - this.matchingColorFilters = Collections.synchronizedList(new ArrayList<UUID>());
    103  - this.matchingTags = Collections.synchronizedList(new ArrayList<Tag>());
     109 + this.matchingColorFilters = Collections.synchronizedList(new ArrayList<>());
     110 + this.matchingTags = Collections.synchronizedList(new ArrayList<>());
    104 111   }
    105 112   
    106  - public LogEntry(int tool, IHttpRequestResponse requestResponse) {
     113 + public LogEntry(ToolType tool, HttpRequest request) {
    107 114   this();
    108 115   this.tool = tool;
    109  - this.toolName = LoggerPlusPlus.callbacks.getToolName(tool);
    110  - this.requestResponse = requestResponse;
    111  - this.response = requestResponse.getResponse();
     116 + this.request = request;
     117 + }
     118 + 
     119 + public LogEntry(ToolType tool, HttpRequest request, HttpResponse response){
     120 + this(tool, request);
     121 + this.response = response;
    112 122   }
    113 123   
    114 124   /**
    115 125   * Create new entry and specify arrival time.
    116 126   *
    117 127   * @param tool
     128 + * @param request
    118 129   * @param formattedRequestTime
    119  - * @param requestResponse
    120 130   */
    121  - public LogEntry(int tool, Date formattedRequestTime, IHttpRequestResponse requestResponse) {
    122  - this(tool, requestResponse);
     131 + public LogEntry(ToolType tool, HttpRequest request, Date formattedRequestTime) {
     132 + this(tool, request);
    123 133   this.setReqestTime(formattedRequestTime);
    124 134   }
    125 135   
    126  - public void process() {
    127  - // TODO Move into separate processing class
     136 + public boolean process() {
    128 137   previousStatus = this.status;
    129 138   switch (this.status) {
    130 139   case UNPROCESSED: {
    131 140   this.status = processRequest();
    132  - // If the entry should be ignored, break here.
     141 + // If the entry should be ignored, stop here.
    133 142   if (this.status == Status.IGNORED)
    134  - break;
     143 + return true;
    135 144   
    136 145   // Else continue, fall through to process response
    137 146   }
    138 147   case AWAITING_RESPONSE: {
    139 148   if (this.response == null) {
    140 149   this.status = Status.AWAITING_RESPONSE;
    141  - break;
     150 + return false;
    142 151   }
    143 152   processResponse();
    144 153   this.status = Status.PROCESSED;
     154 + return true;
    145 155   }
    146 156   
    147 157   case IGNORED:
    148 158   case PROCESSED: {
    149 159   // Nothing to do, we're done!
    150  - break;
     160 + return true;
    151 161   }
     162 + 
     163 + default: return false;
    152 164   }
    153 165   }
    154 166   
    skipped 11 lines
    166 178   }
    167 179   
    168 180   private Status processRequest() {
    169  - IRequestInfo tempAnalyzedReq = LoggerPlusPlus.callbacks.getHelpers().analyzeRequest(this.requestResponse);
    170  - URL uUrl = tempAnalyzedReq.getUrl();
    171  - if (!LoggerPlusPlus.isUrlInScope(uUrl))
    172  - return Status.IGNORED;
     181 + 
    173 182   
    174  - requestHeaders = tempAnalyzedReq.getHeaders();
     183 + requestHeaders = request.headers();
    175 184   
    176 185   // Get HTTP Version, which would be the last token in "GET /admin/login/?next\u003d/admin/ HTTP/1.1"
    177  - String[] httpRequestTokens = requestHeaders.get(0).split(" ");
     186 + String[] httpRequestTokens = requestHeaders.get(0).value().split(" ");
    178 187   this.requestHttpVersion = httpRequestTokens[httpRequestTokens.length - 1];
    179 188   
    180  - this.tempParameters = tempAnalyzedReq.getParameters().stream()
    181  - .filter(iParameter -> iParameter.getType() != IParameter.PARAM_COOKIE).collect(Collectors.toList());
    182  - this.parameters = tempParameters.stream().map(IParameter::getName).collect(Collectors.toList());
     189 + this.parameters = request.parameters().stream()
     190 + .filter(param -> param.type() != HttpParameterType.COOKIE)
     191 + .map(HttpParameter::name)
     192 + .collect(Collectors.toList());
    183 193   
    184  - this.url = tempAnalyzedReq.getUrl();
    185  - this.hostname = this.requestResponse.getHttpService().getHost();
    186  - this.protocol = this.requestResponse.getHttpService().getProtocol();
    187  - this.isSSL = this.protocol.equals("https");
    188  - this.targetPort = this.requestResponse.getHttpService().getPort();
     194 + this.urlString = request.url();
     195 + this.hostname = this.request.httpService().host();
     196 + this.protocol = this.request.httpService().secure() ? "https" : "http";
     197 + this.isSSL = this.request.httpService().secure();
     198 + this.targetPort = this.request.httpService().port();
    189 199   
    190 200   boolean isDefaultPort = (this.protocol.equals("https") && this.targetPort == 443)
    191 201   || (this.protocol.equals("http") && this.targetPort == 80);
    192 202   
    193 203   this.host = this.protocol + "://" + this.hostname + (isDefaultPort ? "" : ":" + this.targetPort);
    194 204   
    195  - this.method = tempAnalyzedReq.getMethod();
     205 + this.method = request.method();
     206 + this.requestBodyLength = this.getRequestBytes().length - request.bodyOffset();
     207 + this.hasBodyParam = requestBodyLength > 0;
     208 + 
    196 209   try {
     210 + this.url = new URL(request.url());
     211 + 
    197 212   // I don't want to delete special characters such as ; or : from the extension
    198 213   // as it may really be part of the extension! (burp proxy log ignores them)
    199  - String tempPath = this.url.getPath().replaceAll("\\\\", "/");
     214 + String tempPath = url.getPath().replaceAll("\\\\", "/");
    200 215   tempPath = tempPath.substring(tempPath.lastIndexOf("/"));
    201 216   int tempPathDotLocation = tempPath.lastIndexOf(".");
    202  - if (tempPathDotLocation >= 0)
     217 + if (tempPathDotLocation >= 0) {
    203 218   this.urlExtension = tempPath.substring(tempPathDotLocation + 1);
    204  - } catch (Exception e) {
    205  - this.urlExtension = "";
    206  - }
     219 + }
     220 + this.params = url.getQuery() != null || this.hasBodyParam;
     221 + } catch (MalformedURLException ignored) {}
    207 222   
    208  - this.requestBodyLength = this.getRequest().length - tempAnalyzedReq.getBodyOffset();
    209  - this.hasBodyParam = requestBodyLength > 0;
    210  - this.params = this.url.getQuery() != null || this.hasBodyParam;
    211  - this.hasCookieParam = false;
     223 + 
     224 + 
    212 225   
    213 226   // reading request headers like a boss!
    214  - for (String item : requestHeaders) {
    215  - if (item.contains(":")) {
    216  - String[] headerItem = item.split(":\\s", 2);
    217  - if (headerItem[0].equalsIgnoreCase("cookie")) {
    218  - this.sentCookies = headerItem[1];
     227 + for (HttpHeader header : requestHeaders) {
     228 +// if (header.contains(":")) {
     229 + if (header.name().equalsIgnoreCase("cookie")) {
     230 + this.sentCookies = header.value();
    219 231   if (!this.sentCookies.isEmpty()) {
    220 232   this.hasCookieParam = true;
    221 233   this.sentCookies += ";"; // we need to ad this to search it in cookie Jar!
    222 234   
    223 235   // Check to see if it uses cookie Jars!
    224  - List<ICookie> cookieJars = LoggerPlusPlus.callbacks.getCookieJarContents();
     236 + List<Cookie> cookiesInJar = LoggerPlusPlus.montoya.http().cookieJar().cookies();
    225 237   boolean oneNotMatched = false;
    226 238   boolean anyParamMatched = false;
    227 239   
    228  - for (ICookie cookieItem : cookieJars) {
    229  - if (cookieItem.getDomain().equals(this.hostname)) {
     240 + for (Cookie cookieItem : cookiesInJar) {
     241 + if (cookieItem.domain().equals(this.hostname)) {
    230 242   // now we want to see if any of these cookies have been set here!
    231  - String currentCookieJarParam = cookieItem.getName() + "=" + cookieItem.getValue() + ";";
     243 + String currentCookieJarParam = cookieItem.name() + "=" + cookieItem.value() + ";";
    232 244   if (this.sentCookies.contains(currentCookieJarParam)) {
    233 245   anyParamMatched = true;
    234 246   } else {
    skipped 10 lines
    245 257   this.usesCookieJar = CookieJarStatus.YES;
    246 258   }
    247 259   }
    248  - } else if (headerItem[0].equalsIgnoreCase("referer")) {
    249  - this.referrerURL = headerItem[1];
    250  - } else if (headerItem[0].equalsIgnoreCase("content-type")) {
    251  - this.requestContentType = headerItem[1];
    252  - } else if (headerItem[0].equalsIgnoreCase("origin")) {
    253  - this.origin = headerItem[1];
     260 + } else if (header.name().equalsIgnoreCase("referer")) {
     261 + this.referrerURL = header.value();
     262 + } else if (header.name().equalsIgnoreCase("content-type")) {
     263 + this.requestContentType = header.value();
     264 + } else if (header.name().equalsIgnoreCase("origin")) {
     265 + this.origin = header.value();
    254 266   }
    255  - }
     267 +// }
    256 268   }
    257 269   
    258 270   return Status.AWAITING_RESPONSE;
    skipped 44 lines
    303 315   //// this.regexAllReq[i] = allMatches.toString();
    304 316   //
    305 317   // }catch(Exception e){
    306  - // LoggerPlusPlus.callbacks.printError("Error in regular expression: " +
     318 + // LoggerPlusPlus.montoya.printError("Error in regular expression: " +
    307 319   // regexString);
    308 320   // }
    309 321   //
    skipped 7 lines
    317 329   * @param requestResponse
    318 330   * @param arrivalTime
    319 331   */
    320  - public void addResponse(IHttpRequestResponse requestResponse, Date arrivalTime) {
     332 + public void addResponse(HttpResponse requestResponse, Date arrivalTime) {
    321 333   this.responseDateTime = arrivalTime;
    322 334   
    323 335   //IHttpRequestResponse objects received by the proxy listener do not contain the latest request.
    324 336   //So we must store the content separately.
    325  - this.response = requestResponse.getResponse();
    326  - this.setComment(requestResponse.getComment()); //Update the comment with the current comment
     337 + this.response = requestResponse;
     338 +// this.setComment(requestResponse.getComment()); //Update the comment with the current comment
    327 339   }
    328 340   
    329 341   private Status processResponse() {
    330 342   reflectedParameters = new ArrayList<>();
    331  - IResponseInfo tempAnalyzedResp = LoggerPlusPlus.callbacks.getHelpers()
    332  - .analyzeResponse(response);
     343 +// IResponseInfo tempAnalyzedResp = LoggerPlusPlus.montoya.getHelpers()
     344 +// .analyzeResponse(response);
    333 345   
    334  - this.responseStatus = tempAnalyzedResp.getStatusCode();
    335  - this.responseBodyLength = response.length - tempAnalyzedResp.getBodyOffset();
    336  - this.responseMimeType = tempAnalyzedResp.getStatedMimeType();
    337  - this.responseInferredMimeType = tempAnalyzedResp.getInferredMimeType();
     346 + this.responseStatus = response.statusCode();
     347 + this.responseBodyLength = response.body().length();
     348 + this.responseMimeType = response.statedMimeType();
     349 + this.responseInferredMimeType = response.inferredMimeType();
    338 350   
    339 351   /**************************************
    340 352   ************HEADER PROCESSING*********
    341 353   **************************************/
    342 354   
    343  - //Fancy handling to combine duplicate headers into CSVs.
    344  - Map<String, String> headers = tempAnalyzedResp.getHeaders().stream().filter(s -> s.contains(":"))
    345  - .collect(Collectors.toMap(s -> {
    346  - String[] split = s.split(": ", 2);
    347  - return split.length > 0 ? split[0] : "";
    348  - }, s -> {
    349  - String[] split = s.split(": ", 2);
    350  - if (split.length > 1) {
    351  - return split[1];
    352  - }
    353  - return "";
    354  - }, (s, s2) -> {
     355 + Map<String, String> headers = response.headers().stream()
     356 + .collect(Collectors.toMap(HttpHeader::name, HttpHeader::value, (s, s2) -> {
    355 357   s += ", " + s2;
    356 358   return s;
    357 359   }, () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER)));
    358 360   
    359  - responseHeaders = tempAnalyzedResp.getHeaders();
     361 + responseHeaders = response.headers();
    360 362   
    361 363   if (headers.containsKey("Location")) {
    362 364   this.redirectURL = headers.get("Location");
    363 365   }
    364 366   
    365 367   // Extract HTTP Status message
    366  - String[] httpStatusTokens = responseHeaders.get(0).split(" ");
    367  - this.responseStatusText = httpStatusTokens[httpStatusTokens.length - 1];
    368  - this.responseHttpVersion = httpStatusTokens[0];
     368 + HttpHeader httpStatusTokens = response.headers().get(0);
     369 + //TODO FixMe
     370 +// this.responseStatusText = httpStatusTokens[httpStatusTokens.length - 1];
     371 +// this.responseHttpVersion = httpStatusTokens[0];
     372 + 
    369 373   
    370 374   if (headers.containsKey("content-type")) {
    371 375   this.responseContentType = headers.get("content-type");
    372 376   }
    373 377   
    374 378   //Cookies
    375  - for (ICookie cookieItem : tempAnalyzedResp.getCookies()) {
    376  - this.newCookies += cookieItem.getName() + "=" + cookieItem.getValue() + "; "; //TODO convert to map, and add filter support for maps
    377  - }
     379 + this.newCookies = response.cookies().stream().map(cookie -> String.format("%s=%s", cookie.name(), cookie.value())).collect(Collectors.toList());
    378 380   this.hasSetCookies = !newCookies.isEmpty();
    379 381   
    380 382   
    skipped 27 lines
    408 410   **************************************/
    409 411   
    410 412   Long maxRespSize = ((Integer) LoggerPlusPlus.instance.getPreferencesController().getPreferences().getSetting(Globals.PREF_MAX_RESP_SIZE)) * 1000000L;
    411  - int bodyOffset = response.length - responseBodyLength;
     413 + int bodyOffset = response.bodyOffset();
    412 414   if (responseBodyLength < maxRespSize) {
    413 415   //Only title match HTML files. Prevents expensive regex running on e.g. binary downloads.
    414  - if (this.responseInferredMimeType.equalsIgnoreCase("HTML")) {
    415  - String strFullResponse = new String(response);
    416  - Matcher titleMatcher = Globals.HTML_TITLE_PATTERN.matcher(strFullResponse);
     416 + if (this.responseInferredMimeType == MimeType.HTML) {
     417 + Matcher titleMatcher = Globals.HTML_TITLE_PATTERN.matcher(response.bodyAsString());
    417 418   if (titleMatcher.find()) {
    418 419   this.title = titleMatcher.group(1);
    419 420   }
    420 421   }
    421 422   
    422  - String responseBody = new String(response, bodyOffset, responseBodyLength);
    423 423   ReflectionController reflectionController = LoggerPlusPlus.instance.getReflectionController();
    424  - reflectedParameters = tempParameters.parallelStream()
    425  - .filter(iParameter -> !reflectionController.isParameterFiltered(iParameter)
    426  - && reflectionController.validReflection(responseBody, iParameter))
    427  - .map(IParameter::getName).collect(Collectors.toList());
     424 + reflectedParameters = request.parameters().parallelStream()
     425 + .filter(parameter -> !reflectionController.isParameterFiltered(parameter) && reflectionController.validReflection(response.bodyAsString(), parameter))
     426 + .map(HttpParameter::name).collect(Collectors.toList());
    428 427   
    429  -// this.requestResponse = LoggerPlusPlus.callbacks.saveBuffersToTempFiles(requestResponse);
     428 +// this.requestResponse = LoggerPlusPlus.montoya.saveBuffersToTempFiles(requestResponse);
    430 429   } else {
    431 430   //Just look for reflections in the headers.
    432 431   ReflectionController reflectionController = LoggerPlusPlus.instance.getReflectionController();
    433  - reflectedParameters = tempParameters.parallelStream()
    434  - .filter(iParameter -> !reflectionController.isParameterFiltered(iParameter)
    435  - && reflectionController.validReflection(new String(response, 0, bodyOffset), iParameter))
    436  - .map(IParameter::getName).collect(Collectors.toList());
     432 + reflectedParameters = request.parameters().parallelStream()
     433 + .filter(parameter -> !reflectionController.isParameterFiltered(parameter)
     434 + && reflectionController.validReflection(new String(response.asBytes().getBytes(), 0, bodyOffset), parameter))
     435 + .map(HttpParameter::name).collect(Collectors.toList());
    437 436   
    438 437   //Trim the response down to a maximum size, but at least keep the headers!
    439  - this.response = (new String(this.response, 0, bodyOffset) + "Response body trimmed by Logger++. To prevent this, increase \"Maximum Response Size\" in the Logger++ options.").getBytes(StandardCharsets.UTF_8);
     438 + //TODO Fix response trimming?
     439 +// this.response = (new String(this.response, 0, bodyOffset) + "Response body trimmed by Logger++. To prevent this, increase \"Maximum Response Size\" in the Logger++ options.").getBytes(StandardCharsets.UTF_8);
    440 440   }
    441  - 
    442  - 
    443  - tempParameters = null; // We're done with these. Allow them to be cleaned.
    444 441   
    445 442   this.complete = true;
    446 443   
    skipped 40 lines
    487 484   // this.regexAllResp[i] = allMatches.toString();
    488 485   //
    489 486   // }catch(Exception e){
    490  - // LoggerPlusPlus.callbacks.printError("Error in regular expression: " +
     487 + // LoggerPlusPlus.montoya.printError("Error in regular expression: " +
    491 488   // regexString);
    492 489   // }
    493 490   //
    skipped 7 lines
    501 498   // }
    502 499   }
    503 500   
    504  - public byte[] getRequest() {
    505  - return this.requestResponse.getRequest();
     501 + public byte[] getRequestBytes() {
     502 + return this.request.asBytes().getBytes();
    506 503   }
    507 504   
    508  - public byte[] getResponse() {
    509  - return response;
     505 + public byte[] getResponseBytes() {
     506 + return response.asBytes().getBytes();
    510 507   }
    511 508   
    512 509   public void setReqestTime(Date requestTime) {
    skipped 7 lines
    520 517   }
    521 518   
    522 519   public void setComment(String comment) {
    523  - this.requestResponse.setComment(comment);
     520 + this.comment = comment;
    524 521   }
    525 522   
    526 523   public String getComment() {
    527  - return this.requestResponse.getComment();
     524 + return this.comment;
    528 525   }
    529 526   
    530 527   
    skipped 3 lines
    534 531   switch (columnName) {
    535 532   case PROXY_TOOL:
    536 533   case REQUEST_TOOL:
    537  - return getToolName();
     534 + return tool.toolName();
    538 535   case TAGS:
    539 536   return this.matchingTags.stream().map(Tag::getName).collect(Collectors.toList());
    540 537   case URL:
    541  - return this.url;
     538 + return this.urlString;
    542 539   case PATH:
    543  - return this.url.getPath();
     540 + return (this.url != null ? this.url.getPath() : "");
    544 541   case QUERY:
    545  - return this.url.getQuery();
     542 + return (this.url != null ? this.url.getQuery() : "");
    546 543   case STATUS:
    547 544   return this.responseStatus;
    548 545   case STATUS_TEXT:
    skipped 19 lines
    568 565   case RESPONSE_TIME:
    569 566   return this.responseDateTime;
    570 567   case COMMENT:
    571  - return this.requestResponse.getComment();
     568 + return this.comment;
    572 569   case REQUEST_CONTENT_TYPE:
    573 570   return this.requestContentType;
    574 571   case REQUEST_HTTP_VERSION:
    skipped 7 lines
    582 579   case PARAMETER_COUNT:
    583 580   return this.parameters.size();
    584 581   case HASGETPARAM:
    585  - return this.url.getQuery() != null;
     582 + return this.url != null && this.url.getQuery() != null;
    586 583   case HASPOSTPARAM:
    587 584   return this.hasBodyParam;
    588 585   case HASCOOKIEPARAM:
    skipped 52 lines
    641 638   return reflectedParameters.size();
    642 639   case REQUEST_BODY: // request
    643 640   if (requestBodyLength == 0) return "";
    644  - return new String(getRequest(), getRequest().length - requestBodyLength, requestBodyLength);
     641 + return new String(getRequestBytes(), getRequestBytes().length - requestBodyLength, requestBodyLength);
    645 642  // .substring(request.length - requestBodyLength);
    646 643   case RESPONSE_BODY: // response
    647  - if (responseBodyLength == 0) return "";
    648  - return new String(response, response.length - responseBodyLength, responseBodyLength);
    649  -// .substring(response.length - responseBodyLength);
     644 + return response.bodyAsString();
    650 645   case RTT:
    651 646   return requestResponseDelay;
    652 647   case REQUEST_HEADERS:
    653  - return requestHeaders != null ? String.join("\r\n", requestHeaders) : "";
     648 + return requestHeaders != null ? requestHeaders.stream().map(HttpHeader::toString).collect(Collectors.joining("\r\n")) : "";
    654 649   case RESPONSE_HEADERS:
    655  - return responseHeaders != null ? String.join("\r\n", responseHeaders) : "";
     650 + return responseHeaders != null ? responseHeaders.stream().map(HttpHeader::toString).collect(Collectors.joining("\r\n")) : "";
    656 651   case REDIRECT_URL:
    657 652   return redirectURL;
    658 653   case BASE64_REQUEST:
    659  - return Base64.getEncoder().encodeToString(this.getRequest());
     654 + return Base64.getEncoder().encodeToString(this.getRequestBytes());
    660 655   case BASE64_RESPONSE:
    661  - return Base64.getEncoder().encodeToString(response);
     656 + return Base64.getEncoder().encodeToString(this.getResponseBytes());
    662 657   case RESPONSE_HASH: {
    663 658   if (responseHash == null) {
    664 659   responseHash = DigestUtils
    skipped 17 lines
    682 677   return matchingTags;
    683 678   }
    684 679   
    685  - public IHttpService getHttpService() {
    686  - return this.requestResponse.getHttpService();
     680 + public HttpService getHttpService() {
     681 + return this.request.httpService();
    687 682   }
    688 683   
    689 684   public enum CookieJarStatus {
    skipped 73 lines
    763 758   
    764 759   @Override
    765 760   public String toString() {
    766  - return this.url.toString();
     761 + return this.urlString.toString();
    767 762   }
    768 763   
    769  - public static Integer extractAndRemoveIdentifierFromComment(LogEntry logEntry) {
    770  - return LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(logEntry.requestResponse);
    771  - }
     764 +// public static Integer extractAndRemoveIdentifierFromComment(LogEntry logEntry) {
     765 +// return LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(logEntry.request);
     766 +// }
    772 767  }
    773 768   
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntryFieldSerializer.java
    skipped 2 lines
    3 3  import com.google.gson.*;
    4 4   
    5 5  import java.lang.reflect.Type;
    6  -import java.util.Collection;
    7  -import java.util.Date;
    8  -import java.util.HashMap;
    9  -import java.util.LinkedHashMap;
    10 6   
    11 7  public class LogEntryFieldSerializer implements JsonSerializer<LogEntryField>, JsonDeserializer<LogEntryField> {
    12 8   
    skipped 11 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logging/BurpAppender.java
     1 +package com.nccgroup.loggerplusplus.logging;
     2 + 
     3 +import com.nccgroup.loggerplusplus.LoggerPlusPlus;
     4 +import org.apache.logging.log4j.Level;
     5 +import org.apache.logging.log4j.core.Appender;
     6 +import org.apache.logging.log4j.core.Core;
     7 +import org.apache.logging.log4j.core.Filter;
     8 +import org.apache.logging.log4j.core.LogEvent;
     9 +import org.apache.logging.log4j.core.appender.AbstractAppender;
     10 +import org.apache.logging.log4j.core.config.plugins.Plugin;
     11 +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
     12 +import org.apache.logging.log4j.core.config.plugins.PluginElement;
     13 +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
     14 +import org.apache.logging.log4j.core.layout.PatternLayout;
     15 + 
     16 +@Plugin(name="BurpAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
     17 +public class BurpAppender extends AbstractAppender {
     18 + 
     19 + public BurpAppender(String name, Filter filter){
     20 + super(name, filter, PatternLayout.createDefaultLayout(), false, null);
     21 + System.out.println("Created appender");
     22 + }
     23 + 
     24 + @PluginFactory
     25 + public static BurpAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") Filter filter) {
     26 + return new BurpAppender(name, filter);
     27 + }
     28 + 
     29 + @Override
     30 + public void append(LogEvent event) {
     31 + String message = new String(this.getLayout().toByteArray(event));
     32 + if(LoggerPlusPlus.montoya == null) return;
     33 + 
     34 + if (event.getLevel().isInRange(Level.WARN, Level.FATAL)) {
     35 + LoggerPlusPlus.montoya.logging().logToError(message);
     36 + } else {
     37 + LoggerPlusPlus.montoya.logging().logToOutput(message);
     38 + }
     39 + }
     40 +}
     41 + 
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logging/JTextAreaAppender.java
    1  -package com.nccgroup.loggerplusplus.logging;
    2  - 
    3  -import org.apache.logging.log4j.core.*;
    4  -import org.apache.logging.log4j.core.appender.AbstractAppender;
    5  -import org.apache.logging.log4j.core.config.plugins.Plugin;
    6  -import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    7  -import org.apache.logging.log4j.core.config.plugins.PluginElement;
    8  -import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    9  - 
    10  -import javax.swing.*;
    11  -import java.util.ArrayList;
    12  - 
    13  -import static javax.swing.SwingUtilities.invokeLater;
    14  -import static org.apache.logging.log4j.core.config.Property.EMPTY_ARRAY;
    15  -import static org.apache.logging.log4j.core.layout.PatternLayout.createDefaultLayout;
    16  - 
    17  -/**
    18  - * JTextAreaAppender - https://stackoverflow.com/a/29736246
    19  - * Credit to https://stackoverflow.com/users/4544015/vshiro
    20  - */
    21  - 
    22  -@Plugin(name = "JTextAreaAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
    23  -public class JTextAreaAppender extends AbstractAppender {
    24  - private static volatile ArrayList<JTextArea> textAreas = new ArrayList<>();
    25  - 
    26  - private int maxLines;
    27  - 
    28  - private JTextAreaAppender(String name, Layout<?> layout, Filter filter, int maxLines, boolean ignoreExceptions) {
    29  - super(name, filter, layout, ignoreExceptions, EMPTY_ARRAY);
    30  - this.maxLines = maxLines;
    31  - }
    32  - 
    33  - @SuppressWarnings("unused")
    34  - @PluginFactory
    35  - public static JTextAreaAppender createAppender(@PluginAttribute("name") String name,
    36  - @PluginAttribute("maxLines") int maxLines,
    37  - @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
    38  - @PluginElement("Layout") Layout<?> layout,
    39  - @PluginElement("Filters") Filter filter) {
    40  - if (name == null) {
    41  - LOGGER.error("No name provided for JTextAreaAppender");
    42  - return null;
    43  - }
    44  - 
    45  - if (layout == null) {
    46  - layout = createDefaultLayout();
    47  - }
    48  - return new JTextAreaAppender(name, layout, filter, maxLines, ignoreExceptions);
    49  - }
    50  - 
    51  - // Add the target JTextArea to be populated and updated by the logging information.
    52  - public static void addLog4j2TextAreaAppender(final JTextArea textArea) {
    53  - JTextAreaAppender.textAreas.add(textArea);
    54  - }
    55  - 
    56  - @Override
    57  - public void append(LogEvent event) {
    58  - String message = new String(this.getLayout().toByteArray(event));
    59  - 
    60  - // Append formatted message to text area using the Thread.
    61  - try {
    62  - invokeLater(() ->
    63  - {
    64  - for (JTextArea textArea : textAreas) {
    65  - try {
    66  - if (textArea != null) {
    67  - if (textArea.getText().length() == 0) {
    68  - textArea.setText(message);
    69  - } else {
    70  - textArea.append("\n" + message);
    71  - if (maxLines > 0 & textArea.getLineCount() > maxLines + 1) {
    72  - int endIdx = textArea.getDocument().getText(0, textArea.getDocument().getLength()).indexOf("\n");
    73  - textArea.getDocument().remove(0, endIdx + 1);
    74  - }
    75  - }
    76  - String content = textArea.getText();
    77  - textArea.setText(content.substring(0, content.length() - 1));
    78  - }
    79  - } catch (Throwable throwable) {
    80  - throwable.printStackTrace();
    81  - }
    82  - }
    83  - });
    84  - } catch (IllegalStateException exception) {
    85  - exception.printStackTrace();
    86  - }
    87  - }
    88  -}
    89  - 
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logging/LoggingController.java
    1 1  package com.nccgroup.loggerplusplus.logging;
    2 2   
    3  -import burp.IBurpExtenderCallbacks;
     3 +import burp.api.montoya.MontoyaApi;
    4 4  import com.coreyd97.BurpExtenderUtilities.IGsonProvider;
    5  -import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    6 5  import com.nccgroup.loggerplusplus.util.Globals;
     6 +import lombok.extern.log4j.Log4j2;
    7 7  import org.apache.logging.log4j.Level;
    8 8  import org.apache.logging.log4j.LogManager;
    9  -import org.apache.logging.log4j.core.Appender;
    10  -import org.apache.logging.log4j.core.LogEvent;
    11 9  import org.apache.logging.log4j.core.LoggerContext;
    12  -import org.apache.logging.log4j.core.appender.AbstractAppender;
    13  -import org.apache.logging.log4j.core.config.Configuration;
    14  -import org.apache.logging.log4j.core.layout.PatternLayout;
    15 10   
     11 +@Log4j2
    16 12  public class LoggingController {
    17 13   
    18 14   private final IGsonProvider gsonProvider;
    19  - private IBurpExtenderCallbacks callbacks;
    20 15   private Level logLevel;
    21 16   
    22  - public LoggingController(IGsonProvider gsonProvider) {
     17 + public LoggingController(IGsonProvider gsonProvider, MontoyaApi montoyaApi) {
    23 18   this.gsonProvider = gsonProvider;
    24  - this.callbacks = LoggerPlusPlus.callbacks;
    25  - configureLogger();
    26  - }
    27  - 
    28  - private void configureLogger() {
    29  - logLevel = gsonProvider.getGson().fromJson(callbacks.loadExtensionSetting(Globals.PREF_LOG_LEVEL), Level.class);
    30  - 
    31  - if (logLevel == null) { //Handle change from debug boolean to log level.
    32  - logLevel = Level.INFO;
    33  - callbacks.saveExtensionSetting(Globals.PREF_LOG_LEVEL, gsonProvider.getGson().toJson(logLevel));
    34  - }
    35  - 
    36  - LoggerContext context = (LoggerContext) LogManager.getContext(false);
    37  - Configuration config = context.getConfiguration();
    38  - PatternLayout logLayout = PatternLayout.newBuilder()
    39  - .withConfiguration(config)
    40  - .withPattern("[%-5level] %d{yyyy-MM-dd HH:mm:ss} %msg%n")
    41  - .build();
    42  - 
    43  - Appender burpAppender = new AbstractAppender("Burp Appender", null, logLayout, false, null) {
    44  - @Override
    45  - public void append(LogEvent event) {
    46  - String message = new String(this.getLayout().toByteArray(event));
    47  - if (event.getLevel().isMoreSpecificThan(Level.INFO)) {
    48  - callbacks.printError(message);
    49  - } else {
    50  - callbacks.printOutput(message);
    51  - }
    52  - }
    53  - };
    54  - burpAppender.start();
    55  - 
    56  - context.getConfiguration().getRootLogger().addAppender(burpAppender, logLevel, null);
    57  - context.updateLoggers();
     19 + logLevel = gsonProvider.getGson().fromJson(montoyaApi.persistence().preferences().getString(Globals.PREF_LOG_LEVEL), Level.class);
     20 + setLogLevel(logLevel);
    58 21   }
    59 22   
    60 23   public void setLogLevel(Level logLevel) {
    skipped 7 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/LogViewController.java
    skipped 6 lines
    7 7  import com.nccgroup.loggerplusplus.filterlibrary.FilterLibraryController;
    8 8  import com.nccgroup.loggerplusplus.logview.entryviewer.RequestViewerController;
    9 9  import com.nccgroup.loggerplusplus.logview.logtable.LogTableController;
     10 +import lombok.Getter;
    10 11   
    11 12  public class LogViewController {
    12 13   
    13  - private final LoggerPlusPlus loggerPlusPlus;
     14 + @Getter
    14 15   private final FilterLibraryController filterLibraryController;
     16 + 
     17 + @Getter
    15 18   private final Preferences preferences;
     19 + 
     20 + @Getter
    16 21   private final LogFilterController logFilterController;
     22 + 
     23 + @Getter
    17 24   private final LogTableController logTableController;
     25 + 
     26 + @Getter
    18 27   private final RequestViewerController requestViewerController;
    19 28   
     29 + @Getter
    20 30   private final LogViewPanel logViewPanel;
    21 31   
    22  - public LogViewController(LoggerPlusPlus loggerPlusPlus, FilterLibraryController filterLibraryController){
    23  - this.loggerPlusPlus = loggerPlusPlus;
     32 + public LogViewController(FilterLibraryController filterLibraryController){
    24 33   this.filterLibraryController = filterLibraryController;
    25  - this.preferences = loggerPlusPlus.getPreferencesController().getPreferences();
     34 + this.preferences = LoggerPlusPlus.instance.getPreferencesController().getPreferences();
    26 35   
    27 36   this.logTableController = new LogTableController(this, filterLibraryController);
    28 37   this.logFilterController = new LogFilterController(this);
    29  - this.requestViewerController = new RequestViewerController(preferences, false, false);
     38 + this.requestViewerController = new RequestViewerController(preferences);
    30 39   
    31 40   //Build UI
    32 41   this.logViewPanel = new LogViewPanel(this);
    skipped 5 lines
    38 47   
    39 48   public void setEntryViewerLayout(VariableViewPanel.View view){
    40 49   this.logViewPanel.getRequestViewerPanel().getVariableViewPanel().setView(view);
    41  - }
    42  - 
    43  - public LoggerPlusPlus getLoggerPlusPlus() {
    44  - return loggerPlusPlus;
    45  - }
    46  - 
    47  - public LogViewPanel getLogViewPanel() {
    48  - return logViewPanel;
    49  - }
    50  - 
    51  - public LogFilterController getLogFilterController() {
    52  - return logFilterController;
    53  - }
    54  - 
    55  - public LogTableController getLogTableController() {
    56  - return logTableController;
    57  - }
    58  - 
    59  - public RequestViewerController getRequestViewerController() {
    60  - return requestViewerController;
    61  - }
    62  - 
    63  - public Preferences getPreferences() {
    64  - return preferences;
    65 50   }
    66 51  }
    67 52   
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java
    1 1  package com.nccgroup.loggerplusplus.logview;
    2 2   
     3 +import burp.api.montoya.core.BurpSuiteEdition;
     4 +import burp.api.montoya.http.message.HttpRequestResponse;
     5 +import burp.api.montoya.scanner.BuiltInScanConfiguration;
     6 +import burp.api.montoya.scanner.InvalidLauncherConfigurationException;
     7 +import burp.api.montoya.scanner.Scan;
    3 8  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    4 9  import com.nccgroup.loggerplusplus.exports.ContextMenuExportProvider;
    5 10  import com.nccgroup.loggerplusplus.exports.ExportController;
    skipped 1 lines
    7 12  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    8 13  import com.nccgroup.loggerplusplus.logview.logtable.LogTable;
    9 14  import com.nccgroup.loggerplusplus.logview.logtable.LogTableController;
     15 +import lombok.extern.log4j.Log4j2;
    10 16   
    11 17  import javax.swing.*;
    12 18  import java.awt.datatransfer.Clipboard;
    skipped 8 lines
    21 27  /**
    22 28   * Created by corey on 24/08/17.
    23 29   */
     30 +@Log4j2
    24 31  public class MultipleLogEntryMenu extends JPopupMenu {
    25 32   
    26 33   public MultipleLogEntryMenu(final LogTableController logTableController, final List<LogEntry> selectedEntries){
    27 34   final LogTable logTable = logTableController.getLogTable();
    28  - final boolean isPro = LoggerPlusPlus.callbacks.getBurpVersion()[0].equals("Burp Suite Professional");
     35 + final boolean isPro = LoggerPlusPlus.montoya.burpSuite().version().edition() == BurpSuiteEdition.PROFESSIONAL;
    29 36   
    30 37   this.add(new JMenuItem(selectedEntries.size() + " items"));
    31 38   this.add(new Separator());
    skipped 44 lines
    76 83   this.add(copySelectedUrls);
    77 84   
    78 85   JMenu exportMenu = new JMenu("Export entries as...");
    79  - ExportController exportController = logTableController.getLogViewController().getLoggerPlusPlus().getExportController();
     86 + ExportController exportController = LoggerPlusPlus.instance.getExportController();
    80 87   for (LogExporter exporter : exportController.getExporters().values()) {
    81 88   if (exporter instanceof ContextMenuExportProvider) {
    82 89   JMenuItem item = ((ContextMenuExportProvider) exporter).getExportEntriesMenuItem(selectedEntries);
    skipped 8 lines
    91 98   
    92 99   this.add(new Separator());
    93 100   
    94  - JMenuItem spider = new JMenuItem(new AbstractAction("Spider selected " + selectedEntries.size() + " urls") {
     101 + JMenuItem scanner = new JMenuItem(new AbstractAction("Crawl selected " + selectedEntries.size() + " urls") {
    95 102   @Override
    96 103   public void actionPerformed(ActionEvent actionEvent) {
     104 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     105 + 
    97 106   for (LogEntry entry : selectedEntries) {
    98  - LoggerPlusPlus.callbacks.sendToSpider(entry.getUrl());
     107 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     108 + }
     109 + 
     110 + try {
     111 + scan.startCrawl();
     112 + } catch (InvalidLauncherConfigurationException e) {
     113 + log.error(e);
    99 114   }
    100 115   }
    101 116   });
    102  - this.add(spider);
     117 + this.add(scanner);
    103 118   
    104 119   JMenuItem activeScan = new JMenuItem(new AbstractAction("Active scan selected " + selectedEntries.size() + " urls") {
    105 120   @Override
    106 121   public void actionPerformed(ActionEvent actionEvent) {
     122 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     123 + scan.addConfiguration(BuiltInScanConfiguration.ACTIVE_AUDIT_CHECKS);
     124 + 
    107 125   for (LogEntry entry : selectedEntries) {
    108  - LoggerPlusPlus.callbacks.doActiveScan(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest());
     126 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     127 + }
     128 + 
     129 + try {
     130 + scan.startAudit();
     131 + } catch (InvalidLauncherConfigurationException e) {
     132 + log.error(e);
    109 133   }
    110 134   }
    111 135   });
    skipped 3 lines
    115 139   JMenuItem passiveScan = new JMenuItem(new AbstractAction("Passive scan selected " + selectedEntries.size() + " urls") {
    116 140   @Override
    117 141   public void actionPerformed(ActionEvent actionEvent) {
     142 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     143 + scan.addConfiguration(BuiltInScanConfiguration.PASSIVE_AUDIT_CHECKS);
     144 + 
    118 145   for (LogEntry entry : selectedEntries) {
    119  - if (entry.isComplete()) { //Cannot scan entries without response
    120  - LoggerPlusPlus.callbacks.doPassiveScan(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest(), entry.getResponse());
    121  - }
     146 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     147 + }
     148 + 
     149 + try {
     150 + scan.startAudit();
     151 + } catch (InvalidLauncherConfigurationException e) {
     152 + log.error(e);
    122 153   }
    123 154   }
    124 155   });
    skipped 6 lines
    131 162   @Override
    132 163   public void actionPerformed(ActionEvent actionEvent) {
    133 164   for (LogEntry entry : selectedEntries) {
    134  - LoggerPlusPlus.callbacks.sendToRepeater(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest(), "L++");
     165 + LoggerPlusPlus.montoya.repeater().sendToRepeater(entry.getRequest());
    135 166   }
    136 167   }
    137 168   });
    skipped 3 lines
    141 172   @Override
    142 173   public void actionPerformed(ActionEvent actionEvent) {
    143 174   for (LogEntry entry : selectedEntries) {
    144  - LoggerPlusPlus.callbacks.sendToIntruder(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest());
     175 + LoggerPlusPlus.montoya.intruder().sendToIntruder(entry.getRequest());
    145 176   }
    146 177   }
    147 178   });
    skipped 4 lines
    152 183   @Override
    153 184   public void actionPerformed(ActionEvent actionEvent) {
    154 185   for (LogEntry entry : selectedEntries) {
    155  - LoggerPlusPlus.callbacks.sendToComparer(entry.getRequest());
     186 + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().asBytes());
    156 187   }
    157 188   }
    158 189   });
    skipped 3 lines
    162 193   public void actionPerformed(ActionEvent actionEvent) {
    163 194   for (LogEntry entry : selectedEntries) {
    164 195   if (entry.isComplete()) { //Do not add entries without a response
    165  - LoggerPlusPlus.callbacks.sendToComparer(entry.getResponse());
     196 + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().asBytes());
    166 197   }
    167 198   }
    168 199   }
    skipped 24 lines
    193 224   for (LogEntry item : items) {
    194 225   switch (scope) {
    195 226   case URL:
    196  - values.add(String.valueOf(item.getUrl()));
     227 + values.add(String.valueOf(item.getUrlString()));
    197 228   break;
    198 229   case PATH:
    199 230   values.add(item.getUrl().getPath());
    skipped 12 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java
    1 1  package com.nccgroup.loggerplusplus.logview;
    2 2   
     3 +import burp.api.montoya.core.BurpSuiteEdition;
     4 +import burp.api.montoya.http.message.HttpRequestResponse;
     5 +import burp.api.montoya.scanner.BuiltInScanConfiguration;
     6 +import burp.api.montoya.scanner.InvalidLauncherConfigurationException;
     7 +import burp.api.montoya.scanner.Scan;
    3 8  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    4 9  import com.nccgroup.loggerplusplus.exports.ContextMenuExportProvider;
    5 10  import com.nccgroup.loggerplusplus.exports.ExportController;
    skipped 9 lines
    15 20  import com.nccgroup.loggerplusplus.logview.logtable.LogTableController;
    16 21  import com.nccgroup.loggerplusplus.logview.processor.LogProcessor;
    17 22  import com.nccgroup.loggerplusplus.util.userinterface.dialog.ColorFilterDialog;
     23 +import lombok.extern.log4j.Log4j2;
    18 24   
    19 25  import javax.swing.*;
    20 26  import java.awt.event.ActionEvent;
    skipped 5 lines
    26 32  /**
    27 33   * Created by corey on 24/08/17.
    28 34   */
     35 +@Log4j2
    29 36  public class SingleLogEntryMenu extends JPopupMenu {
    30 37   
    31 38   public SingleLogEntryMenu(final LogTableController logTableController, final LogEntry entry, final LogEntryField selectedField){
    skipped 13 lines
    45 52   columnValueString = "\"\"";
    46 53   }
    47 54   
    48  - final boolean isPro = LoggerPlusPlus.callbacks.getBurpVersion()[0].equals("Burp Suite Professional");
     55 + final boolean isPro = LoggerPlusPlus.montoya.burpSuite().version().edition() == BurpSuiteEdition.PROFESSIONAL;
    49 56   String title = entry.getValueByKey(LogEntryField.URL).toString();
    50 57   if(title.length() > 50) title = title.substring(0, 47) + "...";
    51 58   this.add(new JMenuItem(title));
    skipped 46 lines
    98 105   ColorFilter colorFilter = new ColorFilter();
    99 106   colorFilter.setFilter(new LogFilter(LoggerPlusPlus.instance.getLibraryController(),
    100 107   columnName + " == " + columnValueString));
    101  - logTableController.getLogViewController().getLoggerPlusPlus().getLibraryController().addColorFilter(colorFilter);
     108 + LoggerPlusPlus.instance.getLibraryController().addColorFilter(colorFilter);
    102 109   ColorFilterDialog colorFilterDialog = new ColorFilterDialog(LoggerPlusPlus.instance.getLibraryController());
    103 110   colorFilterDialog.setVisible(true);
    104 111   } catch (ParseException e1) {
    skipped 5 lines
    110 117   }
    111 118   
    112 119   this.add(new JPopupMenu.Separator());
    113  - final boolean inScope = LoggerPlusPlus.callbacks.isInScope(entry.getUrl());
     120 + final boolean inScope = LoggerPlusPlus.isUrlInScope(entry.getUrlString());
    114 121   JMenuItem scopeItem;
    115 122   if(!inScope){
    116 123   scopeItem = new JMenu("Add to scope");
    skipped 2 lines
    119 126   public void actionPerformed(ActionEvent actionEvent) {
    120 127   try {
    121 128   URL domainURL = new URL(entry.getProtocol(), entry.getHostname(), entry.getTargetPort(), "");
    122  - LoggerPlusPlus.callbacks.includeInScope(domainURL);
     129 + LoggerPlusPlus.montoya.scope().includeInScope(domainURL.toExternalForm());
    123 130   } catch (MalformedURLException e) {
    124 131   JOptionPane.showMessageDialog(scopeItem, "Could not build URL for scope entry. Sorry!", "Add to scope", JOptionPane.ERROR_MESSAGE);
    125 132   }
    skipped 2 lines
    128 135   scopeItem.add(new JMenuItem(new AbstractAction("Domain + Path") {
    129 136   @Override
    130 137   public void actionPerformed(ActionEvent actionEvent) {
    131  - LoggerPlusPlus.callbacks.includeInScope(entry.getUrl());
     138 + LoggerPlusPlus.montoya.scope().isInScope(entry.getUrlString());
    132 139   }
    133 140   }));
    134 141   }else{
    135 142   scopeItem = new JMenuItem(new AbstractAction("Remove from scope") {
    136 143   @Override
    137 144   public void actionPerformed(ActionEvent actionEvent) {
    138  - LoggerPlusPlus.callbacks.excludeFromScope(entry.getUrl());
     145 + LoggerPlusPlus.montoya.scope().excludeFromScope(entry.getUrlString());
    139 146   }
    140 147   });
    141 148   }
    142 149   this.add(scopeItem);
    143 150   
    144 151   JMenu exportMenu = new JMenu("Export as...");
    145  - ExportController exportController = logTableController.getLogViewController().getLoggerPlusPlus().getExportController();
     152 + ExportController exportController = LoggerPlusPlus.instance.getExportController();
    146 153   for (LogExporter exporter : exportController.getExporters().values()) {
    147 154   if (exporter instanceof ContextMenuExportProvider) {
    148 155   JMenuItem item = ((ContextMenuExportProvider) exporter).getExportEntriesMenuItem(Collections.singletonList(entry));
    skipped 8 lines
    157 164   
    158 165   this.add(new JPopupMenu.Separator());
    159 166   
    160  - JMenuItem spider = new JMenuItem(new AbstractAction("Spider from here") {
     167 + JMenuItem spider = new JMenuItem(new AbstractAction("Crawl from here") {
    161 168   @Override
    162 169   public void actionPerformed(ActionEvent actionEvent) {
    163  - LoggerPlusPlus.callbacks.sendToSpider(entry.getUrl());
     170 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     171 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     172 + 
     173 + try {
     174 + scan.startCrawl();
     175 + } catch (InvalidLauncherConfigurationException e) {
     176 + log.error(e);
     177 + }
    164 178   }
    165 179   });
    166 180   this.add(spider);
    skipped 1 lines
    168 182   JMenuItem activeScan = new JMenuItem(new AbstractAction("Do an active scan") {
    169 183   @Override
    170 184   public void actionPerformed(ActionEvent actionEvent) {
    171  - LoggerPlusPlus.callbacks.doActiveScan(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest());
     185 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     186 + scan.addConfiguration(BuiltInScanConfiguration.ACTIVE_AUDIT_CHECKS);
     187 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     188 + 
     189 + try {
     190 + scan.startAudit();
     191 + } catch (InvalidLauncherConfigurationException e) {
     192 + log.error(e);
     193 + }
    172 194   }
    173 195   });
    174 196   this.add(activeScan);
    skipped 2 lines
    177 199   JMenuItem passiveScan = new JMenuItem(new AbstractAction("Do a passive scan") {
    178 200   @Override
    179 201   public void actionPerformed(ActionEvent actionEvent) {
    180  - LoggerPlusPlus.callbacks.doPassiveScan(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest(), entry.getResponse());
     202 + Scan scan = LoggerPlusPlus.montoya.scanner().createScan();
     203 + scan.addConfiguration(BuiltInScanConfiguration.PASSIVE_AUDIT_CHECKS);
     204 + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse()));
     205 + 
     206 + try {
     207 + scan.startAudit();
     208 + } catch (InvalidLauncherConfigurationException e) {
     209 + log.error(e);
     210 + }
    181 211   }
    182 212   });
    183 213   passiveScan.setEnabled(entry.isComplete() && isPro);
    skipped 4 lines
    188 218   JMenuItem sendToRepeater = new JMenuItem(new AbstractAction("Send to Repeater") {
    189 219   @Override
    190 220   public void actionPerformed(ActionEvent actionEvent) {
    191  - LoggerPlusPlus.callbacks.sendToRepeater(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest(), "L++");
     221 + LoggerPlusPlus.montoya.repeater().sendToRepeater(entry.getRequest());
    192 222   }
    193 223   });
    194 224   this.add(sendToRepeater);
    skipped 1 lines
    196 226   JMenuItem sendToIntruder = new JMenuItem(new AbstractAction("Send to Intruder") {
    197 227   @Override
    198 228   public void actionPerformed(ActionEvent actionEvent) {
    199  - LoggerPlusPlus.callbacks.sendToIntruder(entry.getHostname(), entry.getTargetPort(), entry.isSSL(), entry.getRequest());
     229 + LoggerPlusPlus.montoya.intruder().sendToIntruder(entry.getRequest());
    200 230   }
    201 231   });
    202 232   this.add(sendToIntruder);
    skipped 2 lines
    205 235   JMenuItem comparerRequest = new JMenuItem(new AbstractAction("Request") {
    206 236   @Override
    207 237   public void actionPerformed(ActionEvent actionEvent) {
    208  - LoggerPlusPlus.callbacks.sendToComparer(entry.getRequest());
     238 + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().asBytes());
    209 239   }
    210 240   });
    211 241   sendToComparer.add(comparerRequest);
    212 242   JMenuItem comparerResponse = new JMenuItem(new AbstractAction("Response") {
    213 243   @Override
    214 244   public void actionPerformed(ActionEvent actionEvent) {
    215  - LoggerPlusPlus.callbacks.sendToComparer(entry.getResponse());
     245 + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().asBytes());
    216 246   }
    217 247   });
    218 248   sendToComparer.add(comparerResponse);
    skipped 14 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/entryviewer/RequestViewerController.java
    1 1  package com.nccgroup.loggerplusplus.logview.entryviewer;
    2 2   
    3  -import burp.IHttpService;
    4  -import burp.IMessageEditor;
    5  -import burp.IMessageEditorController;
     3 +import burp.api.montoya.ui.editor.EditorOptions;
     4 +import burp.api.montoya.ui.editor.HttpRequestEditor;
     5 +import burp.api.montoya.ui.editor.HttpResponseEditor;
    6 6  import com.coreyd97.BurpExtenderUtilities.Preferences;
    7 7  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    8 8  import com.nccgroup.loggerplusplus.logentry.LogEntry;
     9 +import lombok.Getter;
    9 10   
    10  -public class RequestViewerController implements IMessageEditorController {
     11 +@Getter
     12 +public class RequestViewerController {
    11 13   
    12 14   private final Preferences preferences;
    13  - private final IMessageEditor requestEditor;
    14  - private final IMessageEditor responseEditor;
     15 + private final HttpRequestEditor requestEditor;
     16 + private final HttpResponseEditor responseEditor;
    15 17   private final RequestViewerPanel requestViewerPanel;
    16 18   
    17 19   private LogEntry currentEntry;
    18 20   
    19  - public RequestViewerController(Preferences preferences, boolean requestEditable, boolean responseEditable) {
     21 + public RequestViewerController(Preferences preferences) {
    20 22   this.preferences = preferences;
    21  - this.requestEditor = LoggerPlusPlus.callbacks.createMessageEditor(this, requestEditable);
    22  - this.responseEditor = LoggerPlusPlus.callbacks.createMessageEditor(this, responseEditable);
     23 + this.requestEditor = LoggerPlusPlus.montoya.userInterface().createHttpRequestEditor(EditorOptions.READ_ONLY);
     24 + this.responseEditor = LoggerPlusPlus.montoya.userInterface().createHttpResponseEditor(EditorOptions.READ_ONLY);
    23 25   this.requestViewerPanel = new RequestViewerPanel(this);
    24 26   }
    25 27   
    26 28   public void setDisplayedEntity(LogEntry logEntry) {
    27 29   this.currentEntry = logEntry;
    28 30   
    29  - if (logEntry == null) {
    30  - requestEditor.setMessage(new byte[0], true);
    31  - responseEditor.setMessage(new byte[0], false);
    32  - return;
    33  - }
    34  - 
    35  - if (logEntry.getRequest() != null) {
    36  - requestEditor.setMessage(logEntry.getRequest(), true);
    37  - } else {
    38  - requestEditor.setMessage(new byte[0], true);
     31 + if (logEntry == null || logEntry.getRequest() == null) {
     32 + requestEditor.setRequest(null);
     33 + }else{
     34 + requestEditor.setRequest(logEntry.getRequest());
    39 35   }
    40 36   
    41  - if (logEntry.getResponse() != null) {
    42  - responseEditor.setMessage(logEntry.getResponse(), false);
    43  - } else {
    44  - responseEditor.setMessage(new byte[0], false);
    45  - }
    46  - }
    47  - 
    48  - public IMessageEditor getRequestEditor() {
    49  - return requestEditor;
    50  - }
    51  - 
    52  - public IMessageEditor getResponseEditor() {
    53  - return responseEditor;
    54  - }
    55  - 
    56  - public Preferences getPreferences() {
    57  - return preferences;
    58  - }
    59  - 
    60  - public RequestViewerPanel getRequestViewerPanel() {
    61  - return requestViewerPanel;
    62  - }
    63  - 
    64  - @Override
    65  - public byte[] getRequest() {
    66  - if (currentEntry != null && currentEntry.getRequest() != null) {
    67  - return currentEntry.getRequest();
    68  - } else {
    69  - return new byte[0];
     37 + if (logEntry == null || logEntry.getResponse() == null) {
     38 + responseEditor.setResponse(null);
     39 + }else{
     40 + responseEditor.setResponse(logEntry.getResponse());
    70 41   }
    71 42   }
    72 43   
    73  - @Override
    74  - public byte[] getResponse() {
    75  - if (currentEntry != null && currentEntry.getResponse() != null) {
    76  - return currentEntry.getResponse();
    77  - } else {
    78  - return new byte[0];
    79  - }
    80  - }
     44 + public void setMarkers(){
    81 45   
    82  - @Override
    83  - public IHttpService getHttpService() {
    84  - if (currentEntry == null) return null;
    85  - return currentEntry.getHttpService();
    86 46   }
    87 47  }
    88 48   
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/entryviewer/RequestViewerPanel.java
    skipped 13 lines
    14 14   this.controller = controller;
    15 15   
    16 16   this.variableViewPanel = new VariableViewPanel(controller.getPreferences(), Globals.PREF_MESSAGE_VIEW_LAYOUT,
    17  - controller.getRequestEditor().getComponent(), "Request",
    18  - controller.getResponseEditor().getComponent(), "Response",
     17 + controller.getRequestEditor().uiComponent(), "Request",
     18 + controller.getResponseEditor().uiComponent(), "Response",
    19 19   VariableViewPanel.View.HORIZONTAL);
    20 20   
    21 21   this.setComponent(variableViewPanel);
    skipped 9 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/logtable/LogTableColumn.java
    skipped 18 lines
    19 19   
    20 20  import com.google.gson.*;
    21 21  import com.nccgroup.loggerplusplus.logentry.LogEntryField;
    22  -import com.nccgroup.loggerplusplus.util.userinterface.renderer.LeftTableCellRenderer;
    23 22   
    24 23  import javax.swing.table.TableColumn;
    25 24  import java.lang.reflect.Type;
    skipped 118 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/logtable/LogTableColumnModel.java
    skipped 12 lines
    13 13  package com.nccgroup.loggerplusplus.logview.logtable;
    14 14   
    15 15  import com.coreyd97.BurpExtenderUtilities.Preferences;
    16  -import com.nccgroup.loggerplusplus.logentry.LogEntryField;
    17 16  import com.nccgroup.loggerplusplus.util.Globals;
    18 17  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    19 18   
    skipped 156 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/logtable/TableHeader.java
    skipped 1 lines
    2 2   
    3 3  import javax.swing.*;
    4 4  import javax.swing.table.JTableHeader;
    5  -import javax.swing.table.TableColumnModel;
    6 5  import java.awt.*;
    7 6  import java.awt.event.MouseAdapter;
    8 7  import java.awt.event.MouseEvent;
    skipped 50 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/processor/EntryImportWorker.java
    1 1  package com.nccgroup.loggerplusplus.logview.processor;
    2 2   
    3  -import burp.IBurpExtenderCallbacks;
    4  -import burp.IHttpRequestResponse;
     3 +import burp.api.montoya.core.ToolType;
     4 +import burp.api.montoya.http.message.HttpRequestResponse;
     5 +import burp.api.montoya.http.message.requests.HttpRequest;
     6 +import burp.api.montoya.http.message.responses.HttpResponse;
     7 +import burp.api.montoya.proxy.ProxyRequestResponse;
    5 8  import com.nccgroup.loggerplusplus.logentry.LogEntry;
    6 9   
    7 10  import javax.swing.*;
    skipped 5 lines
    13 16  public class EntryImportWorker extends SwingWorker<Void, Integer> {
    14 17   
    15 18   private final LogProcessor logProcessor;
    16  - private final int originatingTool;
    17  - private final List<IHttpRequestResponse> entries;
     19 + private final ToolType originatingTool;
     20 + private final List<ProxyRequestResponse> proxyEntries;
     21 + private final List<HttpRequestResponse> httpEntries;
    18 22   private final Consumer<List<Integer>> interimConsumer;
    19 23   private final Runnable callback;
    20 24   private final boolean sendToAutoExporters;
    skipped 1 lines
    22 26   private EntryImportWorker(Builder builder){
    23 27   this.logProcessor = builder.logProcessor;
    24 28   this.originatingTool = builder.originatingTool;
    25  - this.entries = builder.entries;
     29 + this.proxyEntries = builder.proxyEntries;
     30 + this.httpEntries = builder.httpEntries;
    26 31   this.interimConsumer = builder.interimConsumer;
    27 32   this.callback = builder.callback;
    28 33   this.sendToAutoExporters = builder.sendToAutoExporters;
    skipped 2 lines
    31 36   @Override
    32 37   protected Void doInBackground() throws Exception {
    33 38   logProcessor.getEntryProcessExecutor().pause(); //Pause the processor, we don't want it mixing with our import.
     39 + boolean isProxyEntries = proxyEntries.size() > 0;
     40 + int count = isProxyEntries ? proxyEntries.size() : httpEntries.size();
     41 + 
    34 42   
    35  - CountDownLatch countDownLatch = new CountDownLatch(entries.size());
     43 + CountDownLatch countDownLatch = new CountDownLatch(count);
    36 44   ThreadPoolExecutor entryImportExecutor = logProcessor.getEntryImportExecutor();
    37  - for (int index = 0; index < entries.size(); index++) {
     45 + for (int index = 0; index < count; index++) {
    38 46   if(entryImportExecutor.isShutdown() || this.isCancelled()) return null;
    39  - final LogEntry logEntry = new LogEntry(originatingTool, entries.get(index));
     47 + HttpRequest request;
     48 + HttpResponse response;
     49 + if(isProxyEntries){
     50 + request = proxyEntries.get(index).finalRequest();
     51 + response = proxyEntries.get(index).originalResponse();
     52 + }else{
     53 + request = httpEntries.get(index).httpRequest();
     54 + response = httpEntries.get(index).httpResponse();
     55 + }
     56 + final LogEntry logEntry = new LogEntry(originatingTool, request, response);
    40 57   int finalIndex = index;
    41 58   entryImportExecutor.submit(() -> {
    42 59   if(this.isCancelled()) return;
    skipped 25 lines
    68 85   public static class Builder {
    69 86   
    70 87   private final LogProcessor logProcessor;
    71  - private int originatingTool = IBurpExtenderCallbacks.TOOL_EXTENDER;
    72  - private List<IHttpRequestResponse> entries;
     88 + private ToolType originatingTool = ToolType.EXTENSIONS;
     89 + private List<ProxyRequestResponse> proxyEntries;
     90 + private List<HttpRequestResponse> httpEntries;
    73 91   private Consumer<List<Integer>> interimConsumer;
    74 92   private Runnable callback;
    75 93   private boolean sendToAutoExporters = false;
    skipped 2 lines
    78 96   this.logProcessor = logProcessor;
    79 97   }
    80 98   
    81  - public Builder setOriginatingTool(int originatingTool){
     99 + public Builder setOriginatingTool(ToolType originatingTool){
    82 100   this.originatingTool = originatingTool;
    83 101   return this;
    84 102   }
    85 103   
    86  - public Builder setEntries(List<IHttpRequestResponse> entries) {
    87  - this.entries = entries;
     104 + public Builder setProxyEntries(List<ProxyRequestResponse> entries) {
     105 + this.proxyEntries.addAll(entries);
     106 + this.httpEntries.clear();
     107 + return this;
     108 + }
     109 + 
     110 + public Builder setHttpEntries(List<HttpRequestResponse> entries) {
     111 + this.httpEntries.addAll(entries);
     112 + this.proxyEntries.clear();
    88 113   return this;
    89 114   }
    90 115   
    skipped 22 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessor.java
    1 1  package com.nccgroup.loggerplusplus.logview.processor;
    2 2   
    3  -import burp.*;
     3 +import burp.api.montoya.core.Annotations;
     4 +import burp.api.montoya.core.ToolSource;
     5 +import burp.api.montoya.core.ToolType;
     6 +import burp.api.montoya.http.HttpHandler;
     7 +import burp.api.montoya.http.RequestResult;
     8 +import burp.api.montoya.http.ResponseResult;
     9 +import burp.api.montoya.http.message.requests.HttpRequest;
     10 +import burp.api.montoya.http.message.responses.HttpResponse;
     11 +import burp.api.montoya.proxy.*;
    4 12  import com.coreyd97.BurpExtenderUtilities.Preferences;
    5 13  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    6 14  import com.nccgroup.loggerplusplus.exports.ExportController;
    skipped 4 lines
    11 19  import com.nccgroup.loggerplusplus.logview.logtable.LogTableController;
    12 20  import com.nccgroup.loggerplusplus.util.NamedThreadFactory;
    13 21  import com.nccgroup.loggerplusplus.util.PausableThreadPoolExecutor;
     22 +import lombok.Getter;
     23 +import lombok.extern.log4j.Log4j2;
    14 24  import org.apache.logging.log4j.LogManager;
    15 25  import org.apache.logging.log4j.Logger;
    16 26   
    skipped 7 lines
    24 34  /**
    25 35   * Created by corey on 07/09/17.
    26 36   */
    27  -public class LogProcessor implements IHttpListener, IProxyListener {
     37 +@Log4j2
     38 +public class LogProcessor {
    28 39   public static final SimpleDateFormat LOGGER_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    29 40   public static final SimpleDateFormat SERVER_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
    30  - 
    31  - private final LoggerPlusPlus loggerPlusPlus;
    32 41   private final LogTableController logTableController;
    33 42   private final ExportController exportController;
    34 43   private final Preferences preferences;
    skipped 3 lines
    38 47   private final PausableThreadPoolExecutor entryImportExecutor;
    39 48   private final ScheduledExecutorService cleanupExecutor;
    40 49   
     50 + @Getter
     51 + private final HttpHandler httpHandler;
     52 + @Getter
     53 + private final ProxyHttpResponseHandler proxyHttpResponseHandler;
     54 + 
    41 55   Logger logger = LogManager.getLogger(this);
    42 56   
    43 57   /**
    skipped 1 lines
    45 59   * Logic to allow requests independently and match them to responses once received.
    46 60   * TODO SQLite integration
    47 61   */
    48  - public LogProcessor(LoggerPlusPlus loggerPlusPlus, LogTableController logTableController, ExportController exportController) {
    49  - this.loggerPlusPlus = loggerPlusPlus;
     62 + public LogProcessor(LogTableController logTableController, ExportController exportController) {
    50 63   this.logTableController = logTableController;
    51 64   this.exportController = exportController;
    52  - this.preferences = this.loggerPlusPlus.getPreferencesController().getPreferences();
     65 + this.preferences = LoggerPlusPlus.instance.getPreferencesController().getPreferences();
    53 66   
    54 67   this.entriesPendingProcessing = new ConcurrentHashMap<>();
    55 68   this.entryProcessingFutures = new ConcurrentHashMap<>();
    skipped 6 lines
    62 75   this.cleanupExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("LPP-LogManager-Cleanup"));
    63 76   this.cleanupExecutor.scheduleAtFixedRate(new AbandonedRequestCleanupRunnable(),30, 30, TimeUnit.SECONDS);
    64 77   
    65  - LoggerPlusPlus.callbacks.registerHttpListener(this);
    66  - LoggerPlusPlus.callbacks.registerProxyListener(this);
     78 + //TODO Enable new logging API when support for matching requests and their responses improves...
     79 + this.httpHandler = createHttpHandler();
     80 + this.proxyHttpResponseHandler = createProxyResponseHandler();
    67 81   }
    68 82   
    69  - /**
    70  - * Process messages from all tools.
    71  - * Adds to queue for later processing.
    72  - * Note: processProxyMessage runs *after* processHttpMessage, responses from the proxy tool are left for that method.
    73  - *
    74  - * @param toolFlag Tool used to make request
    75  - * @param isRequestOnly If the message is request only or complete with response
    76  - * @param httpMessage The request and potentially response received.
    77  - */
    78  - @Override
    79  - public void processHttpMessage(final int toolFlag, final boolean isRequestOnly, final IHttpRequestResponse httpMessage) {
    80  - if (httpMessage == null || !(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolFlag)) return;
    81  - Date arrivalTime = new Date();
     83 + private HttpHandler createHttpHandler(){
     84 + return new HttpHandler() {
     85 + @Override
     86 + public RequestResult handleHttpRequest(HttpRequest request, Annotations annotations, ToolSource toolSource) {
     87 + if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolSource.toolType())
     88 + || !LoggerPlusPlus.isUrlInScope(request.url())){
     89 + return RequestResult.requestResult(request,annotations);
     90 + }
     91 + Date arrivalTime = new Date();
    82 92   
    83  - if (isRequestOnly) {
    84  - //If we're handling a new request, create a log entry.
    85  - //We must also handle proxy messages here, since the HTTP listener operates after the proxy listener
    86  - final LogEntry logEntry = new LogEntry(toolFlag, arrivalTime, httpMessage);
     93 + //If we're handling a new request, create a log entry.
     94 + //We must also handle proxy messages here, since the HTTP listener operates after the proxy listener
     95 + final LogEntry logEntry = new LogEntry(toolSource.toolType(), request, arrivalTime);
    87 96   
    88  - //Set the entry's identifier to the HTTP request's hashcode.
    89  - // For non-proxy messages, this doesn't change when we receive the response
    90  - logEntry.setIdentifier(System.identityHashCode(httpMessage.getRequest()));
    91  - //Submit a new task to process the entry
    92  - submitNewEntryProcessingRunnable(logEntry);
    93  - } else {
    94  - if (toolFlag == IBurpExtenderCallbacks.TOOL_PROXY) {
    95  - //If the request came from the proxy, the response isn't final yet.
    96  - //Just tag the comment with the identifier so we can match it up later.
    97  - Integer identifier = System.identityHashCode(httpMessage.getRequest());
    98  - LogProcessorHelper.addIdentifierInComment(identifier, httpMessage);
    99  - return; //Process proxy responses using processProxyMessage
    100  - } else {
    101  - //Otherwise, we have the final HTTP response, and can use the request hashcode to match it up with the log entry.
    102  - Integer identifier = System.identityHashCode(httpMessage.getRequest());
    103  - updateRequestWithResponse(identifier, arrivalTime, httpMessage);
     97 + //Set the entry's identifier to the HTTP request's hashcode.
     98 + // For non-proxy messages, this doesn't change when we receive the response
     99 + Integer identifier = System.identityHashCode(request.body());
     100 + logEntry.setIdentifier(identifier);
     101 + annotations = LogProcessorHelper.addIdentifierInComment(identifier, annotations);
     102 + //Submit a new task to process the entry
     103 + submitNewEntryProcessingRunnable(logEntry);
     104 + 
     105 + return RequestResult.requestResult(request, annotations);
    104 106   }
    105  - }
     107 + 
     108 + @Override
     109 + public ResponseResult handleHttpResponse(HttpResponse response, HttpRequest initiatingRequest, Annotations annotations, ToolSource toolSource) {
     110 + if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolSource.toolType())
     111 + || !LoggerPlusPlus.isUrlInScope(initiatingRequest.url())){
     112 + return ResponseResult.responseResult(response,annotations);
     113 + }
     114 + Date arrivalTime = new Date();
     115 + 
     116 + if (toolSource.isFromTool(ToolType.PROXY)) {
     117 + //If the request came from the proxy, the response isn't final yet.
     118 + //Just tag the comment with the identifier so we can match it up later.
     119 +// Integer identifier = System.identityHashCode(initiatingRequest);
     120 +// System.out.println("HTTP Response Proxy - Initiating Request: " + identifier);
     121 +// log.info("New Proxy Response: " + identifier);
     122 +// annotations = LogProcessorHelper.addIdentifierInComment(identifier, annotations);
     123 +// return ResponseResult.responseResult(response, annotations); //Process proxy responses using processProxyMessage
     124 + } else {
     125 + //Otherwise, we have the final HTTP response, and can use the request hashcode to match it up with the log entry.
     126 + Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(annotations);
     127 + Integer identifier = (Integer) identifierAndAnnotation[0]; //TODO Ew.
     128 + annotations = (Annotations) identifierAndAnnotation[1];
     129 + updateRequestWithResponse(identifier, arrivalTime, response);
     130 + }
     131 + return ResponseResult.responseResult(response, annotations);
     132 + }
     133 + };
    106 134   }
    107 135   
    108  - /**
    109  - * Since this method runs after processHttpMessage, we must use it to get the final response for proxy tool requests
    110  - * otherwise, changes to the message by other tools using processProxyMessage would not be seen!
    111  - *
    112  - * @param isRequestOnly
    113  - * @param proxyMessage
    114  - */
    115  - @Override
    116  - public void processProxyMessage(final boolean isRequestOnly, final IInterceptedProxyMessage proxyMessage) {
    117  - final int toolFlag = IBurpExtenderCallbacks.TOOL_PROXY;
    118  - if (proxyMessage == null || !(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolFlag)) return;
    119  - Date arrivalTime = new Date();
     136 + private ProxyHttpResponseHandler createProxyResponseHandler(){
     137 + return new ProxyHttpResponseHandler() {
     138 + @Override
     139 + public ResponseInitialInterceptResult handleReceivedResponse(InterceptedHttpResponse interceptedResponse, HttpRequest initiatingRequest, Annotations annotations) {
     140 + return ResponseInitialInterceptResult.followUserRules(interceptedResponse, annotations); //Do nothing
     141 + }
    120 142   
    121  - if (isRequestOnly) {
     143 + @Override
     144 + public ResponseFinalInterceptResult handleResponseToReturn(InterceptedHttpResponse interceptedResponse, HttpRequest initiatingRequest, Annotations annotations) {
     145 + if(!((boolean) preferences.getSetting(PREF_ENABLED)) || !((boolean) preferences.getSetting(PREF_LOG_PROXY))
     146 + || !LoggerPlusPlus.isUrlInScope(initiatingRequest.url())) {
     147 + return ResponseFinalInterceptResult.continueWith(interceptedResponse, annotations);
     148 + }
     149 + 
     150 + Date arrivalTime = new Date();
     151 + Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(annotations);
     152 + Integer identifier = (Integer) identifierAndAnnotation[0]; //TODO Ew.
     153 + annotations = (Annotations) identifierAndAnnotation[1];
    122 154   
    123  - } else { //We only want to handle responses.
    124  - Integer identifier = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(proxyMessage.getMessageInfo());
    125  - updateRequestWithResponse(identifier, arrivalTime, proxyMessage.getMessageInfo());
    126  - }
     155 + updateRequestWithResponse(identifier, arrivalTime, interceptedResponse);
     156 + return ResponseFinalInterceptResult.continueWith(interceptedResponse, annotations);
     157 + }
     158 + };
    127 159   }
    128 160   
     161 + 
     162 +// /**
     163 +// * Process messages from all tools.
     164 +// * Adds to queue for later processing.
     165 +// * Note: processProxyMessage runs *after* processHttpMessage, responses from the proxy tool are left for that method.
     166 +// *
     167 +// * @param toolFlag Tool used to make request
     168 +// * @param isRequestOnly If the message is request only or complete with response
     169 +// * @param httpMessage The request and potentially response received.
     170 +// */
     171 +// @Override
     172 +// public void processHttpMessage(final int toolFlag, final boolean isRequestOnly, final IHttpRequestResponse httpMessage) {
     173 +// if (httpMessage == null || !(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolFlag)) return;
     174 +// Date arrivalTime = new Date();
     175 +//
     176 +// if (isRequestOnly) {
     177 +// //If we're handling a new request, create a log entry.
     178 +// //We must also handle proxy messages here, since the HTTP listener operates after the proxy listener
     179 +// final LogEntry logEntry = new LogEntry(toolFlag, arrivalTime, httpMessage);
     180 +//
     181 +// //Set the entry's identifier to the HTTP request's hashcode.
     182 +// // For non-proxy messages, this doesn't change when we receive the response
     183 +// logEntry.setIdentifier(System.identityHashCode(httpMessage.getRequest()));
     184 +// //Submit a new task to process the entry
     185 +// submitNewEntryProcessingRunnable(logEntry);
     186 +// } else {
     187 +// if (toolFlag == IBurpExtendermontoya.TOOL_PROXY) {
     188 +// //If the request came from the proxy, the response isn't final yet.
     189 +// //Just tag the comment with the identifier so we can match it up later.
     190 +// Integer identifier = System.identityHashCode(httpMessage.getRequest());
     191 +// LogProcessorHelper.addIdentifierInComment(identifier, httpMessage);
     192 +// return; //Process proxy responses using processProxyMessage
     193 +// } else {
     194 +// //Otherwise, we have the final HTTP response, and can use the request hashcode to match it up with the log entry.
     195 +// Integer identifier = System.identityHashCode(httpMessage.getRequest());
     196 +// updateRequestWithResponse(identifier, arrivalTime, httpMessage);
     197 +// }
     198 +// }
     199 +// }
     200 +//
     201 +// /**
     202 +// * Since this method runs after processHttpMessage, we must use it to get the final response for proxy tool requests
     203 +// * otherwise, changes to the message by other tools using processProxyMessage would not be seen!
     204 +// *
     205 +// * @param isRequestOnly
     206 +// * @param proxyMessage
     207 +// */
     208 +// @Override
     209 +// public void processProxyMessage(final boolean isRequestOnly, final IInterceptedProxyMessage proxyMessage) {
     210 +// final int toolFlag = IBurpExtendermontoya.TOOL_PROXY;
     211 +// if (proxyMessage == null || !(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolFlag)) return;
     212 +// Date arrivalTime = new Date();
     213 +//
     214 +// if (isRequestOnly) {
     215 +//
     216 +// } else { //We only want to handle responses.
     217 +// Integer identifier = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(proxyMessage.getMessageInfo());
     218 +// updateRequestWithResponse(identifier, arrivalTime, proxyMessage.getMessageInfo());
     219 +// }
     220 +// }
     221 + 
    129 222   /**
    130 223   * When a response comes in, determine if the request has already been processed or not.
    131 224   * If it has not yet been processed, add the response information to the entry and let the original job handle it.
    skipped 2 lines
    134 227   *
    135 228   * @param entryIdentifier The unique UUID for the log entry.
    136 229   * @param arrivalTime The arrival time of the response.
    137  - * @param requestResponse The HTTP request response object.
     230 + * @param response The HTTP request response object.
    138 231   */
    139  - private void updateRequestWithResponse(Integer entryIdentifier, Date arrivalTime, IHttpRequestResponse requestResponse) {
     232 + private void updateRequestWithResponse(Integer entryIdentifier, Date arrivalTime, HttpResponse response) {
    140 233   if (entriesPendingProcessing.containsKey(entryIdentifier)) {
    141 234   //Not yet started processing the entry, we can add the response so it is processed in the first pass
    142 235   final LogEntry logEntry = entriesPendingProcessing.get(entryIdentifier);
    143  - //Update the requestResponse with the new one, and tell it when it arrived.
    144  - logEntry.addResponse(requestResponse, arrivalTime);
     236 + //Update the response with the new one, and tell it when it arrived.
     237 + logEntry.addResponse(response, arrivalTime);
    145 238   
    146 239   //Do nothing now, there's already a runnable submitted to process it somewhere in the queue.
    147 240   return;
    skipped 6 lines
    154 247   
    155 248   //Submit a job for the processing of its response.
    156 249   //This will block on the request finishing processing, then update the response and process it separately.
    157  - entryProcessExecutor.submit(createEntryUpdateRunnable(processingFuture, requestResponse, arrivalTime));
     250 + entryProcessExecutor.submit(createEntryUpdateRunnable(processingFuture, response, arrivalTime));
    158 251   } else {
    159 252   //Unknown Identifier. Potentially for a request which was ignored or cleaned up already?
    160 253   }
    skipped 55 lines
    216 309   }
    217 310   
    218 311   private RunnableFuture<LogEntry> createEntryUpdateRunnable(final Future<LogEntry> processingFuture,
    219  - final IHttpRequestResponse requestResponse,
     312 + final HttpResponse requestResponse,
    220 313   final Date arrivalTime){
    221 314   return new FutureTask<>(() -> {
    222 315   //Block until initial processing is complete.
    skipped 24 lines
    247 340   //TODO Remove to more suitable UI class and show dialog
    248 341   
    249 342   //Build list of entries to import
    250  - IHttpRequestResponse[] proxyHistory = LoggerPlusPlus.callbacks.getProxyHistory();
     343 + List<ProxyRequestResponse> proxyHistory = LoggerPlusPlus.montoya.proxy().history();
    251 344   int maxEntries = preferences.getSetting(PREF_MAXIMUM_ENTRIES);
    252  - int startIndex = Math.max(proxyHistory.length - maxEntries, 0);
    253  - List<IHttpRequestResponse> entriesToImport = Arrays.asList(proxyHistory).subList(startIndex, proxyHistory.length);
     345 + int startIndex = Math.max(proxyHistory.size() - maxEntries, 0);
     346 + List<ProxyRequestResponse> entriesToImport = proxyHistory.subList(startIndex, proxyHistory.size());
    254 347   
    255 348   //Build and start import worker
    256 349   EntryImportWorker importWorker = new EntryImportWorker.Builder(this)
    257  - .setOriginatingTool(IBurpExtenderCallbacks.TOOL_PROXY)
    258  - .setEntries(entriesToImport)
     350 + .setOriginatingTool(ToolType.PROXY)
     351 + .setProxyEntries(entriesToImport)
    259 352   .setSendToAutoExporters(sendToAutoExporters).build();
    260 353   
    261 354   importWorker.execute();
    262 355   }
    263 356   
    264  - private boolean isValidTool(int toolFlag){
    265  - return ((Boolean) preferences.getSetting(PREF_LOG_GLOBAL) ||
    266  - ((Boolean) preferences.getSetting(PREF_LOG_PROXY) && toolFlag== IBurpExtenderCallbacks.TOOL_PROXY) ||
    267  - ((Boolean) preferences.getSetting(PREF_LOG_INTRUDER) && toolFlag== IBurpExtenderCallbacks.TOOL_INTRUDER) ||
    268  - ((Boolean) preferences.getSetting(PREF_LOG_REPEATER) && toolFlag== IBurpExtenderCallbacks.TOOL_REPEATER) ||
    269  - ((Boolean) preferences.getSetting(PREF_LOG_SCANNER) && toolFlag== IBurpExtenderCallbacks.TOOL_SCANNER) ||
    270  - ((Boolean) preferences.getSetting(PREF_LOG_SEQUENCER) && toolFlag== IBurpExtenderCallbacks.TOOL_SEQUENCER) ||
    271  - ((Boolean) preferences.getSetting(PREF_LOG_SPIDER) && toolFlag== IBurpExtenderCallbacks.TOOL_SPIDER) ||
    272  - ((Boolean) preferences.getSetting(PREF_LOG_EXTENDER) && toolFlag == IBurpExtenderCallbacks.TOOL_EXTENDER) ||
    273  - ((Boolean) preferences.getSetting(PREF_LOG_TARGET_TAB) && toolFlag == IBurpExtenderCallbacks.TOOL_TARGET));
     357 + private boolean isValidTool(ToolType toolType){
     358 + if(preferences.getSetting(PREF_LOG_GLOBAL)) return true;
     359 + 
     360 + switch (toolType){
     361 + case PROXY -> {return preferences.getSetting(PREF_LOG_PROXY);}
     362 + case INTRUDER -> {return preferences.getSetting(PREF_LOG_INTRUDER);}
     363 + case REPEATER -> {return preferences.getSetting(PREF_LOG_REPEATER);}
     364 + case EXTENSIONS -> {return preferences.getSetting(PREF_LOG_EXTENSIONS);}
     365 + case SCANNER -> {return preferences.getSetting(PREF_LOG_SCANNER);}
     366 + case SEQUENCER -> {return preferences.getSetting(PREF_LOG_SEQUENCER);}
     367 + case SUITE -> {return preferences.getSetting(PREF_LOG_SUITE);}
     368 + case RECORDED_LOGIN_REPLAYER -> {return preferences.getSetting(PREF_LOG_RECORDED_LOGINS);}
     369 + default -> {return false;}
     370 + }
    274 371   }
    275 372   
    276 373   public void shutdown() {
    skipped 55 lines
    332 429   long responseTimeout = 1000 * ((Integer) preferences.getSetting(PREF_RESPONSE_TIMEOUT)).longValue();
    333 430   if (timeNow - entryTime > responseTimeout) {
    334 431   iter.remove();
    335  - if (logEntry.getTool() == IBurpExtenderCallbacks.TOOL_PROXY) {
     432 + if (logEntry.getTool() == ToolType.PROXY) {
    336 433   //Remove the identifier from the comment.
    337  - LogEntry.extractAndRemoveIdentifierFromComment(logEntry);
     434 + //TODO Fix Comment cleanup
     435 +// LogEntry.extractAndRemoveIdentifierFromComment(logEntry);
    338 436   }
    339 437   logEntry.setComment(logEntry.getComment() + " Timed Out");
    340 438   }
    skipped 10 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessorHelper.java
    1 1  package com.nccgroup.loggerplusplus.logview.processor;
    2 2   
    3  -import burp.IHttpRequestResponse;
     3 +import burp.api.montoya.core.Annotations;
    4 4  import com.nccgroup.loggerplusplus.util.Globals;
     5 +import org.apache.commons.lang3.StringUtils;
    5 6   
    6 7  import java.util.regex.Matcher;
    7 8   
    8 9  public class LogProcessorHelper {
    9 10   
    10  - public static void addIdentifierInComment(Integer identifier, IHttpRequestResponse requestResponse) {
    11  - String originalComment = requestResponse.getComment() != null ? requestResponse.getComment() : "";
    12  - requestResponse.setComment(originalComment + "$LPP:" + identifier + "$");
     11 + public static Annotations addIdentifierInComment(Integer identifier, Annotations annotations) {
     12 + String originalComment = annotations.comment() != null ? annotations.comment() : "";
     13 + annotations = annotations.withComment(originalComment + "$LPP:" + identifier + "$");
     14 + return annotations;
    13 15   }
    14 16   
    15  - public static Integer extractAndRemoveIdentifierFromRequestResponseComment(IHttpRequestResponse requestResponse) {
     17 + public static Object[] extractAndRemoveIdentifierFromRequestResponseComment(Annotations annotations) {
    16 18   Integer identifier = null;
    17  - if (requestResponse.getComment() != null) {
    18  - Matcher matcher = Globals.LOG_ENTRY_ID_PATTERN.matcher(requestResponse.getComment());
     19 + if (!StringUtils.isEmpty(annotations.comment())) {
     20 + Matcher matcher = Globals.LOG_ENTRY_ID_PATTERN.matcher(annotations.comment());
    19 21   if (matcher.find()) {
    20 22   identifier = Integer.parseInt(matcher.group(1));
    21  - requestResponse.setComment(matcher.replaceAll(""));
     23 + annotations = annotations.withComment(matcher.replaceAll(""));
    22 24   }
    23 25   }
    24 26   
    25  - return identifier;
     27 + return new Object[]{identifier,annotations};
    26 28   }
    27 29  }
    28 30   
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/preferences/LoggerPreferenceFactory.java
    1 1  package com.nccgroup.loggerplusplus.preferences;
    2 2   
    3  -import burp.IBurpExtenderCallbacks;
     3 +import burp.api.montoya.MontoyaApi;
    4 4  import com.coreyd97.BurpExtenderUtilities.IGsonProvider;
    5 5  import com.coreyd97.BurpExtenderUtilities.ILogProvider;
    6 6  import com.coreyd97.BurpExtenderUtilities.PreferenceFactory;
    skipped 22 lines
    29 29   private ArrayList<LogTableColumn> defaultlogTableColumns;
    30 30   private Set<String> defaultBlacklistedReflections;
    31 31   
    32  - public LoggerPreferenceFactory(IGsonProvider gsonProvider, ILogProvider logProvider, IBurpExtenderCallbacks callbacks){
    33  - super("LoggerPlusPlus", gsonProvider, logProvider, callbacks);
     32 + public LoggerPreferenceFactory(MontoyaApi montoya, IGsonProvider gsonProvider, ILogProvider logProvider){
     33 + super(montoya, "LoggerPlusPlus", gsonProvider, logProvider);
    34 34   }
    35 35   
    36  - public LoggerPreferenceFactory(IGsonProvider gsonProvider, IBurpExtenderCallbacks callbacks){
    37  - super("LoggerPlusPlus", gsonProvider, callbacks);
     36 + public LoggerPreferenceFactory(MontoyaApi montoya, IGsonProvider gsonProvider){
     37 + super(montoya, "LoggerPlusPlus", gsonProvider);
    38 38   }
    39 39   
    40 40   @Override
    skipped 30 lines
    71 71   prefs.registerSetting(PREF_LOG_SCANNER, Boolean.class, true);
    72 72   prefs.registerSetting(PREF_LOG_REPEATER, Boolean.class, true);
    73 73   prefs.registerSetting(PREF_LOG_SEQUENCER, Boolean.class, true);
    74  - prefs.registerSetting(PREF_LOG_EXTENDER, Boolean.class, true);
     74 + prefs.registerSetting(PREF_LOG_EXTENSIONS, Boolean.class, true);
    75 75   prefs.registerSetting(PREF_LOG_TARGET_TAB, Boolean.class, true);
    76 76   prefs.registerSetting(PREF_MAX_RESP_SIZE, Integer.class, 10); //Default 10MB
    77 77   prefs.registerSetting(PREF_COLOR_FILTERS, new TypeToken<Map<UUID, ColorFilter>>() {
    skipped 47 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/preferences/PreferencesController.java
    1 1  package com.nccgroup.loggerplusplus.preferences;
    2 2   
     3 +import burp.api.montoya.MontoyaApi;
    3 4  import com.coreyd97.BurpExtenderUtilities.IGsonProvider;
    4 5  import com.coreyd97.BurpExtenderUtilities.ILogProvider;
    5 6  import com.coreyd97.BurpExtenderUtilities.Preferences;
    6 7  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
     8 +import lombok.Getter;
     9 +import lombok.extern.log4j.Log4j2;
    7 10  import org.apache.logging.log4j.LogManager;
    8 11  import org.apache.logging.log4j.Logger;
    9 12   
     13 +@Log4j2
    10 14  public class PreferencesController {
    11  - private final LoggerPlusPlus loggerPlusPlus;
     15 + 
     16 + @Getter
    12 17   private final IGsonProvider gsonProvider;
     18 + 
     19 + @Getter
    13 20   private final Preferences preferences;
    14 21   
    15 22   private PreferencesPanel preferencesPanel;
    16 23   
    17  - private Logger logger = LogManager.getLogger(this.getClass());
    18  - 
    19  - public PreferencesController(LoggerPlusPlus loggerPlusPlus) {
    20  - this.loggerPlusPlus = loggerPlusPlus;
    21  - this.gsonProvider = loggerPlusPlus.getGsonProvider();
    22  - this.preferences = new LoggerPreferenceFactory(
     24 + public PreferencesController(MontoyaApi montoya) {
     25 + this.gsonProvider = LoggerPlusPlus.gsonProvider;
     26 + this.preferences = new LoggerPreferenceFactory(montoya,
    23 27   gsonProvider,
    24 28   new ILogProvider() {
    25 29   @Override
    26 30   public void logOutput(String message) {
    27  - logger.debug(message);
     31 + log.debug(message);
    28 32   }
    29 33   
    30 34   @Override
    31 35   public void logError(String errorMessage) {
    32  - logger.error(errorMessage);
     36 + log.error(errorMessage);
    33 37   }
    34  - },
    35  - LoggerPlusPlus.callbacks
     38 + }
    36 39   ).buildPreferences();
    37 40   }
    38 41   
    39 42   public PreferencesPanel getPreferencesPanel() {
    40  - if(preferencesPanel == null) {
    41  - preferencesPanel = new PreferencesPanel(this);
     43 + if(this.preferencesPanel == null) {
     44 + this.preferencesPanel = new PreferencesPanel(this);
    42 45   }
     46 + 
    43 47   return preferencesPanel;
    44  - }
    45  - 
    46  - public LoggerPlusPlus getLoggerPlusPlus() {
    47  - return loggerPlusPlus;
    48  - }
    49  - 
    50  - public IGsonProvider getGsonProvider() {
    51  - return gsonProvider;
    52  - }
    53  - 
    54  - public Preferences getPreferences() {
    55  - return preferences;
    56 48   }
    57 49  }
    58 50   
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/preferences/PreferencesPanel.java
    skipped 11 lines
    12 12   
    13 13  package com.nccgroup.loggerplusplus.preferences;
    14 14   
    15  -import burp.IHttpRequestResponse;
     15 +import burp.api.montoya.http.message.HttpRequestResponse;
    16 16  import com.coreyd97.BurpExtenderUtilities.Alignment;
    17 17  import com.coreyd97.BurpExtenderUtilities.ComponentGroup;
    18 18  import com.coreyd97.BurpExtenderUtilities.ComponentGroup.Orientation;
    skipped 58 lines
    77 77   JCheckBox logSequencer = logFromPanel.addPreferenceComponent(preferences, PREF_LOG_SEQUENCER, "Sequencer");
    78 78   JCheckBox logProxy = logFromPanel.addPreferenceComponent(preferences, PREF_LOG_PROXY, "Proxy");
    79 79   JCheckBox logTarget = logFromPanel.addPreferenceComponent(preferences, PREF_LOG_TARGET_TAB, "Target");
    80  - JCheckBox logExtender = logFromPanel.addPreferenceComponent(preferences, PREF_LOG_EXTENDER, "Extender");
     80 + JCheckBox logExtender = logFromPanel.addPreferenceComponent(preferences, PREF_LOG_EXTENSIONS, "Extender");
    81 81   
    82 82   strutConstraints = logFromPanel.generateNextConstraints(true);
    83 83   strutConstraints.weighty = strutConstraints.weightx = 0;
    skipped 31 lines
    115 115   importGroup.add(new JButton(new AbstractAction("Import Burp Proxy History") {
    116 116   @Override
    117 117   public void actionPerformed(ActionEvent e) {
    118  - int historySize = LoggerPlusPlus.callbacks.getProxyHistory().length;
     118 + int historySize = LoggerPlusPlus.montoya.proxy().history().size();
    119 119   int maxEntries = preferences.getSetting(PREF_MAXIMUM_ENTRIES);
    120 120   String message = "Import " + historySize
    121 121   + " items from burp suite proxy history? This will clear the current entries."
    skipped 15 lines
    137 137   sendToAutoExporters = res == JOptionPane.YES_OPTION;
    138 138   }
    139 139   
    140  - preferencesController.getLoggerPlusPlus().getLogProcessor().importProxyHistory(sendToAutoExporters);
     140 + LoggerPlusPlus.instance.getLogProcessor().importProxyHistory(sendToAutoExporters);
    141 141   }
    142 142   }
    143 143   }));
    skipped 1 lines
    145 145   importGroup.add(new JButton(new AbstractAction("Import From WStalker CSV") {
    146 146   @Override
    147 147   public void actionPerformed(ActionEvent e) {
    148  - ArrayList<IHttpRequestResponse> requests = LoggerImport.importWStalker();
     148 + ArrayList<HttpRequestResponse> requests = LoggerImport.importWStalker();
    149 149   if (LoggerPlusPlus.instance.getExportController().getEnabledExporters().size() > 0) {
    150 150   int res = JOptionPane.showConfirmDialog(LoggerPlusPlus.instance.getLoggerFrame(),
    151 151   "One or more auto-exporters are currently enabled. " +
    skipped 9 lines
    161 161   importGroup.add(new JButton(new AbstractAction("Import From OWASP ZAP") {
    162 162   @Override
    163 163   public void actionPerformed(ActionEvent e) {
    164  - ArrayList<IHttpRequestResponse> requests = LoggerImport.importZAP();
     164 + ArrayList<HttpRequestResponse> requests = LoggerImport.importZAP();
    165 165   
    166 166   if (LoggerPlusPlus.instance.getExportController().getEnabledExporters().size() > 0) {
    167 167   int res = JOptionPane.showConfirmDialog(LoggerPlusPlus.instance.getLoggerFrame(),
    skipped 8 lines
    176 176   }));
    177 177   
    178 178   ComponentGroup exportGroup = new ComponentGroup(Orientation.HORIZONTAL);
    179  - HashMap<Class<? extends LogExporter>, LogExporter> exporters = preferencesController.getLoggerPlusPlus()
     179 + HashMap<Class<? extends LogExporter>, LogExporter> exporters = LoggerPlusPlus.instance
    180 180   .getExportController().getExporters();
    181 181   exportGroup.add(((ExportPanelProvider) exporters.get(CSVExporter.class)).getExportPanel());
    182 182   exportGroup.add(((ExportPanelProvider) exporters.get(JSONExporter.class)).getExportPanel());
    skipped 97 lines
    280 280   JOptionPane.YES_NO_OPTION);
    281 281   if (result == JOptionPane.YES_OPTION) {
    282 282   preferences.resetSettings(preferences.getRegisteredSettings().keySet());
    283  - preferencesController.getLoggerPlusPlus().getLogViewController().getLogTableController()
     283 + LoggerPlusPlus.instance.getLogViewController().getLogTableController()
    284 284   .reinitialize();
    285 285   }
    286 286   }
    skipped 2 lines
    289 289   resetPanel.add(new JButton(new AbstractAction("Clear The Logs") {
    290 290   @Override
    291 291   public void actionPerformed(ActionEvent e) {
    292  - preferencesController.getLoggerPlusPlus().getLogViewController().getLogTableController().reset();
     292 + LoggerPlusPlus.instance.getLogViewController().getLogTableController().reset();
    293 293   }
    294 294   }));
    295 295   
    skipped 29 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/ReflectionController.java
    1 1  package com.nccgroup.loggerplusplus.reflection;
    2 2   
    3  -import burp.IParameter;
     3 +import burp.api.montoya.http.message.params.HttpParameter;
    4 4  import com.coreyd97.BurpExtenderUtilities.Alignment;
    5 5  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
    6 6  import com.coreyd97.BurpExtenderUtilities.Preferences;
    skipped 2 lines
    9 9  import com.nccgroup.loggerplusplus.reflection.filter.LengthFilter;
    10 10  import com.nccgroup.loggerplusplus.reflection.filter.ParameterFilter;
    11 11  import com.nccgroup.loggerplusplus.reflection.transformer.*;
    12  -import com.nccgroup.loggerplusplus.util.MoreHelp;
    13 12  import com.nccgroup.loggerplusplus.util.userinterface.renderer.BooleanRenderer;
    14 13  import com.nccgroup.loggerplusplus.util.userinterface.renderer.ButtonRenderer;
    15 14   
    16 15  import javax.swing.*;
    17  -import javax.swing.table.AbstractTableModel;
    18 16  import javax.swing.table.DefaultTableModel;
    19 17  import java.awt.*;
    20  -import java.awt.event.ActionEvent;
    21 18  import java.awt.event.MouseAdapter;
    22 19  import java.awt.event.MouseEvent;
    23  -import java.util.*;
     20 +import java.util.ArrayList;
    24 21  import java.util.List;
    25  -import java.util.regex.Matcher;
    26 22  import java.util.regex.Pattern;
    27 23   
    28 24  public class ReflectionController {
    skipped 18 lines
    47 43   transformerList.add(new XMLUnescapeTransformer(preferences));
    48 44   }
    49 45   
    50  - public List<IParameter> filterParameters(List<IParameter> allParameters){
    51  - List<IParameter> interestingParameters = new ArrayList<>();
    52  - for (IParameter parameter : allParameters) {
     46 + public List<HttpParameter> filterParameters(List<? extends HttpParameter> allParameters){
     47 + List<HttpParameter> interestingParameters = new ArrayList<>();
     48 + for (HttpParameter parameter : allParameters) {
    53 49   if(!isParameterFiltered(parameter)) interestingParameters.add(parameter);
    54 50   }
    55 51   return interestingParameters;
    56 52   }
    57 53  
    58  - public boolean isParameterFiltered(IParameter parameter){
     54 + public boolean isParameterFiltered(HttpParameter parameter){
    59 55   for (ParameterFilter filter : filterList) {
    60 56   if(!filter.isEnabled()) continue;
    61 57   if(filter.isFiltered(parameter)){
    skipped 3 lines
    65 61   return false;
    66 62   }
    67 63  
    68  - public boolean validReflection(String responseBody, IParameter param){
    69  - if(param.getName().isEmpty() || param.getValue().isEmpty()) return false;
     64 + public boolean validReflection(String responseBody, HttpParameter param){
     65 + if(param.name().isEmpty() || param.value().isEmpty()) return false;
    70 66   
    71  - if(responseBody.contains(param.getValue())) return true;
     67 + if(responseBody.contains(param.value())) return true;
    72 68   
    73 69   for (ParameterValueTransformer transformer : transformerList) {
    74 70   try {
    75 71   if (transformer.isEnabled()){
    76  - Pattern pattern = Pattern.compile("\\Q"+transformer.transform(param.getValue())+"\\E", Pattern.CASE_INSENSITIVE);
     72 + Pattern pattern = Pattern.compile("\\Q"+transformer.transform(param.value())+"\\E", Pattern.CASE_INSENSITIVE);
    77 73   if(pattern.matcher(responseBody).find()){
    78 74   return true;
    79 75   }
    skipped 167 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/filter/BlacklistFilter.java
    1 1  package com.nccgroup.loggerplusplus.reflection.filter;
    2 2   
    3  -import burp.IParameter;
    4  -import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
     3 +import burp.api.montoya.http.message.params.HttpParameter;
    5 4  import com.coreyd97.BurpExtenderUtilities.Preferences;
    6 5  import com.google.gson.reflect.TypeToken;
    7 6  import com.nccgroup.loggerplusplus.util.MoreHelp;
    8 7  import org.apache.commons.lang3.StringUtils;
    9 8   
    10  -import javax.swing.*;
    11 9  import java.util.Arrays;
    12 10  import java.util.HashSet;
    13 11  import java.util.Set;
    skipped 14 lines
    28 26   }
    29 27   
    30 28   @Override
    31  - public boolean isFiltered(IParameter parameter) {
    32  - return blacklist.contains(parameter.getValue());
     29 + public boolean isFiltered(HttpParameter parameter) {
     30 + return blacklist.contains(parameter.value());
    33 31   }
    34 32   
    35 33   @Override
    skipped 13 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/filter/LengthFilter.java
    1 1  package com.nccgroup.loggerplusplus.reflection.filter;
    2 2   
    3  -import burp.IParameter;
     3 +import burp.api.montoya.http.message.params.HttpParameter;
    4 4  import com.coreyd97.BurpExtenderUtilities.Alignment;
    5 5  import com.coreyd97.BurpExtenderUtilities.PanelBuilder;
    6 6  import com.coreyd97.BurpExtenderUtilities.Preferences;
    7  -import com.google.gson.reflect.TypeToken;
    8 7  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    9  -import com.nccgroup.loggerplusplus.util.MoreHelp;
    10  -import org.apache.commons.lang3.StringUtils;
    11 8   
    12 9  import javax.swing.*;
    13  -import java.util.Arrays;
    14  -import java.util.HashSet;
    15  -import java.util.Set;
    16  -import java.util.TreeSet;
    17  -import java.util.logging.Logger;
    18 10   
    19 11  public class LengthFilter extends ParameterFilter {
    20 12   
    skipped 12 lines
    33 25   }
    34 26   
    35 27   @Override
    36  - public boolean isFiltered(IParameter parameter) {
    37  - int len = parameter.getValue().length();
     28 + public boolean isFiltered(HttpParameter parameter) {
     29 + int len = parameter.value().length();
    38 30   return len < min_length || len > max_length;
    39 31   
    40 32   }
    skipped 25 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/filter/ParameterFilter.java
    1 1  package com.nccgroup.loggerplusplus.reflection.filter;
    2 2   
    3  -import burp.IParameter;
     3 +import burp.api.montoya.http.message.params.HttpParameter;
    4 4  import com.coreyd97.BurpExtenderUtilities.Preferences;
    5 5   
    6 6  public abstract class ParameterFilter {
    skipped 24 lines
    31 31   return enabled;
    32 32   }
    33 33   
    34  - public abstract boolean isFiltered(IParameter parameter);
     34 + public abstract boolean isFiltered(HttpParameter parameter);
    35 35   public abstract void showConfigDialog();
    36 36   
    37 37  }
    skipped 1 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/transformer/Base64EncodeTransformer.java
    skipped 2 lines
    3 3  import com.coreyd97.BurpExtenderUtilities.Preferences;
    4 4   
    5 5  import java.io.UnsupportedEncodingException;
    6  -import java.net.URLEncoder;
    7 6  import java.util.Base64;
    8 7   
    9 8  public class Base64EncodeTransformer extends ParameterValueTransformer {
    skipped 11 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/transformer/HTMLEscapeTransformer.java
    1 1  package com.nccgroup.loggerplusplus.reflection.transformer;
    2 2   
    3 3  import com.coreyd97.BurpExtenderUtilities.Preferences;
    4  -import org.apache.commons.lang3.StringUtils;
    5 4  import org.apache.commons.text.StringEscapeUtils;
    6  - 
    7  -import java.io.UnsupportedEncodingException;
    8  -import java.net.URLEncoder;
    9 5   
    10 6  public class HTMLEscapeTransformer extends ParameterValueTransformer {
    11 7   
    skipped 10 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/transformer/HexEncodeTransformer.java
    skipped 3 lines
    4 4  import org.apache.commons.codec.binary.Hex;
    5 5   
    6 6  import java.io.UnsupportedEncodingException;
    7  -import java.util.Base64;
    8 7   
    9 8  public class HexEncodeTransformer extends ParameterValueTransformer {
    10 9   
    skipped 10 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/reflection/transformer/URLDecodeTransformer.java
    skipped 3 lines
    4 4   
    5 5  import java.io.UnsupportedEncodingException;
    6 6  import java.net.URLDecoder;
    7  -import java.net.URLEncoder;
    8 7   
    9 8  public class URLDecodeTransformer extends ParameterValueTransformer {
    10 9   
    skipped 10 lines
  • ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/util/Globals.java
    skipped 34 lines
    35 35   public static final String PREF_LOG_SCANNER = "logscanner";
    36 36   public static final String PREF_LOG_REPEATER = "logrepeater";
    37 37   public static final String PREF_LOG_SEQUENCER = "logsequencer";
    38  - public static final String PREF_LOG_EXTENDER = "logextender";
     38 + public static final String PREF_LOG_EXTENSIONS = "logextender";
    39 39   public static final String PREF_LOG_TARGET_TAB = "logtargettab";
     40 + public static final String PREF_LOG_RECORDED_LOGINS = "logrecordedlogins";
     41 + public static final String PREF_LOG_SUITE = "logsuite";
    40 42   public static final String PREF_COLOR_FILTERS = "colorfilters";
    41 43   public static final String PREF_TAG_FILTERS = "tagfilters";
    42 44   public static final String PREF_SAVED_FILTERS = "savedfilters";
    skipped 99 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/util/MoreHelp.java
    skipped 109 lines
    110 110   
    111 111   // public static void checkForUpdate(boolean showMessages) {
    112 112   // new Thread(() -> {
    113  - // IExtensionHelpers helper = LoggerPlusPlus.callbacks.getHelpers();
     113 + // IExtensionHelpers helper = LoggerPlusPlus.montoya.getHelpers();
    114 114   // Double currenVersion = Globals.VERSION;
    115 115   // Double latestVersion = 0.0;
    116 116   // int updateStatus = -1;
    skipped 3 lines
    120 120   // URL changeLogURL = new URL(Globals.CHANGELOG);
    121 121   // byte[] request = helper.buildHttpRequest(changeLogURL);
    122 122   // byte[] response =
    123  - // LoggerPlusPlus.callbacks.makeHttpRequest(changeLogURL.getHost(), 443, true,
     123 + // LoggerPlusPlus.montoya.makeHttpRequest(changeLogURL.getHost(), 443, true,
    124 124   // request);
    125 125   //
    126 126   // if (response != null) {
    skipped 21 lines
    148 148   //
    149 149   // }
    150 150   // } catch (Exception e) {
    151  - // LoggerPlusPlus.callbacks.printError(e.getMessage());
     151 + // LoggerPlusPlus.montoya.printError(e.getMessage());
    152 152   // }
    153 153   //
    154 154   // switch (updateStatus) {
    155 155   // case -1:
    156 156   // updateMessage = "Check for update failed: Could not get a proper response
    157 157   // from " + Globals.CHANGELOG;
    158  - // LoggerPlusPlus.callbacks.printError(updateMessage);
     158 + // LoggerPlusPlus.montoya.printError(updateMessage);
    159 159   // break;
    160 160   // case 0:
    161 161   // updateMessage = "This version is up to date.";
    162  - // LoggerPlusPlus.callbacks.printOutput(updateMessage);
     162 + // LoggerPlusPlus.montoya.printOutput(updateMessage);
    163 163   // break;
    164 164   // case 1:
    165 165   // updateMessage = "Version " + latestVersion.toString() + " is available via
    166 166   // GitHub. Visit the extension homepage.";
    167  - // if (LoggerPlusPlus.callbacks.isExtensionBapp()) {
     167 + // if (LoggerPlusPlus.montoya.isExtensionBapp()) {
    168 168   // updateMessage += "\nAs you are using BApp Store, you have to remove it first
    169 169   // and download the Jar file from the GitHub repository. ";
    170 170   // } else {
    171  - // if (LoggerPlusPlus.callbacks.getExtensionFilename() != null) {
     171 + // if (LoggerPlusPlus.montoya.getExtensionFilename() != null) {
    172 172   // int res = MoreHelp.askConfirmMessage("Update Available", "An update is
    173 173   // available. Would you like to update now?", new String[]{"Yes", "No"});
    174 174   // if (res == JOptionPane.OK_OPTION) {
    skipped 1 lines
    176 176   // //TODO FIXME
    177 177   // URL updateUrl = new URL(Globals.UPDATE_URL);
    178 178   // InputStream input = updateUrl.openStream();
    179  - // Path outputPath = Paths.get(LoggerPlusPlus.callbacks.getExtensionFilename());
     179 + // Path outputPath = Paths.get(LoggerPlusPlus.montoya.getExtensionFilename());
    180 180   // Files.copy(input, outputPath, StandardCopyOption.REPLACE_EXISTING);
    181 181   // } catch (Exception e) {
    182 182   // MoreHelp.showMessage("Could not update the plugin. Please visit the extension
    skipped 2 lines
    185 185   // }
    186 186   // MoreHelp.showMessage("Update complete. Re-enable the plugin in the extensions
    187 187   // tab to continue.");
    188  - // LoggerPlusPlus.callbacks.unloadExtension();
     188 + // LoggerPlusPlus.montoya.unloadExtension();
    189 189   // return;
    190 190   // }
    191 191   // }
    192 192   // }
    193  - // LoggerPlusPlus.callbacks.printOutput(updateMessage);
     193 + // LoggerPlusPlus.montoya.printOutput(updateMessage);
    194 194   // break;
    195 195   // case 2:
    196 196   // updateMessage = "This version is more up to date than the GitHub version! Are
    197 197   // you a time traveler? or just a keen ninja? ;)";
    198  - // LoggerPlusPlus.callbacks.printOutput(updateMessage);
     198 + // LoggerPlusPlus.montoya.printOutput(updateMessage);
    199 199   // break;
    200 200   // }
    201 201   // if (!showMessages) return;
    skipped 61 lines
  • ■ ■ ■ ■ ■ ■
    src/main/resources/log4j2.xml
     1 +<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" packages="com.nccgroup" status="WARN">
     2 + <Appenders>
     3 + <BurpAppender name="BurpAppender" />
     4 + <Console name="Out">
     5 + <PatternLayout pattern="%m%n"/>
     6 + </Console>
     7 + </Appenders>
     8 + <Loggers>
     9 + <Root level="DEBUG">
     10 + <AppenderRef ref="BurpAppender" />
     11 +<!-- <AppenderRef ref="Out" />-->
     12 + </Root>
     13 + </Loggers>
     14 +</Configuration>
  • ■ ■ ■ ■ ■ ■
    src/test/java/Test.java
     1 +public class Test {
     2 + public static void main(String[] args) {
     3 + burp.StartBurp.main(args);
     4 + }
     5 +}
     6 + 
Please wait...
Page is in error, reload to recover