Skip to content

Instantly share code, notes, and snippets.

@leesoh
Forked from jrmdev/HttpEvidenceGenerator.py
Created May 28, 2020 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leesoh/d820e17cf1536296f6a0cb9307856596 to your computer and use it in GitHub Desktop.
Save leesoh/d820e17cf1536296f6a0cb9307856596 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