Skip to content

Instantly share code, notes, and snippets.

@jrmdev
Last active May 21, 2021 19:42
Show Gist options
  • Save jrmdev/e41da1aa4da504b21af64ca6549fd7be to your computer and use it in GitHub Desktop.
Save jrmdev/e41da1aa4da504b21af64ca6549fd7be to your computer and use it in GitHub Desktop.
Burp Proxy plugin to generate ready to paste text-based evidence for HTTP requests and responses.
##
## Evidence Generator Evidence Generator - Burp Extension
##
## Download Jython and configure it in the Extender options:
## http://search.maven.org/remotecontent?filepath=org/python/jython-standalone/2.5.4-rc1/jython-standalone-2.5.4-rc1.jar
##
## Right click on any request from different Burp Suite tools and send to the extension
##
from burp import IBurpExtender, ITab, IContextMenuFactory
from javax.swing import JPanel, JTextArea, JMenuItem, JScrollPane, JLabel, JTextField, JButton, JOptionPane, JPopupMenu
from javax.swing.text import DefaultHighlighter
from java.io import PrintWriter
from java.util import LinkedList
from java.awt import Toolkit
from java.awt.event import ActionListener, ComponentListener, MouseAdapter, MouseEvent
from java.awt.datatransfer import StringSelection
from re import sub, MULTILINE
import json
import array
class BurpExtender(IBurpExtender, IContextMenuFactory):
def registerExtenderCallbacks(self, callbacks):
self.callbacks = callbacks
self.helpers = self.callbacks.getHelpers()
self.callbacks.setExtensionName('HTTP Evidence Generator')
self.stdout = PrintWriter(self.callbacks.getStdout(), True)
self.stderr = PrintWriter(self.callbacks.getStderr(), True)
self.stdout.println('Extension loaded')
#self.stderr.println('Extension loaded')
#self.callbacks.issueAlert('Extension loaded') # Alerts tab
self.callbacks.registerContextMenuFactory(self)
self.tab = EvidenceGeneratorTab(self.callbacks)
self.callbacks.addSuiteTab(self.tab)
def createMenuItems(self, invocation):
responses = invocation.getSelectedMessages()
if responses > 0:
ret = LinkedList()
MenuItem1 = JMenuItem("Evidence Generator: Generate Evidence")
MenuItem1.addActionListener(handleMenuItems(self, responses[0], "MenuItem1"))
ret.add(MenuItem1)
# To add more:
#MenuItem2 = JMenuItem("Evidence Generator: Test")
#MenuItem2.addActionListener(handleMenuItems(self, responses[0], "MenuItem2"))
#ret.add(MenuItem2)
return ret
return None
class FrameListener(ComponentListener):
def __init__(self, tab):
self.tab = tab
def componentHidden(self, e):
pass
def componentMoved(self, e):
pass
def componentShown(self, e):
pass
def componentResized(self, e):
size = e.getComponent().getBounds().getSize()
self.tab.textbox1.setBounds(10, 35, size.width-20, 25)
self.tab.textbox2_component.setBounds(10, 90, size.width-20, size.height-140)
self.tab.button1.setBounds(10, size.height-42, 120, 30)
self.tab.button2.setBounds(140, size.height-42, 140, 30)
self.tab.button3.setBounds(290, size.height-42, 150, 30)
self.tab.button4.setBounds(450, size.height-42, 150, 30)
self.tab.button5.setBounds(610, size.height-42, 150, 30)
class EvidencePopUp(JPopupMenu, ActionListener):
def __init__(self, text_component, encoding='utf-8'):
self.text_component = text_component
self.text_encoding = encoding
self.item = JMenuItem("Beautify JSON")
self.item.addActionListener(self)
self.add(self.item)
def actionPerformed(self, e):
if e.getActionCommand() == "Beautify JSON":
sel_bytes = self.text_component.getSelectedText()
if sel_bytes is None:
return
text = self.text_component.getText()
sel_text = bytearray(sel_bytes).decode(self.text_encoding)
(sel_begin, sel_end) = self.text_component.getSelectionBounds()
try:
o_json = json.loads(sel_text)
f_json = json.dumps(o_json, indent=3, sort_keys=False)
except Exception as e:
print("Cannot beautify JSON: {}".format(repr(e)))
return
self.text_component.setText(text[0:sel_begin] + array.array('b', f_json.encode(self.text_encoding)) + text[sel_end+1:])
class EvidenceMouseListener(MouseAdapter):
def __init__(self, text_component):
self.text_component = text_component
def mousePressed(self, e):
if e.isPopupTrigger():
self.popup(e)
def mouseReleased(self, e):
if e.isPopupTrigger():
self.popup(e)
def popup(self, e):
menu = EvidencePopUp(self.text_component)
menu.show(e.getComponent(), e.getX(), e.getY())
class EvidenceGeneratorTab(ITab):
def __init__(self, callbacks):
self.callbacks = callbacks
self.helpers = self.callbacks.getHelpers()
def getTabCaption(self):
return 'HTTP Evidence Generator'
def getUiComponent(self):
label1 = JLabel("Evidence title:")
label1.setBounds(10, 10, 200, 25)
label2 = JLabel("Evidence text:")
label2.setBounds(10, 65, 200, 25)
self.textbox1 = JTextField("", 25)
self.textbox2 = self.callbacks.createTextEditor()
self.textbox2.setEditable(True)
self.textbox2_component = self.textbox2.getComponent()
self.textbox2_component.addMouseListener(EvidenceMouseListener(self.textbox2))
self.button1 = JButton("Snip cookies", actionPerformed=self.snip_cookies)
self.button2 = JButton("Snip resp. body", actionPerformed=self.snip_resp_body)
self.button3 = JButton("Snip selected text", actionPerformed=self.snip_selection)
self.button4 = JButton("Keep selected text", actionPerformed=self.keep_selection)
self.button5 = JButton("Copy to clipboard", actionPerformed=self.copy_to_clipboard)
self.panel = JPanel()
self.panel.setLayout(None)
self.panel.add(label1)
self.panel.add(self.textbox1)
self.panel.add(label2)
self.panel.add(self.textbox2_component)
self.panel.add(self.button1)
self.panel.add(self.button2)
self.panel.add(self.button3)
self.panel.add(self.button4)
self.panel.add(self.button5)
self.panel.addComponentListener(FrameListener(self))
self.callbacks.customizeUiComponent(self.panel)
return self.panel
def snip_cookies(self, e):
text = self.helpers.bytesToString(self.textbox2.getText())
if 'Cookie: ' in text:
text = sub(r"^Cookie: .+$", "Cookie: <Snip>", text, flags=MULTILINE)
self.textbox2.setText(text)
def snip_resp_body(self, e):
text = self.helpers.bytesToString(self.textbox2.getText())
if len(text):
index = text.find("Response:") + 10
text = text[:index] + text[index:].split("\n\n", 2)[0]
text += "\n\n<!-- Snip -->\n"
self.textbox2.setText(text)
def keep_selection(self, e):
if self.textbox2.getSelectedText():
text = self.helpers.bytesToString(self.textbox2.getText())
index = text.find("Response:") + 10
if text[index:].find("\n\n") > -1: # resp. body not empty
resp_body_offset = index + text[index:].find("\n\n") + 2
b1, b2 = self.textbox2.getSelectionBounds()
if b1 > resp_body_offset and b2 > resp_body_offset:
self.textbox2.setText(text[:resp_body_offset] + "<!-- Snip -->\n" + text[b1:b2] + "\n<!-- Snip -->")
def snip_selection(self, e):
if self.textbox2.getSelectedText():
text = self.helpers.bytesToString(self.textbox2.getText())
b1, b2 = self.textbox2.getSelectionBounds()
self.textbox2.setText(text[:b1] + "<!-- Snip -->" + text[b2:])
def copy_to_clipboard(self, e):
text = self.helpers.bytesToString(self.textbox2.getText())
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
clipboard.setContents(StringSelection(text), None)
class handleMenuItems(ActionListener):
def __init__(self, extender, messageInfo, menuName):
self.extender = extender
self.menuName = menuName
self.messageInfo = messageInfo
self.raw_req = self.extender.helpers.bytesToString(messageInfo.getRequest()).strip()
self.raw_res = self.extender.helpers.bytesToString(messageInfo.getResponse()).strip()
# Work around MST oddities when copy pasting
self.raw_req = self.raw_req.replace("\r", "")
self.raw_res = self.raw_res.replace("\r", "")
self.raw_req = self.raw_req.replace("\x00", "")
self.raw_res = self.raw_res.replace("\x00", "")
self.title_field = self.extender.tab.textbox1
self.evidence_field = self.extender.tab.textbox2
self.title_field.setText("")
self.evidence_field.setText("")
def actionPerformed(self, e):
if self.menuName == "MenuItem1":
self.evidence_generic(self.messageInfo)
#if self.menuName == "MenuItem2":
# do stuff
def evidence_generic(self, messageInfo):
self.title_field.setText("Raw HTTP request / response:")
self.evidence_field.setText("Request:\n\n%s\n\nResponse:\n\n%s" % (self.raw_req, self.raw_res))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment