Wednesday, August 8, 2012

Adding GUI features to an extension

A unique feature of our framework is the ability to add your own GUI features to your extensions. It takes advantaged of Jython, the Python for Java platform. There are many tutorials out there on using Jython, but to make your life easier I have added the 'AdvancedSkeleton.py' to the framework for you to take a peak it. It is a working example of a Jython SwingSampler working within our framework. Even with zero experience with Jython/Java you should be able to look at the current code and piece together aspects that you would like available in your extension. If you do have GUI development experience with Java, this is going to be cake for you.

Lets build a new extension that has some GUI functionality. We'll start by importing the correct modules to build a swing based GUI, including other modules that will be used for the extensions features. In this case we'll build a payload encoder and parser.


import javax.swing as swing
import java.awt as awt
import java.net as net
import urllib
import base64
import re
import os
import imp
import inspect



We can then continue on like the usual standard... include our INFO dictionary, our original class, and make sure that we subclass 'Extension'.


class PayloadEncoder(Extension):
    INFO = {
        'Name'    :    'Payload Encoder',
        'Usage'   :    'This extension will help encode and parse out which payloads you will be able to use by stripping out sanitized characters.',
        'Author'  :    'James Lester, Joseph Tartaro'
    }

    def finishedLaunching(self):
        for key in ["Name", "Usage", "Author"]:
            self.printLogTab("%s: %s\n" % (key, self.INFO[key]))
            self.printLogTab("---\n\n")
            PayloadEncoderMain(self)



We can now continue by building the pane we'll be adding to a tab, including the functionality of the extension. This will all be inside of the 'PayloadEncoderMain' class that is initiated upon 'finishedLaunching'. In this case we'll use the 'BorderLayout' layout manager, but you're not limited to this, there are various layout managers to choose from. I won't explain every line in detail, but a quick walkthrough... We setup two panels and define them with the 'BorderLayout' layout manager. We then add borders to them with specific titles, 'Payload Encoder' and 'Payload Parser'. We then populate them with textfields for input and also text areas for output. We then build a split pane that will be populated with both panels, which is then added to a tab and displayed in the GUI via the 'addTabPanel' method.


class PayloadEncoderMain(object):

    def __init__(self, parent):
        self.parent = parent
        
        Panel = swing.JPanel()
        Panel.layout = awt.BorderLayout()
        Panel.border = swing.BorderFactory.createTitledBorder("Payload Encoder")
        self.text = swing.JTextField( actionPerformed = self.encodePayload );
        Panel.add(self.text, Panel.layout.PAGE_START);
        
        self.textArea = swing.JTextArea()
        scrollPane = swing.JScrollPane(self.textArea)
        
        Panel.add(scrollPane, Panel.layout.CENTER)
        
        Panel1 = swing.JPanel()
        Panel1.layout = awt.BorderLayout()
        Panel1.border = swing.BorderFactory.createTitledBorder("Payload Parser")
        self.text1 = swing.JTextField( actionPerformed = self.parsePayload );
        Panel1.add(self.text1, Panel1.layout.PAGE_START);
        
        self.textArea1 = swing.JTextArea()
        scrollPane1 = swing.JScrollPane(self.textArea1)
        
        Panel1.add(scrollPane1, Panel1.layout.CENTER)

        self.splitPane = swing.JSplitPane(swing.JSplitPane.VERTICAL_SPLIT);

        self.splitPane.setDividerLocation(250)
        self.splitPane.setLeftComponent(Panel);
        self.splitPane.setRightComponent(Panel1);

        self.parent.addTabPanel("Options", self.splitPane)




We can now build the methods that are called by the textfields and take input, 'encodePayload' and 'parsePayload'. Since burp already has an encoder, there's no real reason to have our own except for ease while parsing payloads... but the real time saver here is the payload parser. Inside of our 'encodePayload' we append different encodings of the input to the text area, URL, Double URL, Base64, HTML, etc... Someone can now simply take this and add any new encoding they would like, or let us know what you would like and we can update it. In our 'parsePayload' method we start by crawling recursively through 'lib/payloads/' and finding all .txt files. We then go line by line in each file and print out any line that does not include the users supplied input. The idea is that if you're in a situation where you're testing a parameter and single quote and semicolon are sanitized, but other characters get through fine... you can now parse your list of payloads for anything that you can potentially use. We recommend starting by populating it with something like fuzzdb.



    def encodePayload(self, event):
        self.textArea.setText("")
        self.textArea.append("URL Encoded: " + self.urlencode(self.text.getText()) + "\n")
        self.textArea.append("URL Encoded(full): " + self.urlencodefull(self.text.getText()) + "\n")
        self.textArea.append("Double URL Encoded: " + self.doubleurlencode(self.text.getText()) + "\n")
        self.textArea.append("Double URL Encoded(full): " + self.doubleurlencodefull(self.text.getText()) + "\n")
        self.textArea.append("Base64: " + self.base64encode(self.text.getText()) + "\n")
        self.textArea.append("HTML: " + self.htmlencode(self.text.getText()) + "\n")
        
    def parsePayload(self, event):
        self.textArea1.setText("")
        if len(self.text1.getText()) > 0:
            var =  "[" + self.text1.getText() + "]"
            for r,d,f in os.walk("lib/payloads/"):
                for files in f:
                    if files.endswith(".txt"):
                        path = os.path.join(r,files)
                        payloads = open(path, 'r')
                        self.textArea1.append("\n\n=== " + path + " ===\n\n")
                        for line in payloads:
                            if not re.findall(var, line):
                                self.textArea1.append(line)

    def urlencode(self, payload):
        return urllib.quote_plus(payload)

    def urlencodefull(self, payload):
        new = payload
        payload = ""
        for i in new:
            payload += "%" + str(hex(ord(i)))[2:]
        return payload
                
    def doubleurlencode(self, payload):
        payload = self.urlencode(payload)
        return re.sub('%', '%25', payload)
        
    def doubleurlencodefull(self, payload):
        payload = self.urlencodefull(payload)
        return re.sub('%', '%25', payload)

        
    def base64encode(self, payload):
        return base64.urlsafe_b64encode(payload)
        
    def htmlencode(self, payload):
        new = payload
        payload = ""
        for i in new:
            payload += "&#x" + str(hex(ord(i)))[2:] + ";"
        return payload  



