Custom Scan Checks Example Extension The sample extension demonstrates the following techniques:
Registering a custom scan check
Performing passive and active scanning when initiated by the user
Using the Burp-provided AuditInsertionPoint
to construct requests for active scanning using specified payloads
Using a helper method to search responses for relevant match strings
Providing an MarkedHttpRequestResponse
to highlight relevant portions of requests and responses,
Synchronously reporting custom scan issues in response to the relevant checks.
Guiding Burp on when to consolidate duplicated issues at the same URL (e.g., when the user has scanned the same item multiple times).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 import burp.api.montoya.MontoyaApi;import burp.api.montoya.core.Marker;import burp.api.montoya.http.message.HttpRequestResponse;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.scanner.AuditResult;import burp.api.montoya.scanner.ConsolidationAction;import burp.api.montoya.scanner.ScanCheck;import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint;import burp.api.montoya.scanner.audit.issues.AuditIssue;import burp.api.montoya.scanner.audit.issues.AuditIssueConfidence;import burp.api.montoya.scanner.audit.issues.AuditIssueSeverity;import java.util.LinkedList;import java.util.List;import static burp.api.montoya.core.ByteArray.byteArray;import static burp.api.montoya.scanner.AuditResult.auditResult;import static burp.api.montoya.scanner.ConsolidationAction.KEEP_BOTH;import static burp.api.montoya.scanner.ConsolidationAction.KEEP_EXISTING;import static burp.api.montoya.scanner.audit.issues.AuditIssue.auditIssue;import static java.util.Collections.emptyList;import static java.util.Collections.singletonList;class MyScanCheck implements ScanCheck { private static final String GREP_STRING = "Page generated by:" ; private static final String INJ_TEST = "|" ; private static final String INJ_ERROR = "Unexpected pipe" ; private final MontoyaApi api; MyScanCheck(MontoyaApi api) { this .api = api; } @Override public AuditResult activeAudit (HttpRequestResponse baseRequestResponse, AuditInsertionPoint auditInsertionPoint) { HttpRequest checkRequest = auditInsertionPoint.buildHttpRequestWithPayload(byteArray(INJ_TEST)).withService(baseRequestResponse.httpService()); HttpRequestResponse checkRequestResponse = api.http().sendRequest(checkRequest); List<Marker> responseHighlights = getResponseHighlights(checkRequestResponse, INJ_ERROR); List<AuditIssue> auditIssueList = responseHighlights.isEmpty() ? emptyList() : singletonList( auditIssue( "Pipe injection" , "Submitting a pipe character returned the string: " + INJ_ERROR, null , baseRequestResponse.request().url(), AuditIssueSeverity.HIGH, AuditIssueConfidence.CERTAIN, null , null , AuditIssueSeverity.HIGH, checkRequestResponse.withResponseMarkers(responseHighlights) ) ); return auditResult(auditIssueList); } @Override public AuditResult passiveAudit (HttpRequestResponse baseRequestResponse) { List<Marker> responseHighlights = getResponseHighlights(baseRequestResponse, GREP_STRING); List<AuditIssue> auditIssueList = responseHighlights.isEmpty() ? emptyList() : singletonList( auditIssue( "CMS Info Leakage" , "The response contains the string: " + GREP_STRING, null , baseRequestResponse.request().url(), AuditIssueSeverity.HIGH, AuditIssueConfidence.CERTAIN, null , null , AuditIssueSeverity.HIGH, baseRequestResponse.withResponseMarkers(responseHighlights) ) ); return auditResult(auditIssueList); } @Override public ConsolidationAction consolidateIssues (AuditIssue newIssue, AuditIssue existingIssue) { return existingIssue.name().equals(newIssue.name()) ? KEEP_EXISTING : KEEP_BOTH; } private static List<Marker> getResponseHighlights (HttpRequestResponse requestResponse, String match) { List<Marker> highlights = new LinkedList <>(); String response = requestResponse.response().toString(); int start = 0 ; while (start < response.length()) { start = response.indexOf(match, start); if (start == -1 ) { break ; } Marker marker = Marker.marker(start, start+match.length()); highlights.add(marker); start += match.length(); } return highlights; } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class CustomScanChecks implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Custom Scanner checks" ); api.scanner().registerScanCheck(new MyScanCheck (api)); } }
发现原来是Pro版本才有scan功能,重新装了Pro版本
Custom Session Tokens Example Extension This example demonstrates how you can couple a recorded macro with an extension to automatically gain a session token for a website and use it in later requests that Burp makes.
The macro mechanism that Burp provides allows you to record the request triggering creation of a session made via the proxy.
The extension uses the following techniques:
Registers a SessionHandlingAction
handler
Fetches the list of macro requests and responses
Extracts the response headers from the last HttprequestResponse
item in the list
Finds the relevant session header (in this example, this header is X-Custom-Session-Id
)
Returns an HttpRequest
with an updated session header
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 import burp.api.montoya.http.message.HttpHeader;import burp.api.montoya.http.message.HttpRequestResponse;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.http.sessions.ActionResult;import burp.api.montoya.http.sessions.SessionHandlingAction;import burp.api.montoya.http.sessions.SessionHandlingActionData;import java.util.List;import static burp.api.montoya.http.sessions.ActionResult.actionResult;public class MySessionHandlingAction implements SessionHandlingAction { @Override public String name () { return "Use session token from macro" ; } @Override public ActionResult performAction (SessionHandlingActionData actionData) { ActionResult result = actionResult(actionData.request(), actionData.annotations()); List<HttpRequestResponse> macroRequestResponseList = actionData.macroRequestResponses(); if (macroRequestResponseList.isEmpty()) { return result; } List<HttpHeader> headers = macroRequestResponseList.get(macroRequestResponseList.size()-1 ).response().headers(); HttpHeader sessionHeader = findSessionHeader(headers); if (sessionHeader == null ) { return result; } HttpRequest updatedRequest = actionData.request().withUpdatedHeader(sessionHeader); return actionResult(updatedRequest, actionData.annotations()); } private HttpHeader findSessionHeader (List<HttpHeader> headers) { HttpHeader sessionHeader = null ; for (HttpHeader header : headers) { if (!header.name().equals("X-Custom-Session-Id" )) { continue ; } sessionHeader = header; } return sessionHeader; } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class CustomSessionTokens implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Session token example" ); api.http().registerSessionHandlingAction(new MySessionHandlingAction ()); } }
这个插件主要用于以下几种场景中:
自动化会话管理 :
在进行自动化渗透测试或功能测试时,特别是当会话令牌需要频繁更新以保持会话活跃的场合,此插件可以自动地从先前的交互(如登录后的响应)中提取新的会话令牌,并用其更新随后的请求。这确保了测试过程中的会话有效性和连续性。
多步骤过程中的令牌管理 :
在需要执行多个依赖于特定会话状态的步骤的测试中,如购物车添加商品、结账等步骤,此插件能够确保每一步使用正确的会话令牌,从而避免测试因会话过期或令牌失效而失败。
应对防御机制 :
在目标应用实施了严格的会话管理策略(例如会话固定、会话超时、每次请求后更新令牌等)的情况下,此插件通过动态更新会话令牌来帮助绕过这些机制,允许测试者模拟或维持一个持久的会话状态。
宏和自定义脚本中使用 :
当使用 Burp Suite 的宏功能进行复杂的预配置任务时,如自动登录并执行一系列操作,此插件可以被配置为宏的一部分,用于在执行宏时自动处理会话令牌的更新。
维持活跃会话 :
在测试需要长时间运行的脚本或过程时,例如长时间的漏洞扫描或大量数据的传输测试,此插件能够帮助维护会话的活跃状态,避免因会话超时而导致的中断。
Custom Intruder Payloads Example Extension This example shows how you can use an extension to:
Generate custom Intruder payloads
Apply custom processing to Intruder payloads (including built-in ones)
When an extension registers itself as an Intruder payload provider, this will be available within the Intruder UI for the user to select as the payload source for an attack. When an extension registers itself as a payload processor, the user can create a payload processing rule and select the extension’s processor as the rule’s action.
The extension uses the following techniques:
Registers a new PayloadGeneratorProvider
, which returns a new PayloadGenerator
Registers a new PayloadProcessor
The PayloadGenerator
does the following:
Contains a list of payloads to be used
Iterates through the payload list, until there are no longer any payloads available
The PayloadProcessor
does the following:
Decodes the base value of the payload
Parses the location of the input
string in the decoded data
Rebuilds the serialized data with the new payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 package aiassist;import burp.api.montoya.MontoyaApi;import burp.api.montoya.core.ByteArray;import burp.api.montoya.intruder.PayloadData;import burp.api.montoya.intruder.PayloadProcessingResult;import burp.api.montoya.intruder.PayloadProcessor;import burp.api.montoya.utilities.Base64Utils;import burp.api.montoya.utilities.URLUtils;import static burp.api.montoya.intruder.PayloadProcessingResult.usePayload;public class MyPayloadProcessor implements PayloadProcessor { public static final String INPUT_PREFIX = "input=" ; private final MontoyaApi api; public MyPayloadProcessor (MontoyaApi api) { this .api = api; } @Override public String displayName () { return "Serialized input wrapper" ; } @Override public PayloadProcessingResult processPayload (PayloadData payloadData) { Base64Utils base64Utils = api.utilities().base64Utils(); URLUtils urlUtils = api.utilities().urlUtils(); String dataParameter = base64Utils.decode(urlUtils.decode(payloadData.insertionPoint().baseValue())).toString(); String prefix = findPrefix(dataParameter); if (prefix == null ) { return usePayload(payloadData.currentPayload()); } String suffix = findSuffix(dataParameter); String rebuiltDataParameter = prefix + payloadData.currentPayload() + suffix; ByteArray reserializedDataParameter = urlUtils.encode(base64Utils.encode(rebuiltDataParameter)); return usePayload(reserializedDataParameter); } private String findPrefix (String dataParameter) { int start = dataParameter.indexOf(INPUT_PREFIX); if (start == -1 ) { return null ; } start += INPUT_PREFIX.length(); return dataParameter.substring(0 , start); } private String findSuffix (String dataParameter) { int start = dataParameter.indexOf(INPUT_PREFIX); int end = dataParameter.indexOf("&" , start); if (end == -1 ) { end = dataParameter.length(); } return dataParameter.substring(end); } } import burp.api.montoya.intruder.AttackConfiguration;import burp.api.montoya.intruder.PayloadGenerator;import burp.api.montoya.intruder.PayloadGeneratorProvider;public class MyPayloadGeneratorProvider implements PayloadGeneratorProvider { @Override public String displayName () { return "My custom payloads" ; } @Override public PayloadGenerator providePayloadGenerator (AttackConfiguration attackConfiguration) { return new MyPayloadGenerator (); } } import burp.api.montoya.intruder.GeneratedPayload;import burp.api.montoya.intruder.IntruderInsertionPoint;import burp.api.montoya.intruder.PayloadGenerator;import java.util.List;public class MyPayloadGenerator implements PayloadGenerator { private static final List<String> PAYLOADS = List.of("|" , "<script>alert(1)</script>" ); private int payloadIndex; @Override public GeneratedPayload generatePayloadFor (IntruderInsertionPoint insertionPoint) { payloadIndex++; if (payloadIndex > PAYLOADS.size()) { return GeneratedPayload.end(); } String payload = PAYLOADS.get(payloadIndex); return GeneratedPayload.payload(payload); } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class IntruderPayloads implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Intruder payloads" ); api.intruder().registerPayloadGeneratorProvider(new MyPayloadGeneratorProvider ()); api.intruder().registerPayloadProcessor(new MyPayloadProcessor (api)); } }
Persistence Example Extension The extension works as follows:
It saves and loads a simple incrementing integer value with the project file.
Sends to the event log how many times Burp or the extension were restarted.
It saves and loads extension built http requests
Sends the requests to repeater with an incrementing tab counter when Burp is restarted or the extension is reloaded.
It saves the last 5 requests/responses issued by Burp
Prints the last 5 request/responses to the output log when burp is restarted or the extension is reloaded.
Uses Persisted Lists to automatically save/load data stored in the list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 import burp.api.montoya.MontoyaApi;import burp.api.montoya.http.message.requests.HttpRequest;import burp.api.montoya.persistence.PersistedObject;import static burp.api.montoya.http.message.requests.HttpRequest.httpRequest;import static burp.api.montoya.http.message.requests.HttpRequest.httpRequestFromUrl;import static example.persistence.PersistenceExample.STARTUP_COUNT_KEY;public class SavingLoadingRequests { public static final String SIMPLE_REQUEST_KEY = "simpleRequest" ; public static final String REQUEST_WITH_HEADERS_KEY = "requestWithHeaders" ; public static final String REQUEST_FROM_URL_KEY = "requestFromUrl" ; private final MontoyaApi api; private final PersistedObject myExtensionData; public SavingLoadingRequests (MontoyaApi api) { this .api = api; this .myExtensionData = api.persistence().extensionData(); } public void runExample () { if (!checkForRequests()) { api.logging().raiseInfoEvent("No Requests saved, creating requests" ); createAndSaveExampleRequests(); } sendExampleRequestsToRepeaterWithStartupCount(); } private boolean checkForRequests () { return myExtensionData.httpRequestKeys().contains(SIMPLE_REQUEST_KEY) && myExtensionData.httpRequestKeys().contains(REQUEST_WITH_HEADERS_KEY) && myExtensionData.httpRequestKeys().contains(REQUEST_FROM_URL_KEY); } private void createAndSaveExampleRequests () { HttpRequest simpleRequest = httpRequest("GET / HTTP1.0\r\n\r\n" ); HttpRequest requestWithHeaders = httpRequest("GET / HTTP1.1\r\nHost: localhost\r\nMyHeader: Example\r\n\r\n" ); HttpRequest requestFromUrl = httpRequestFromUrl("http://localhost" ); myExtensionData.setHttpRequest(SIMPLE_REQUEST_KEY, simpleRequest); myExtensionData.setHttpRequest(REQUEST_WITH_HEADERS_KEY, requestWithHeaders); myExtensionData.setHttpRequest(REQUEST_FROM_URL_KEY, requestFromUrl); } private void sendExampleRequestsToRepeaterWithStartupCount () { HttpRequest simpleRequest = myExtensionData.getHttpRequest(SIMPLE_REQUEST_KEY); HttpRequest requestWithHeaders = myExtensionData.getHttpRequest(REQUEST_WITH_HEADERS_KEY); HttpRequest requestFromUrl = myExtensionData.getHttpRequest(REQUEST_FROM_URL_KEY); Integer startupCount = myExtensionData.getInteger(STARTUP_COUNT_KEY); api.repeater().sendToRepeater(simpleRequest, "Simple Request " + startupCount); api.repeater().sendToRepeater(requestWithHeaders, "Request With Headers " + startupCount); api.repeater().sendToRepeater(requestFromUrl, "Request From Url " + startupCount); } } import burp.api.montoya.MontoyaApi;import burp.api.montoya.http.handler.*;import burp.api.montoya.http.message.HttpRequestResponse;import burp.api.montoya.persistence.PersistedList;import burp.api.montoya.persistence.PersistedObject;import static burp.api.montoya.http.handler.RequestToBeSentAction.continueWith;import static burp.api.montoya.http.handler.ResponseReceivedAction.continueWith;import static burp.api.montoya.http.message.HttpRequestResponse.httpRequestResponse;public class RequestResponseLogging { private static final String REQUEST_RESPONSE_LIST_KEY = "last5" ; private final MontoyaApi api; private final PersistedObject myExtensionData; public RequestResponseLogging (MontoyaApi api) { this .api = api; this .myExtensionData = api.persistence().extensionData(); } public void runExample () { ensurePersistedListIsPresent(); PersistedList<HttpRequestResponse> myPersistedList = myExtensionData.getHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY); printToOutput(myPersistedList); api.http().registerHttpHandler(new HttpHandler () { @Override public RequestToBeSentAction handleHttpRequestToBeSent (HttpRequestToBeSent requestToBeSent) { return continueWith(requestToBeSent); } @Override public synchronized ResponseReceivedAction handleHttpResponseReceived (HttpResponseReceived responseReceived) { if (myPersistedList.size() >= 5 ) { myPersistedList.remove(0 ); } myPersistedList.add(httpRequestResponse(responseReceived.initiatingRequest().withBody("" ), responseReceived.withBody("" ))); return continueWith(responseReceived); } }); } private void printToOutput (PersistedList<HttpRequestResponse> myPersistedList) { for (HttpRequestResponse httpRequestResponse : myPersistedList) { api.logging().logToOutput(httpRequestResponse.request().toString()); api.logging().logToOutput("\n========================\n" ); api.logging().logToOutput(httpRequestResponse.response().toString()); api.logging().logToOutput("\n**************************" .repeat(2 )); } } private void ensurePersistedListIsPresent () { if (myExtensionData.getHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY) == null ) { PersistedList<HttpRequestResponse> emptyPersistedList = PersistedList.persistedHttpRequestResponseList(); myExtensionData.setHttpRequestResponseList(REQUEST_RESPONSE_LIST_KEY, emptyPersistedList); } } } public class PersistenceExample implements BurpExtension { static final String STARTUP_COUNT_KEY = "Startup Count" ; @Override public void initialize (MontoyaApi api) { api.extension().setName("Persistence example extension" ); PersistedObject myExtensionData = api.persistence().extensionData(); Integer startupCount = myExtensionData.getInteger(STARTUP_COUNT_KEY); if (startupCount == null ) { startupCount = 0 ; } myExtensionData.setInteger(STARTUP_COUNT_KEY, startupCount + 1 ); api.logging().raiseInfoEvent("Startup count is: " + myExtensionData.getInteger(STARTUP_COUNT_KEY)); advancedExamples(api); } private static void advancedExamples (MontoyaApi api) { SavingLoadingRequests savingLoadingRequests = new SavingLoadingRequests (api); savingLoadingRequests.runExample(); RequestResponseLogging requestLogging = new RequestResponseLogging (api); requestLogging.runExample(); } }
WebSocket Handler Example Extension The extension works as follows:
It registers a web socket created handler
When a web socket is created
It sends an initial text message
It registers a message listener for the websocket
Any message from the client that contains the text “password” is base64 encoded.
这个先不看了
This extension demonstrates registering a top level menu bar item with various actions.
It demonstrates the following techniques:
Creating a BasicMenuItem with a caption Providing an action for a BasicMenuItem Adding the Menu to Burp Registering an ExtensionUnloadingHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import burp.api.montoya.MontoyaApi;import burp.api.montoya.extension.ExtensionUnloadingHandler;public class MyExtensionUnloadingHandler implements ExtensionUnloadingHandler { private final MontoyaApi api; public MyExtensionUnloadingHandler (MontoyaApi api) { this .api = api; } @Override public void extensionUnloaded () { api.logging().logToOutput("Extension has been unloaded." ); } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;import burp.api.montoya.ui.menu.BasicMenuItem;import burp.api.montoya.ui.menu.Menu;import burp.api.montoya.ui.menu.MenuItem;public class MenuBar implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Add menu bar" ); api.logging().logToOutput("Extension has been loaded." ); BasicMenuItem alertEventItem = BasicMenuItem.basicMenuItem("Raise critical alert" ).withAction(() -> api.logging().raiseCriticalEvent("Alert from extension" )); BasicMenuItem basicMenuItem = MenuItem.basicMenuItem("Unload extension" ); MenuItem unloadExtensionItem = basicMenuItem.withAction(() -> api.extension().unload()); Menu menu = Menu.menu("Menu bar" ).withMenuItems(alertEventItem, unloadExtensionItem); api.userInterface().menuBar().registerMenu(menu); api.extension().registerUnloadingHandler(new MyExtensionUnloadingHandler (api)); } }
This extension adds a new context menu item to print out the request or response of an HttpRequestResponse in the Target, Proxy or Logger tab.
The sample extension demonstrates the following techniques:
Registering a new ContextMenuItemsProvider. Creating a JMenuItem. Adding an action listener to a JMenuItem. If you right-click in a message editor context, it will use the item from the message editor. If you right-click on a table item, it will print the request/response for the first selected item.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import javax.swing.*;import java.awt.*;import java.util.ArrayList;import java.util.List;public class MyContextMenuItemsProvider implements ContextMenuItemsProvider { private final MontoyaApi api; public MyContextMenuItemsProvider (MontoyaApi api) { this .api = api; } @Override public List<Component> provideMenuItems (ContextMenuEvent event) { if (event.isFromTool(ToolType.PROXY, ToolType.TARGET, ToolType.LOGGER)) { List<Component> menuItemList = new ArrayList <>(); JMenuItem retrieveRequestItem = new JMenuItem ("Print request" ); JMenuItem retrieveResponseItem = new JMenuItem ("Print response" ); HttpRequestResponse requestResponse = event.messageEditorRequestResponse().isPresent() ? event.messageEditorRequestResponse().get().requestResponse() : event.selectedRequestResponses().get(0 ); retrieveRequestItem.addActionListener(l -> api.logging().logToOutput("Request is:\r\n" + requestResponse.request().toString())); menuItemList.add(retrieveRequestItem); if (requestResponse.response() != null ) { retrieveResponseItem.addActionListener(l -> api.logging().logToOutput("Response is:\r\n" + requestResponse.response().toString())); menuItemList.add(retrieveResponseItem); } return menuItemList; } return null ; } } import burp.api.montoya.BurpExtension;import burp.api.montoya.MontoyaApi;public class ContextMenu implements BurpExtension { @Override public void initialize (MontoyaApi api) { api.extension().setName("Context menu extension" ); api.userInterface().registerContextMenuItemsProvider(new MyContextMenuItemsProvider (api)); } }
上面代码是创建右键处理选项的