package burp; import java.util.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.Toolkit; import java.io.UnsupportedEncodingException; import javax.swing.JMenuItem; public class BurpExtender implements IBurpExtender, IContextMenuFactory, ClipboardOwner { private IExtensionHelpers helpers; private final static String NAME = "Copy as Go HTTP"; private final static String[] GO_ESCAPE = new String[256]; private int currentID = 0; private int currentTotal = 0; static { for (int i = 0x00; i <= 0xFF; i++) GO_ESCAPE[i] = String.format("\\x%02x", i); for (int i = 0x20; i < 0x80; i++) GO_ESCAPE[i] = String.valueOf((char)i); GO_ESCAPE['\n'] = "\\n"; GO_ESCAPE['\r'] = "\\r"; GO_ESCAPE['\t'] = "\\t"; GO_ESCAPE['"'] = "\\\""; GO_ESCAPE['\\'] = "\\\\"; } @Override public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { helpers = callbacks.getHelpers(); callbacks.setExtensionName(NAME); callbacks.registerContextMenuFactory(this); } @Override public List createMenuItems(IContextMenuInvocation invocation) { final IHttpRequestResponse[] messages = invocation.getSelectedMessages(); if (messages == null || messages.length == 0) return null; JMenuItem i = new JMenuItem(NAME); i.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { copyMessages(messages); } }); return Collections.singletonList(i); } private void copyMessages(IHttpRequestResponse[] messages) { StringBuilder goSrc = new StringBuilder(""); buildBoilerCodeStart(goSrc); this.currentID = 0; this.currentTotal = messages.length; for (IHttpRequestResponse message : messages) { this.currentID += 1; IRequestInfo ri = helpers.analyzeRequest(message); byte[] req = message.getRequest(); goSrc.append(String.format(" method"+ this.currentID +" := \"%s\"\n", escapeGoString(ri.getMethod()))); goSrc.append(String.format(" url"+ this.currentID +" := \"%s\"\n", escapeGoString(ri.getUrl().toString()))); goSrc.append("\n"); goSrc.append(" // making body\n"); processBody(goSrc, req, ri.getBodyOffset()); buildBoilerCodeRequest(goSrc); processHeaders(goSrc, ri.getHeaders()); buildBoilerCodeSend(goSrc); } goSrc.append(" return res\n"); goSrc.append("}\n"); Toolkit.getDefaultToolkit().getSystemClipboard() .setContents(new StringSelection(goSrc.toString()), this); } public String escapeGoString(String src) { StringBuilder buildStr = new StringBuilder(""); for (int i=0;i headers) { boolean firstHeader = true; for (String header : headers) { int colonPos = header.indexOf(':'); if (colonPos == -1) continue; if (header.substring(0,colonPos).toLowerCase().equals("cookie")) { goSrc.append(" newRequest"+ this.currentID +".Header.Add(\""); goSrc.append(header, 0, colonPos); goSrc.append("\",\""); goSrc.append(header, colonPos + 2, header.length()); goSrc.append("\")\n"); goSrc.append(" urlStruct"+ this.currentID +", _ := url.Parse(url"+ this.currentID +")\n"); goSrc.append(" urlStruct"+ this.currentID +".Path = \"/\"\n"); goSrc.append(" client.Jar.SetCookies(urlStruct"+ this.currentID +", newRequest"+ this.currentID +".Cookies())\n"); goSrc.append(" newRequest"+ this.currentID +".Header.Del(\""+header.substring(0,colonPos)+"\")\n"); } else { goSrc.append(" newRequest"+ this.currentID +".Header.Add(\""); goSrc.append(header, 0, colonPos); goSrc.append("\",\""); goSrc.append(header, colonPos + 2, header.length()); goSrc.append("\")\n"); } } } private void processBody(StringBuilder goSrc, byte[] fullRequest, int start) { byte[] bodyBytes = Arrays.copyOfRange(fullRequest, start, fullRequest.length); String str = new String(bodyBytes); String bodyStr = String.format(" body"+ this.currentID +" := strings.NewReader(\"%s\")\n", escapeGoString(str)); goSrc.append(bodyStr); } @Override public void lostOwnership(Clipboard aClipboard, Transferable aContents) {} }