diff --git a/src/base/FindUrl_Action.java b/src/base/FindUrl_Action.java new file mode 100644 index 0000000..df7547a --- /dev/null +++ b/src/base/FindUrl_Action.java @@ -0,0 +1,334 @@ +package base; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.swing.JOptionPane; + +import org.apache.commons.lang3.StringUtils; + +import com.bit4woo.utilbox.burp.HelperPlus; +import com.bit4woo.utilbox.utils.SwingUtils; +import com.bit4woo.utilbox.utils.TextUtils; +import com.bit4woo.utilbox.utils.UrlUtils; + +import burp.BurpExtender; +import burp.IBurpExtenderCallbacks; +import burp.IContextMenuInvocation; +import burp.IExtensionHelpers; +import burp.IHttpRequestResponse; +import burp.threadRequester; + +public class FindUrl_Action implements ActionListener { + private IContextMenuInvocation invocation; + public IExtensionHelpers helpers; + public PrintWriter stdout; + public PrintWriter stderr; + public IBurpExtenderCallbacks callbacks; + public BurpExtender burp; + + public static final String[] blackHostList = {"www.w3.org", "ns.adobe.com", "iptc.org", "openoffice.org" + , "schemas.microsoft.com", "schemas.openxmlformats.org", "sheetjs.openxmlformats.org","registry.npmjs.org" + ,"json-schema.org","jmespath.org"}; + + public static final List blackPath = TextUtils.textToLines("text/css\r\n" + + " text/html\r\n" + + " text/plain\r\n" + + " image/pdf\r\n"); + + + private static Proxy proxy; + public static Map BaseUrlMap = new HashMap<>(); + + public FindUrl_Action(BurpExtender burp, IContextMenuInvocation invocation) { + this.burp = burp; + this.invocation = invocation; + this.helpers = burp.helpers; + this.callbacks = BurpExtender.callbacks; + this.stderr = BurpExtender.stderr; + this.stdout = BurpExtender.stdout; + } + + public FindUrl_Action() { + this.helpers = BurpExtender.helpers; + + } + + + public void doSendRequest(String baseurl,List urlPath,String refererToUse) { + try { + BlockingQueue inputQueue = new LinkedBlockingQueue<>(); + + try { + for (String url : urlPath) { + if (!url.startsWith("http://") && !url.startsWith("https://")) { + if (url.startsWith("/")) { + url = url.replaceFirst("/", ""); + } + if (url.startsWith("./")) { + url = url.replaceFirst("\\./", ""); + } + url = baseurl + url; //baseurl统一以“/”结尾;url统一删除“/”的开头 + inputQueue.put(new RequestTask(url, RequestType.GET)); + inputQueue.put(new RequestTask(url, RequestType.POST)); + inputQueue.put(new RequestTask(url, RequestType.JSON)); + } + } + } catch (Exception e) { + e.printStackTrace(BurpExtender.getStderr()); + } + + doRequest(inputQueue, refererToUse); + } catch (Exception e1) { + e1.printStackTrace(stderr); + } + } + + @Override + public void actionPerformed(ActionEvent event) { + Runnable requestRunner = new Runnable() { + @Override + public void run() { + IHttpRequestResponse[] messages = invocation.getSelectedMessages(); + if (messages == null || messages.length <= 0) { + return; + } + String targetBaseUrl = getTargetSiteBaseUrl(messages[0]); + + List urls = FindAllUrls(messages[0]); + + Set baseUrls = findPossibleBaseURL(urls); + + if (baseUrls.size() <= 0) { + return; + } + + String baseurl = choseAndEditBaseURL(baseUrls); + + if (null == baseurl) { + return; + } + + urls = choseURLPath(urls); + if (urls.size()<=0) return; + + doSendRequest(baseurl,urls,targetBaseUrl); + } + }; + new Thread(requestRunner).start(); + } + + /** + * 根据当前web的baseUrl找JS,特征就是referer以它开头 + * @param message + * @return + */ + public static List FindAllUrls(IHttpRequestResponse message) { + String targetBaseUrl = getTargetSiteBaseUrl(message); + + List urls = findUrls(message.getResponse()); + + HelperPlus getter = BurpExtender.getHelperPlus(); + IHttpRequestResponse[] messages = BurpExtender.getCallbacks().getSiteMap(null); + for (IHttpRequestResponse item : messages) { + URL url = getter.getFullURL(item); + if (url == null || (!url.toString().toLowerCase().endsWith(".js") && !url.toString().toLowerCase().endsWith(".js.map"))) { + continue; + } + + int code = getter.getStatusCode(item); + String referUrl = getter.getHeaderValueOf(true, item, "Referer"); + if (referUrl == null || code <= 0) { + continue; + } + + if (referUrl.toLowerCase().startsWith(targetBaseUrl.toLowerCase())) { + urls.addAll(findUrls(item.getResponse())); + } + } + return urls; + } + + /** + * @param message + * @return + */ + public static String getTargetSiteBaseUrl(IHttpRequestResponse message) { + HelperPlus getter = BurpExtender.getHelperPlus(); + + String current_referUrl = getter.getHeaderValueOf(true, message, "Referer"); + String current_fullUrl = getter.getFullURL(message).toString(); + + if (current_referUrl != null) { + //认为当前数据包是前端触发的 + return UrlUtils.getBaseUrl(current_referUrl); + } else { + //认为其是当前数据包是浏览器地址栏访问直接触发的 + return UrlUtils.getBaseUrl(current_fullUrl); + } + } + + public static List findUrls(byte[] content) { + List urls = new ArrayList<>(); + + if (content == null) { + return urls; + }else { + return findUrls(new String(content)); + } + } + + /** + * 在数据包中查找URL + * @param body + * @return + */ + public static List findUrls(String content) { + List urls = new ArrayList<>(); + if (StringUtils.isEmpty(content)) { + return urls; + } + + content = TextUtils.decodeAll(content); + urls.addAll(UrlUtils.grepUrlsWithProtocol(content)); + urls.addAll(UrlUtils.grepUrlPathNotStartWithSlashInQuotes(content)); + urls.addAll(UrlUtils.grepUrlsInQuotes(content)); + urls = cleanUrls(urls); + + return urls; + } + + /** + * 多线程执行请求 + * + * @param inputQueue + */ + public void doRequest(BlockingQueue inputQueue, String referUrl) { + if (proxy == null) { + proxy = Proxy.inputProxy(); + } + if (proxy == null) { + return; + } + + int max = threadNumberShouldUse(inputQueue.size()); + + for (int i = 0; i <= max; i++) { + threadRequester requester = new threadRequester(inputQueue, proxy.getHost(), proxy.getPort(), referUrl, i); + requester.start(); + } + } + + /** + * 根据已有的域名梳理,预估应该使用的线程数 + * 假设1个任务需要1秒钟。线程数在1-100之间,如何选择线程数使用最小的时间? + * + * @param domainNum + * @return + */ + public static int threadNumberShouldUse(int domainNum) { + + int tmp = (int) Math.sqrt(domainNum); + if (tmp <= 1) { + return 1; + } else if (tmp >= 10) { + return 10; + } else { + return tmp; + } + } + + public static Set findPossibleBaseURL(List urls) { + Set baseURLs = new HashSet<>(); + for (String tmpurl : urls) { + //这部分提取的是含有协议头的完整URL地址 + if (tmpurl.toLowerCase().startsWith("http://") + || tmpurl.toLowerCase().startsWith("https://")) { + + baseURLs.add(tmpurl); + } + } + return baseURLs; + } + + + + public static String choseAndEditBaseURL(Set inputs) { + + ArrayList tmpList = new ArrayList(inputs); + Collections.sort(tmpList); + int n = inputs.size() + 1; + String[] possibleValues = new String[n]; + + // Copying contents of domains to arr[] + System.arraycopy(tmpList.toArray(), 0, possibleValues, 0, n - 1); + possibleValues[n - 1] = "Let Me Input"; + + String selectedValue = (String) JOptionPane.showInputDialog(null, + "Chose Base URL", "Chose And Edit Base URL", + JOptionPane.INFORMATION_MESSAGE, null, + possibleValues, possibleValues[0]); + if (null != selectedValue) { + String baseUrl = JOptionPane.showInputDialog("Confirm The Base URL", selectedValue); + if (baseUrl == null) { + return null; + } + if (!baseUrl.endsWith("/")) { + baseUrl = baseUrl.trim() + "/"; + } + return baseUrl.trim(); + } + return selectedValue; + } + + + public static List choseURLPath(List urls) { + + Collections.sort(urls); + + String text = SwingUtils.showTextAreaDialog(String.join(System.lineSeparator(), urls)); + if (StringUtils.isEmpty(text)) { + return new ArrayList(); + }else { + return TextUtils.textToLines(text); + } + } + + + public static List cleanUrls(List urls) { + + urls = TextUtils.deduplicate(urls); + Iterator it = urls.iterator(); + while (it.hasNext()) { + String urlItem = it.next(); + if (UrlUtils.uselessExtension(urlItem)) { + it.remove(); + } + if (blackPath.contains(urlItem)) { + it.remove(); + } + try { + String host = new URL(urlItem).getHost(); + if (Arrays.asList(blackHostList).contains(host)) { + it.remove(); + } + } catch (Exception E) { + continue; + } + } + return urls; + } +} diff --git a/src/base/Proxy.java b/src/base/Proxy.java new file mode 100644 index 0000000..32ac704 --- /dev/null +++ b/src/base/Proxy.java @@ -0,0 +1,84 @@ +package base; + +import javax.swing.JOptionPane; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.validator.routines.DomainValidator; +import org.apache.commons.validator.routines.InetAddressValidator; + +import burp.BurpExtender; + +public class Proxy { + + String host; + int port; + + public Proxy(String proxyStr) throws IllegalArgumentException { + if (StringUtils.isEmpty(proxyStr)) { + throw new IllegalArgumentException("input is empty"); + } + try { + String[] parts = proxyStr.split(":"); + if (parts.length != 2) { + throw new IllegalArgumentException("not valid host:port format"); + } + host = parts[0]; + if (!isValidIPAddress(host) && !isValidDomainName(host)) { + throw new IllegalArgumentException("host is not valid IP address and domain name"); + } + String portStr = parts[1]; + port = Integer.parseInt(portStr); + if (!(port >= 0 && port <= 65535)) { + throw new IllegalArgumentException("invalid port range"); + } + } catch (Exception e) { + throw new IllegalArgumentException(e.getMessage()); + } + } + + // 检查是否是合法的IP地址 + public static boolean isValidIPAddress(String ipAddress) { + InetAddressValidator validator = InetAddressValidator.getInstance(); + return validator.isValidInet4Address(ipAddress); + } + + // 检查是否是合法的域名 + public static boolean isValidDomainName(String domainName) { + DomainValidator validator = DomainValidator.getInstance(); + return validator.isValid(domainName); + } + + public static Proxy inputProxy() { + int retry = 3; + while (retry > 0) { + String proxy = JOptionPane.showInputDialog("Confirm Proxy Of Burp", "127.0.0.1:8080"); + try { + return new Proxy(proxy); + } catch (IllegalArgumentException e) { + BurpExtender.getStderr().println(e); + retry = retry - 1; + } + } + return null; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getProxyStr() { + return host + ":" + port; + } +} diff --git a/src/burp/BurpExtender.java b/src/burp/BurpExtender.java index 5fe50b9..5cceefb 100644 --- a/src/burp/BurpExtender.java +++ b/src/burp/BurpExtender.java @@ -10,268 +10,286 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; +import org.apache.commons.lang3.StringUtils; + import com.bit4woo.utilbox.burp.HelperPlus; import com.google.gson.Gson; -import config.ConfigManager; import config.ConfigEntry; +import config.ConfigManager; import config.ConfigTable; import config.ConfigTableModel; import config.GUI; -import knife.*; +import config.ProcessManager; +import knife.AddHostToScopeMenu; +import knife.ChangeToUploadRequest; +import knife.ChunkedEncodingMenu; +import knife.CopyJsOfThisSite; +import knife.CustomPayloadForAllInsertpointMenu; +import knife.CustomPayloadMenu; +import knife.DismissCancelMenu; +import knife.DismissMenu; +import knife.DoActiveScanMenu; +import knife.DownloadResponseMenu; +import knife.FindUrlAndRequest; +import knife.OpenWithBrowserMenu; +import knife.RunCmdMenu; +import knife.SetCookieMenu; +import knife.SetCookieWithHistoryMenu; +import knife.UpdateCookieMenu; +import knife.UpdateCookieWithHistoryMenu; +import knife.UpdateHeaderMenu; import messageTab.Info.InfoTabFactory; import messageTab.U2C.ChineseTabFactory; -import config.ProcessManager; -import org.apache.commons.lang3.StringUtils; public class BurpExtender extends GUI implements IBurpExtender, IContextMenuFactory, ITab, IHttpListener, IProxyListener, IExtensionStateListener { - /** - * - */ - private static final long serialVersionUID = 1L; - - public static IBurpExtenderCallbacks callbacks; - public static IExtensionHelpers helpers; - private static HelperPlus helperPlus; - - - public static PrintWriter stdout; - public static PrintWriter stderr; - public IContextMenuInvocation invocation; - - - public static String ExtensionName = "Knife"; - public static String Version = bsh.This.class.getPackage().getImplementationVersion(); - public static String Author = "by bit4woo"; - public static String github = "https://github.com/bit4woo/knife"; - - public static String CurrentProxy = ""; - - @Override - public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { - BurpExtender.callbacks = callbacks; - BurpExtender.helpers = callbacks.getHelpers(); - BurpExtender.helperPlus = new HelperPlus(helpers); - - flushStd(); - BurpExtender.stdout.println(getFullExtensionName()); - BurpExtender.stdout.println(github); - - configTable = new ConfigTable(new ConfigTableModel()); - configPanel.setViewportView(configTable); - - String content = callbacks.loadExtensionSetting("knifeconfig"); - if (StringUtils.isEmpty(content)) { - content = initConfig(); - } - - configManager = new Gson().fromJson(content, ConfigManager.class); - showToUI(configManager); - - ChineseTabFactory chntabFactory = new ChineseTabFactory(null, false, helpers, callbacks); - InfoTabFactory infotabFactory = new InfoTabFactory(null, false, helpers, callbacks); - - //各项数据初始化完成后在进行这些注册操作,避免插件加载时的空指针异常 - callbacks.setExtensionName(getFullExtensionName()); - callbacks.registerContextMenuFactory(this);// for menus - callbacks.registerMessageEditorTabFactory(chntabFactory);// for Chinese - callbacks.registerMessageEditorTabFactory(infotabFactory);// for Chinese - callbacks.addSuiteTab(BurpExtender.this); - callbacks.registerHttpListener(this); - callbacks.registerProxyListener(this); - callbacks.registerExtensionStateListener(this); - } - - - private static void flushStd() { - try { - stdout = new PrintWriter(callbacks.getStdout(), true); - stderr = new PrintWriter(callbacks.getStderr(), true); - } catch (Exception e) { - stdout = new PrintWriter(System.out, true); - stderr = new PrintWriter(System.out, true); - } - } - - public static PrintWriter getStdout() { - flushStd();//不同的时候调用这个参数,可能得到不同的值 - return stdout; - } - - public static PrintWriter getStderr() { - flushStd(); - return stderr; - } - - //name+version+author - public static String getFullExtensionName() { - return ExtensionName + " " + Version + " " + Author; - } - - //JMenu 是可以有下级菜单的,而JMenuItem是不能有下级菜单的 - @Override - public List createMenuItems(IContextMenuInvocation invocation) { - ArrayList menu_item_list = new ArrayList(); - - this.invocation = invocation; - //常用 - menu_item_list.add(new OpenWithBrowserMenu(this)); - menu_item_list.add(new CustomPayloadMenu(this)); - menu_item_list.add(new CustomPayloadForAllInsertpointMenu(this)); - - //cookie身份凭证相关 - menu_item_list.add(new UpdateCookieMenu(this)); - menu_item_list.add(new UpdateCookieWithHistoryMenu(this)); - menu_item_list.add(new ChangeToUploadRequest(this)); - - menu_item_list.add(new SetCookieMenu(this)); - menu_item_list.add(new SetCookieWithHistoryMenu(this)); - - UpdateHeaderMenu updateHeader = new UpdateHeaderMenu(this);//JMenuItem vs. JMenu - if (updateHeader.getItemCount() > 0) { - menu_item_list.add(updateHeader); - } - - //扫描攻击相关 - menu_item_list.add(new AddHostToScopeMenu(this)); - menu_item_list.add(new RunCmdMenu(this)); - menu_item_list.add(new DoActiveScanMenu(this)); - - - //不太常用的 - menu_item_list.add(new DismissMenu(this)); - menu_item_list.add(new DismissCancelMenu(this)); - - menu_item_list.add(new ChunkedEncodingMenu(this)); - menu_item_list.add(new DownloadResponseMenu(this)); - //menu_item_list.add(new DownloadResponseMenu2(this)); - //menu_item_list.add(new ViewChineseMenu(this)); - //menu_item_list.add(new JMenuItem()); - //空的JMenuItem不会显示,所以将是否添加Item的逻辑都方法到类当中去了,以便调整菜单顺序。 - - menu_item_list.add(new CopyJsOfThisSite(this)); - menu_item_list.add(new FindUrlAndRequest(this)); - - Iterator it = menu_item_list.iterator(); - while (it.hasNext()) { - JMenuItem item = it.next(); - if (StringUtils.isEmpty(item.getText())) { - it.remove(); - } - } - - String oneMenu = configTableModel.getConfigValueByKey("Put_MenuItems_In_One_Menu"); - if (oneMenu != null) { - ArrayList Knife = new ArrayList(); - JMenu knifeMenu = new JMenu("^_^ Knife"); - Knife.add(knifeMenu); - for (JMenuItem item : menu_item_list) { - knifeMenu.add(item); - } - return Knife; - } else { - return menu_item_list; - } - } - - - @Override - public String getTabCaption() { - return ("Knife"); - } - - - @Override - public Component getUiComponent() { - return this.getContentPane(); - } - - @Override - public void extensionUnloaded() { - saveConfigToBurp(); - } - - @Override - public String initConfig() { - configManager = new ConfigManager("default"); - configTableModel = new ConfigTableModel(); - return getAllConfig(); - } - - //IProxyListener中的方法,修改的内容会在proxy中显示为edited - @Override - public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessage message) { - //processHttpMessage(IBurpExtenderCallbacks.TOOL_PROXY,true,message.getMessageInfo()); - //same action will be executed twice! if call processHttpMessage() here. - if (StringUtils.isEmpty(CurrentProxy)) { - //为了知道burp当前监听的接口。供“find url and request”菜单使用 - CurrentProxy = message.getListenerInterface(); - } - IHttpRequestResponse messageInfo = message.getMessageInfo(); - List rules = ProcessManager.getAllActionRules(); - for (ConfigEntry rule:rules){ - rule.takeProxyAction(messageIsRequest,message); - } - - if (messageIsRequest) { - if (isInCheckBoxScope(IBurpExtenderCallbacks.TOOL_PROXY, messageInfo)) { - ProcessManager.doChunk(messageIsRequest, messageInfo); - } - } - } - - //IHttpListener中的方法,修改的内容在Proxy中不可见 - @Override - public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) { - //stdout.println("processHttpMessage called when messageIsRequest="+messageIsRequest); - try { - if (messageIsRequest) { - //add/update/append header - if (toolFlag == IBurpExtenderCallbacks.TOOL_PROXY) { - //##############################// - //handle it in processProxyMessage(). so we can see the changes in the proxy view. - //##############################// - } else { - List rules = ProcessManager.getEditActionRules(); - for (int index = rules.size() - 1; index >= 0; index--) {//按照时间倒叙引用规则 - - ConfigEntry rule = rules.get(index); - rule.takeEditAction(toolFlag, messageIsRequest, messageInfo); - } - - if (isInCheckBoxScope(toolFlag, messageInfo)) { - ProcessManager.doChunk(messageIsRequest, messageInfo); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - e.printStackTrace(stderr); - } - } - - public static IBurpExtenderCallbacks getCallbacks() { - return callbacks; - } - - - public static HelperPlus getHelperPlus() { + /** + * + */ + private static final long serialVersionUID = 1L; + + public static IBurpExtenderCallbacks callbacks; + public static IExtensionHelpers helpers; + private static HelperPlus helperPlus; + + + public static PrintWriter stdout; + public static PrintWriter stderr; + public IContextMenuInvocation invocation; + + + public static String ExtensionName = "Knife"; + public static String Version = bsh.This.class.getPackage().getImplementationVersion(); + public static String Author = "by bit4woo"; + public static String github = "https://github.com/bit4woo/knife"; + + public static String CurrentProxy = ""; + + @Override + public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { + BurpExtender.callbacks = callbacks; + BurpExtender.helpers = callbacks.getHelpers(); + BurpExtender.helperPlus = new HelperPlus(helpers); + + flushStd(); + BurpExtender.stdout.println(getFullExtensionName()); + BurpExtender.stdout.println(github); + + configTable = new ConfigTable(new ConfigTableModel()); + configPanel.setViewportView(configTable); + + String content = callbacks.loadExtensionSetting("knifeconfig"); + if (StringUtils.isEmpty(content)) { + content = initConfig(); + } + + configManager = new Gson().fromJson(content, ConfigManager.class); + showToUI(configManager); + + ChineseTabFactory chntabFactory = new ChineseTabFactory(null, false, helpers, callbacks); + InfoTabFactory infotabFactory = new InfoTabFactory(null, false, helpers, callbacks); + + //各项数据初始化完成后在进行这些注册操作,避免插件加载时的空指针异常 + callbacks.setExtensionName(getFullExtensionName()); + callbacks.registerContextMenuFactory(this);// for menus + callbacks.registerMessageEditorTabFactory(chntabFactory);// for Chinese + callbacks.registerMessageEditorTabFactory(infotabFactory);// for Chinese + callbacks.addSuiteTab(BurpExtender.this); + callbacks.registerHttpListener(this); + callbacks.registerProxyListener(this); + callbacks.registerExtensionStateListener(this); + } + + + private static void flushStd() { + try { + stdout = new PrintWriter(callbacks.getStdout(), true); + stderr = new PrintWriter(callbacks.getStderr(), true); + } catch (Exception e) { + stdout = new PrintWriter(System.out, true); + stderr = new PrintWriter(System.out, true); + } + } + + public static PrintWriter getStdout() { + flushStd();//不同的时候调用这个参数,可能得到不同的值 + return stdout; + } + + public static PrintWriter getStderr() { + flushStd(); + return stderr; + } + + //name+version+author + public static String getFullExtensionName() { + return ExtensionName + " " + Version + " " + Author; + } + + //JMenu 是可以有下级菜单的,而JMenuItem是不能有下级菜单的 + @Override + public List createMenuItems(IContextMenuInvocation invocation) { + ArrayList menu_item_list = new ArrayList(); + + this.invocation = invocation; + //常用 + menu_item_list.add(new OpenWithBrowserMenu(this)); + menu_item_list.add(new CustomPayloadMenu(this)); + menu_item_list.add(new CustomPayloadForAllInsertpointMenu(this)); + + //cookie身份凭证相关 + menu_item_list.add(new UpdateCookieMenu(this)); + menu_item_list.add(new UpdateCookieWithHistoryMenu(this)); + menu_item_list.add(new ChangeToUploadRequest(this)); + + menu_item_list.add(new SetCookieMenu(this)); + menu_item_list.add(new SetCookieWithHistoryMenu(this)); + + UpdateHeaderMenu updateHeader = new UpdateHeaderMenu(this);//JMenuItem vs. JMenu + if (updateHeader.getItemCount() > 0) { + menu_item_list.add(updateHeader); + } + + //扫描攻击相关 + menu_item_list.add(new AddHostToScopeMenu(this)); + menu_item_list.add(new RunCmdMenu(this)); + menu_item_list.add(new DoActiveScanMenu(this)); + + + //不太常用的 + menu_item_list.add(new DismissMenu(this)); + menu_item_list.add(new DismissCancelMenu(this)); + + menu_item_list.add(new ChunkedEncodingMenu(this)); + menu_item_list.add(new DownloadResponseMenu(this)); + //menu_item_list.add(new DownloadResponseMenu2(this)); + //menu_item_list.add(new ViewChineseMenu(this)); + //menu_item_list.add(new JMenuItem()); + //空的JMenuItem不会显示,所以将是否添加Item的逻辑都方法到类当中去了,以便调整菜单顺序。 + + menu_item_list.add(new CopyJsOfThisSite(this)); + menu_item_list.add(new FindUrlAndRequest(this)); + + Iterator it = menu_item_list.iterator(); + while (it.hasNext()) { + JMenuItem item = it.next(); + if (StringUtils.isEmpty(item.getText())) { + it.remove(); + } + } + + String oneMenu = configTableModel.getConfigValueByKey("Put_MenuItems_In_One_Menu"); + if (oneMenu != null) { + ArrayList Knife = new ArrayList(); + JMenu knifeMenu = new JMenu("^_^ Knife"); + Knife.add(knifeMenu); + for (JMenuItem item : menu_item_list) { + knifeMenu.add(item); + } + return Knife; + } else { + return menu_item_list; + } + } + + + @Override + public String getTabCaption() { + return ("Knife"); + } + + + @Override + public Component getUiComponent() { + return this.getContentPane(); + } + + @Override + public void extensionUnloaded() { + saveConfigToBurp(); + } + + @Override + public String initConfig() { + configManager = new ConfigManager("default"); + configTableModel = new ConfigTableModel(); + return getAllConfig(); + } + + //IProxyListener中的方法,修改的内容会在proxy中显示为edited + @Override + public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessage message) { + //processHttpMessage(IBurpExtenderCallbacks.TOOL_PROXY,true,message.getMessageInfo()); + //same action will be executed twice! if call processHttpMessage() here. + if (StringUtils.isEmpty(CurrentProxy)) { + //为了知道burp当前监听的接口。供“find url and request”菜单使用 + CurrentProxy = message.getListenerInterface(); + } + IHttpRequestResponse messageInfo = message.getMessageInfo(); + List rules = ProcessManager.getAllActionRules(); + for (ConfigEntry rule:rules){ + rule.takeProxyAction(messageIsRequest,message); + } + + if (messageIsRequest) { + if (isInCheckBoxScope(IBurpExtenderCallbacks.TOOL_PROXY, messageInfo)) { + ProcessManager.doChunk(messageIsRequest, messageInfo); + } + } + } + + //IHttpListener中的方法,修改的内容在Proxy中不可见 + @Override + public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) { + //stdout.println("processHttpMessage called when messageIsRequest="+messageIsRequest); + try { + if (messageIsRequest) { + //add/update/append header + if (toolFlag == IBurpExtenderCallbacks.TOOL_PROXY) { + //##############################// + //handle it in processProxyMessage(). so we can see the changes in the proxy view. + //##############################// + } else { + List rules = ProcessManager.getEditActionRules(); + for (int index = rules.size() - 1; index >= 0; index--) {//按照时间倒叙引用规则 + + ConfigEntry rule = rules.get(index); + rule.takeEditAction(toolFlag, messageIsRequest, messageInfo); + } + + if (isInCheckBoxScope(toolFlag, messageInfo)) { + ProcessManager.doChunk(messageIsRequest, messageInfo); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + e.printStackTrace(stderr); + } + } + + public static IBurpExtenderCallbacks getCallbacks() { + return callbacks; + } + + + public static HelperPlus getHelperPlus() { return helperPlus; } public static boolean isInCheckBoxScope(int toolFlag, IHttpRequestResponse messageInfo) { - if (toolFlag == (toolFlag & configManager.getEnableStatus())) { + if (toolFlag == (toolFlag & configManager.getEnableStatus())) { - IExtensionHelpers helpers = getCallbacks().getHelpers(); - URL url = new HelperPlus(helpers).getFullURL(messageInfo); + IExtensionHelpers helpers = getCallbacks().getHelpers(); + URL url = new HelperPlus(helpers).getFullURL(messageInfo); - if (!configManager.isOnlyForScope() || callbacks.isInScope(url)) { - return true; - } - } - return false; - } + if (!configManager.isOnlyForScope() || callbacks.isInScope(url)) { + return true; + } + } + return false; + } } diff --git a/src/burp/Proxy.java b/src/burp/Proxy.java deleted file mode 100644 index 88b487d..0000000 --- a/src/burp/Proxy.java +++ /dev/null @@ -1,82 +0,0 @@ -package burp; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.validator.routines.DomainValidator; -import org.apache.commons.validator.routines.InetAddressValidator; - -import javax.swing.*; - -public class Proxy { - - String host; - int port; - - public Proxy(String proxyStr) throws IllegalArgumentException { - if (StringUtils.isEmpty(proxyStr)) { - throw new IllegalArgumentException("input is empty"); - } - try { - String[] parts = proxyStr.split(":"); - if (parts.length != 2) { - throw new IllegalArgumentException("not valid host:port format"); - } - host = parts[0]; - if (!isValidIPAddress(host) && !isValidDomainName(host)) { - throw new IllegalArgumentException("host is not valid IP address and domain name"); - } - String portStr = parts[1]; - port = Integer.parseInt(portStr); - if (!(port >= 0 && port <= 65535)) { - throw new IllegalArgumentException("invalid port range"); - } - } catch (Exception e) { - throw new IllegalArgumentException(e.getMessage()); - } - } - - // 检查是否是合法的IP地址 - public static boolean isValidIPAddress(String ipAddress) { - InetAddressValidator validator = InetAddressValidator.getInstance(); - return validator.isValidInet4Address(ipAddress); - } - - // 检查是否是合法的域名 - public static boolean isValidDomainName(String domainName) { - DomainValidator validator = DomainValidator.getInstance(); - return validator.isValid(domainName); - } - - public static Proxy inputProxy() { - int retry = 3; - while (retry > 0) { - String proxy = JOptionPane.showInputDialog("Confirm Proxy Of Burp", "127.0.0.1:8080"); - try { - return new Proxy(proxy); - } catch (IllegalArgumentException e) { - BurpExtender.getStderr().println(e); - retry = retry - 1; - } - } - return null; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getProxyStr() { - return host + ":" + port; - } -} diff --git a/src/knife/FindUrlAndRequest.java b/src/knife/FindUrlAndRequest.java index bcbede5..22762d2 100644 --- a/src/knife/FindUrlAndRequest.java +++ b/src/knife/FindUrlAndRequest.java @@ -1,38 +1,9 @@ package knife; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.PrintWriter; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - import javax.swing.JMenuItem; -import javax.swing.JOptionPane; - -import org.apache.commons.lang3.StringUtils; - -import com.bit4woo.utilbox.burp.HelperPlus; -import com.bit4woo.utilbox.utils.SwingUtils; -import com.bit4woo.utilbox.utils.TextUtils; -import com.bit4woo.utilbox.utils.UrlUtils; -import base.RequestTask; -import base.RequestType; +import base.FindUrl_Action; import burp.BurpExtender; -import burp.IBurpExtenderCallbacks; -import burp.IContextMenuInvocation; -import burp.IExtensionHelpers; -import burp.IHttpRequestResponse; -import burp.Proxy; -import burp.threadRequester; public class FindUrlAndRequest extends JMenuItem { @@ -40,14 +11,7 @@ public class FindUrlAndRequest extends JMenuItem { * */ private static final long serialVersionUID = 1L; - public static final String[] blackHostList = {"www.w3.org", "ns.adobe.com", "iptc.org", "openoffice.org" - , "schemas.microsoft.com", "schemas.openxmlformats.org", "sheetjs.openxmlformats.org","registry.npmjs.org" - ,"json-schema.org","jmespath.org"}; - public static final List blackPath = TextUtils.textToLines("text/css\r\n" - + " text/html\r\n" - + " text/plain\r\n" - + " image/pdf\r\n"); //JMenuItem vs. JMenu public FindUrlAndRequest(BurpExtender burp) { @@ -55,31 +19,6 @@ public FindUrlAndRequest(BurpExtender burp) { this.addActionListener(new FindUrl_Action(burp, burp.invocation)); } - - public static List cleanUrls(List urls) { - - urls = TextUtils.deduplicate(urls); - Iterator it = urls.iterator(); - while (it.hasNext()) { - String urlItem = it.next(); - if (UrlUtils.uselessExtension(urlItem)) { - it.remove(); - } - if (blackPath.contains(urlItem)) { - it.remove(); - } - try { - String host = new URL(urlItem).getHost(); - if (Arrays.asList(blackHostList).contains(host)) { - it.remove(); - } - } catch (Exception E) { - continue; - } - } - return urls; - } - public static void main(String[] args) { String url = "./abac/aaa.jpg"; if (url.startsWith("./")) { @@ -88,228 +27,3 @@ public static void main(String[] args) { System.out.println(url); } } - -class FindUrl_Action implements ActionListener { - private IContextMenuInvocation invocation; - public IExtensionHelpers helpers; - public PrintWriter stdout; - public PrintWriter stderr; - public IBurpExtenderCallbacks callbacks; - public BurpExtender burp; - - - private static Proxy proxy; - - public FindUrl_Action(BurpExtender burp, IContextMenuInvocation invocation) { - this.burp = burp; - this.invocation = invocation; - this.helpers = burp.helpers; - this.callbacks = BurpExtender.callbacks; - this.stderr = BurpExtender.stderr; - this.stdout = BurpExtender.stdout; - } - - @Override - public void actionPerformed(ActionEvent event) { - Runnable requestRunner = new Runnable() { - String siteBaseUrl = null; - Set baseUrls = new HashSet<>(); - List urls = new ArrayList<>(); - - @Override - public void run() { - try { - IHttpRequestResponse[] messages = invocation.getSelectedMessages(); - if (messages == null || messages.length <= 0) { - return; - } - - BlockingQueue inputQueue = new LinkedBlockingQueue<>(); - - try { - findUrls(messages[0]); - - if (baseUrls.size() <= 0) { - return; - } - String baseurl = choseAndEditBaseURL(baseUrls); - - if (null == baseurl) { - return; - } - - urls = choseURLPath(urls); - if (urls.size()<=0) return; - for (String url : urls) { - if (!url.startsWith("http://") && !url.startsWith("https://")) { - if (url.startsWith("/")) { - url = url.replaceFirst("/", ""); - } - if (url.startsWith("./")) { - url = url.replaceFirst("\\./", ""); - } - url = baseurl + url; //baseurl统一以“/”结尾;url统一删除“/”的开头 - inputQueue.put(new RequestTask(url, RequestType.GET)); - inputQueue.put(new RequestTask(url, RequestType.POST)); - inputQueue.put(new RequestTask(url, RequestType.JSON)); - } - } - } catch (Exception e) { - e.printStackTrace(BurpExtender.getStderr()); - } - - doRequest(inputQueue, siteBaseUrl); - } catch (Exception e1) { - e1.printStackTrace(stderr); - } - } - - - /** - * 根据当前web的baseUrl找JS,特征就是referer以它开头 - * @param message - * @return - */ - public void findUrls(IHttpRequestResponse message) { - HelperPlus getter = new HelperPlus(helpers); - - String current_referUrl = getter.getHeaderValueOf(true, message, "Referer"); - String current_fullUrl = getter.getFullURL(message).toString(); - - if (current_referUrl != null) { - //认为当前数据包是前端触发的 - baseUrls.add(current_referUrl); - siteBaseUrl = UrlUtils.getBaseUrl(current_referUrl); - } else { - //认为其是当前数据包是浏览器地址栏访问直接触发的 - baseUrls.add(current_fullUrl); - siteBaseUrl = UrlUtils.getBaseUrl(current_fullUrl); - } - - - IHttpRequestResponse[] messages = BurpExtender.getCallbacks().getSiteMap(null); - for (IHttpRequestResponse item : messages) { - URL url = getter.getFullURL(item); - if (url == null || (!url.toString().toLowerCase().endsWith(".js") && !url.toString().toLowerCase().endsWith(".js.map"))) { - continue; - } - - int code = getter.getStatusCode(item); - String referUrl = getter.getHeaderValueOf(true, item, "Referer"); - if (referUrl == null || code <= 0) { - continue; - } - - if (referUrl.toLowerCase().startsWith(siteBaseUrl.toLowerCase())) { - byte[] respBody = HelperPlus.getBody(false, item); - String body = new String(respBody); - body = TextUtils.decodeAll(body); - urls.addAll(UrlUtils.grepUrlsWithProtocol(body)); - urls.addAll(UrlUtils.grepUrlPathNotStartWithSlashInQuotes(body)); - urls.addAll(UrlUtils.grepUrlsInQuotes(body)); - urls = FindUrlAndRequest.cleanUrls(urls); - baseUrls.addAll(findPossibleBaseURL(urls)); - } - } - } - }; - new Thread(requestRunner).start(); - } - - - /** - * 多线程执行请求 - * - * @param inputQueue - */ - public void doRequest(BlockingQueue inputQueue, String referUrl) { - if (proxy == null) { - proxy = Proxy.inputProxy(); - } - if (proxy == null) { - return; - } - - int max = threadNumberShouldUse(inputQueue.size()); - - for (int i = 0; i <= max; i++) { - threadRequester requester = new threadRequester(inputQueue, proxy.getHost(), proxy.getPort(), referUrl, i); - requester.start(); - } - } - - /** - * 根据已有的域名梳理,预估应该使用的线程数 - * 假设1个任务需要1秒钟。线程数在1-100之间,如何选择线程数使用最小的时间? - * - * @param domainNum - * @return - */ - public static int threadNumberShouldUse(int domainNum) { - - int tmp = (int) Math.sqrt(domainNum); - if (tmp <= 1) { - return 1; - } else if (tmp >= 10) { - return 10; - } else { - return tmp; - } - } - - public static Set findPossibleBaseURL(List urls) { - Set baseURLs = new HashSet<>(); - for (String tmpurl : urls) { - //这部分提取的是含有协议头的完整URL地址 - if (tmpurl.toLowerCase().startsWith("http://") - || tmpurl.toLowerCase().startsWith("https://")) { - - baseURLs.add(tmpurl); - } - } - return baseURLs; - } - - - - public static String choseAndEditBaseURL(Set inputs) { - - ArrayList tmpList = new ArrayList(inputs); - Collections.sort(tmpList); - int n = inputs.size() + 1; - String[] possibleValues = new String[n]; - - // Copying contents of domains to arr[] - System.arraycopy(tmpList.toArray(), 0, possibleValues, 0, n - 1); - possibleValues[n - 1] = "Let Me Input"; - - String selectedValue = (String) JOptionPane.showInputDialog(null, - "Chose Base URL", "Chose And Edit Base URL", - JOptionPane.INFORMATION_MESSAGE, null, - possibleValues, possibleValues[0]); - if (null != selectedValue) { - String baseUrl = JOptionPane.showInputDialog("Confirm The Base URL", selectedValue); - if (baseUrl == null) { - return null; - } - if (!baseUrl.endsWith("/")) { - baseUrl = baseUrl.trim() + "/"; - } - return baseUrl.trim(); - } - return selectedValue; - } - - - public static List choseURLPath(List urls) { - - Collections.sort(urls); - - String text = SwingUtils.showTextAreaDialog(String.join(System.lineSeparator(), urls)); - if (StringUtils.isEmpty(text)) { - return new ArrayList(); - }else { - return TextUtils.textToLines(text); - } - } -} diff --git a/src/messageTab/Info/InfoPanel.java b/src/messageTab/Info/InfoPanel.java index d00bf1d..89f8d90 100644 --- a/src/messageTab/Info/InfoPanel.java +++ b/src/messageTab/Info/InfoPanel.java @@ -24,9 +24,20 @@ public class InfoPanel extends JPanel { boolean isRequest; InfoTable table; + private InfoTab InfoTab; + + + public InfoTab getInfoTab() { + return InfoTab; + } + + + public void setInfoTab(InfoTab infoTab) { + InfoTab = infoTab; + } - public InfoTable getTable() { + public InfoTable getTable() { return table; } @@ -37,7 +48,7 @@ public void setTable(InfoTable table) { InfoPanel(InfoTab parent) { - + this.InfoTab = parent; setBorder(new EmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout(0, 0)); @@ -45,7 +56,7 @@ public void setTable(InfoTable table) { add(buttonPanel, BorderLayout.NORTH); InfoTableModel model = new InfoTableModel(); - table = new InfoTable(model); + table = new InfoTable(model,this); JScrollPane scrollPane = new JScrollPane(); scrollPane.setViewportView(table); diff --git a/src/messageTab/Info/InfoTab.java b/src/messageTab/Info/InfoTab.java index b2d3dbf..0483852 100644 --- a/src/messageTab/Info/InfoTab.java +++ b/src/messageTab/Info/InfoTab.java @@ -2,6 +2,7 @@ import java.awt.Component; import java.util.List; +import java.util.Set; import javax.swing.JPanel; import javax.swing.SwingWorker; @@ -11,125 +12,137 @@ import com.bit4woo.utilbox.utils.TextUtils; import com.bit4woo.utilbox.utils.UrlUtils; +import base.FindUrl_Action; import burp.BurpExtender; import burp.IBurpExtenderCallbacks; import burp.IExtensionHelpers; +import burp.IHttpRequestResponse; import burp.IMessageEditorController; import burp.IMessageEditorTab; import knife.FindUrlAndRequest; +import org.apache.commons.lang3.StringUtils; -/** +/** * @author bit4woo - * @github https://github.com/bit4woo - * @version CreateTime:2022年1月15日 下午11:07:59 - * + * @version CreateTime:2022年1月15日 下午11:07:59 + *

* 想要正确显示中文内容,有三个编码设置会影响结果: * 1、原始编码,通过代码尝试自动获取,但是结果可能不准确,极端情况下需要手动设置。 * 2、转换后的编码,手动设置。 * 3、burp设置的显示编码,显示时时用的编码,应该和转换后的编码一致。 - * + *

* 原始数据是byte[],但也是文本内容的某种编码的byte[]. - * + * @github https://github.com/bit4woo */ -public class InfoTab implements IMessageEditorTab{ - private JPanel panel; +public class InfoTab implements IMessageEditorTab { + private JPanel panel; - private byte[] originContent; + private byte[] originContent; - public InfoTab(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) - { - panel = new InfoPanel(this); - BurpExtender.getCallbacks().customizeUiComponent(panel);//尝试使用burp的font size - } - - @Override - public String getTabCaption() - { - return "Info"; - } - - @Override - public Component getUiComponent() - { - return panel; - } - - @Override - public boolean isEnabled(byte[] content, boolean isRequest) - { - return true; - } - - /** - * 每次切换到这个tab,都会调用这个函数。应考虑避免重复劳动,根据originContent是否变化来判断。 - */ - @Override - public void setMessage(byte[] content, boolean isRequest){ - if (content ==null || content.length ==0) { - return; - }else if (ByteArrayUtils.equals(originContent,content)) { - return; - }else { - originContent = content; - SwingWorker worker = new SwingWorker() { - @Override - protected Void doInBackground() throws Exception { - String text = new String(content); - text = TextUtils.decodeAll(text); - - List urls = UrlUtils.grepUrlsWithProtocol(text); - urls.addAll(UrlUtils.grepUrlsInQuotes(text)); - urls.addAll(UrlUtils.grepUrlPathNotStartWithSlashInQuotes(text)); - urls = TextUtils.deduplicate(urls); - urls = FindUrlAndRequest.cleanUrls(urls); - for (String url:urls) { - InfoEntry aaa = new InfoEntry(url,InfoEntry.Type_URL); - ((InfoPanel)panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); - } - - List emails = EmailUtils.grepEmail(text); - emails = TextUtils.deduplicate(emails); - for (String email:emails) { - InfoEntry aaa = new InfoEntry(email,InfoEntry.Type_Email); - ((InfoPanel)panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); - } - - return null; - } - }; - worker.execute(); - } - } - - - /** - * 中文下的编辑还是有问题,暂不支持。 - * 始终返回原始内容。 - */ - @Override - public byte[] getMessage() - { + public byte[] getOriginContent() { return originContent; } - @Override - public boolean isModified() - { - return false; + public void setOriginContent(byte[] originContent) { + this.originContent = originContent; } - /** - * ctrl+c复制数据逻辑会调用这个函数 - */ - @Override - public byte[] getSelectedData() - { - InfoTable table = (InfoTable)((InfoPanel)panel).getTable(); - String content = table.getSelectedContent(); - return content.getBytes(); - } - - - public static void main(String[] args) { - } + public InfoTab(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) { + panel = new InfoPanel(this); + BurpExtender.getCallbacks().customizeUiComponent(panel);//尝试使用burp的font size + } + + @Override + public String getTabCaption() { + return "Info"; + } + + @Override + public Component getUiComponent() { + return panel; + } + + @Override + public boolean isEnabled(byte[] content, boolean isRequest) { + String contentType = BurpExtender.getHelperPlus().getHeaderValueOf(isRequest, content, "Content-Type"); + if (StringUtils.isEmpty(contentType)) { + return true; + } + if (contentType.contains("image/")) { + return false; + } else if (contentType.contains("text/css")) { + return false; + } else if (contentType.contains("font/")) { + return false; + } else if (contentType.contains("x-protobuf")) { + return false; + } + + return true; + } + + /** + * 每次切换到这个tab,都会调用这个函数。应考虑避免重复劳动,根据originContent是否变化来判断。 + */ + @Override + public void setMessage(byte[] content, boolean isRequest) { + if (content == null || content.length == 0) { + return; + } else if (ByteArrayUtils.equals(originContent, content)) { + return; + } else { + originContent = content; + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + + List urls = FindUrl_Action.findUrls(content); + + for (String url : urls) { + InfoEntry aaa = new InfoEntry(url, InfoEntry.Type_URL); + ((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); + } + + List emails = EmailUtils.grepEmail(new String(content)); + emails = TextUtils.deduplicate(emails); + for (String email : emails) { + InfoEntry aaa = new InfoEntry(email, InfoEntry.Type_Email); + ((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); + } + + return null; + } + }; + worker.execute(); + } + } + + + /** + * 中文下的编辑还是有问题,暂不支持。 + * 始终返回原始内容。 + */ + @Override + public byte[] getMessage() { + return originContent; + } + + @Override + public boolean isModified() { + return false; + } + + /** + * ctrl+c复制数据逻辑会调用这个函数 + */ + @Override + public byte[] getSelectedData() { + InfoTable table = (InfoTable) ((InfoPanel) panel).getTable(); + String content = table.getSelectedContent(); + return content.getBytes(); + } + + + public static void main(String[] args) { + } } \ No newline at end of file diff --git a/src/messageTab/Info/InfoTable.java b/src/messageTab/Info/InfoTable.java index 5076b7b..1ff9a5a 100644 --- a/src/messageTab/Info/InfoTable.java +++ b/src/messageTab/Info/InfoTable.java @@ -30,8 +30,11 @@ public class InfoTable extends JTable { //public static final String[] headers = {"Value", "Type"}; public static final String[] headers = {"Value"}; - public InfoTable(InfoTableModel tableModel) { + private InfoPanel infoPanel; + + public InfoTable(InfoTableModel tableModel,InfoPanel infoPanel) { super(tableModel); + this.infoPanel = infoPanel; this.setColumnModel(columnModel); this.setFillsViewportHeight(true);//在table的空白区域显示右键菜单 //https://stackoverflow.com/questions/8903040/right-click-mouselistener-on-whole-jtable-component @@ -127,6 +130,13 @@ public void mouseClicked(MouseEvent e) { String browserPath = BurpExtender.getConfigTableModel().getConfigValueByKey("browserPath"); SystemUtils.browserOpen(url, browserPath); return; + }else { + //TODO 还没有想要获取baseUrl的方法 + byte[] content = infoPanel.getInfoTab().getOriginContent(); + /* + * FindUrl_Action.FindAllUrls(content); FindUrl_Action.findPossibleBaseURL(); + * BurpExtender.BaseUrlMap.get(e); + */ } } } catch (Exception e1) { diff --git a/src/messageTab/Info/InfoTableMenu.java b/src/messageTab/Info/InfoTableMenu.java index ca49010..7b3274d 100644 --- a/src/messageTab/Info/InfoTableMenu.java +++ b/src/messageTab/Info/InfoTableMenu.java @@ -33,6 +33,14 @@ public void actionPerformed(ActionEvent actionEvent) { SystemUtils.writeToClipboard(content); } }); + + JMenuItem changeBaseUrlItem = new JMenuItem(new AbstractAction("Set/Change Base URL") { + @Override + public void actionPerformed(ActionEvent actionEvent) { + String content = infoTable.getSelectedContent(); + SystemUtils.writeToClipboard(content); + } + }); add(copyItem); }