There you have it, quickly building an extension with GUI functionality.

Extension Screenshot:


Extension Code:


from Extension import Extension
import javax.swing as swing
import java.awt as awt
import java.net as net
import urllib
import base64
import re
import os
import imp
import inspect

class PayloadEncoder(Extension):
    INFO = {
            'Name'      :   'Payload Encoder',
            'Usage'     :   'This extension will help encode and parse out which payloads you will be able to use by stripping out sanitized characters.',
            'Author'    :   'James Lester, Joseph Tartaro'
    }

    def finishedLaunching(self):
        for key in ["Name", "Usage", "Author"]:
            self.printLogTab("%s: %s\n" % (key, self.INFO[key]))
        self.printLogTab("---\n\n")
        PayloadEncoderMain(self)

class PayloadEncoderMain(object):

    def __init__(self, parent):
        self.parent = parent
        
        Panel = swing.JPanel()
        Panel.layout = awt.BorderLayout()
        Panel.border = swing.BorderFactory.createTitledBorder("Payload Encoder")
        self.text = swing.JTextField( actionPerformed = self.encodePayload );
        Panel.add(self.text, Panel.layout.PAGE_START);
        
        self.textArea = swing.JTextArea()
        scrollPane = swing.JScrollPane(self.textArea)
        
        Panel.add(scrollPane, Panel.layout.CENTER)
        
        Panel1 = swing.JPanel()
        Panel1.layout = awt.BorderLayout()
        Panel1.border = swing.BorderFactory.createTitledBorder("Payload Parser")
        self.text1 = swing.JTextField( actionPerformed = self.parsePayload );
        Panel1.add(self.text1, Panel1.layout.PAGE_START);
        
        self.textArea1 = swing.JTextArea()
        scrollPane1 = swing.JScrollPane(self.textArea1)
        
        Panel1.add(scrollPane1, Panel1.layout.CENTER)

        self.splitPane = swing.JSplitPane(swing.JSplitPane.VERTICAL_SPLIT);

        self.splitPane.setDividerLocation(250)
        self.splitPane.setLeftComponent(Panel);
        self.splitPane.setRightComponent(Panel1);

        self.parent.addTabPanel("Options", self.splitPane)
#(\/)(*;;;;*)(\/) whoop! whoop! whoop! whoop!
#Should add more...
    def encodePayload(self, event):
        self.textArea.setText("")
        self.textArea.append("URL Encoded: " + self.urlencode(self.text.getText()) + "\n")
        self.textArea.append("URL Encoded(full): " + self.urlencodefull(self.text.getText()) + "\n")
        self.textArea.append("Double URL Encoded: " + self.doubleurlencode(self.text.getText()) + "\n")
        self.textArea.append("Double URL Encoded(full): " + self.doubleurlencodefull(self.text.getText()) + "\n")
        self.textArea.append("Base64: " + self.base64encode(self.text.getText()) + "\n")
        self.textArea.append("HTML: " + self.htmlencode(self.text.getText()) + "\n")
        
    def parsePayload(self, event):
        self.textArea1.setText("")
        if len(self.text1.getText()) > 0:
            var =  "[" + self.text1.getText() + "]"
            for r,d,f in os.walk("lib/payloads/"):
                for files in f:
                    if files.endswith(".txt"):
                        path = os.path.join(r,files)
                        payloads = open(path, 'r')
                        self.textArea1.append("\n\n=== " + path + " ===\n\n")
                        for line in payloads:
                            if not re.findall(var, line):
                                self.textArea1.append(line)

    def urlencode(self, payload):
        return urllib.quote_plus(payload)

    def urlencodefull(self, payload):
        new = payload
        payload = ""
        for i in new:
            payload += "%" + str(hex(ord(i)))[2:]
        return payload
                
    def doubleurlencode(self, payload):
        payload = self.urlencode(payload)
        return re.sub('%', '%25', payload)
        
    def doubleurlencodefull(self, payload):
        payload = self.urlencodefull(payload)
        return re.sub('%', '%25', payload)

        
    def base64encode(self, payload):
        return base64.urlsafe_b64encode(payload)
        
    def htmlencode(self, payload):
        new = payload
        payload = ""
        for i in new:
            payload += "&#x" + str(hex(ord(i)))[2:] + ";"
        return payload  

No comments:

Post a Comment