Hi! Today we will take a step-by-step tour on how to use Brida. We will see how to install and configure Brida and then how to use it during a real penetration test. For this purpose, we will use a iOS app developed by my colleague Mattia for our conference at Hack In The Box 2018 Amsterdam, but we will also see how to configure the plugin in an Android environment.

Brida links

Knowledge requirements

In order to be able to use Brida, you need:

basic knowledge of Burp Suite and web penetration testing

basic knowledge of Frida and instrumentation/hooking/dynamic analysis

Setting up your computer

Brida supports all operating systems. In order to use it you have to install:

1. Burp Suite

Download Burp Suite from PortSwigger’s officiale site. Brida can be used on both Burp Suite Professional and Burp Suite Community Edition.

2. Frida

First download and install the Python 2.7 binary and PIP for your operating system. Then you can easily install Frida with PIP:

pip install frida 1 pip install frida

3. Brida

Install Pyro4:

pip install Pyro4 1 pip install Pyro4 Download the latest version of the Brida plugin from the Brida repository Load the plugin from Burp: Open Burp -> Extender -> Extensions -> Add -> Choose BridaXX.jar file

And that’s all! Now it’s time to execute the Frida server on the mobile device!

Setting up your mobile phone

In order to be able to use Brida (and also Frida) you have to run frida-server on your mobile device with root privileges. Alternately, if you have the IPA of your iOS application or the APK of your Android application, you can patch the it adding the Frida library, in order to be able to use Frida also on non-jailbroken/non-rooted devices.

1. Setting up the mobile environment on a Jailbroken iOS device

Download the right version of frida server from the official repository (for example frida-server-XX.X.X-ios-arm64.xz if you have a 64-bit iOS device or frida-server-XX.X.X-ios-arm.xz otherwise) Copy the frida-server binary on the device using SCP Execute the frida-server binary on the device using SSH

The Frida client on your computer must be able to reach the Frida server on the mobile device. This task can be accomplished in two different ways:

Via USB, simply connecting your iOS device to your computer (not all OSes are supported)

Remotely. In this case you have to connect to your device using SSH, forwarding the local TCP port 27042. On Linux this task can be accomplished with the following command: “ssh -L 27042:127.0.0.1:27042 #IP_OF_IOS_DEVICE”. On Windows you can use Putty and configure the connection as follows:

Brida supports both local and remote connection to Frida, as we will see in the next sections. The Frida server can be also installed from a Cydia repository, but we prefer to manually download the binary and upload it on the device to have more control over the process.

2. Setting up the mobile environment on a rooted Android device

Download the right version of Frida server from the official repository (frida-server-XX.X.X-android-arm64.xz if you have a 64-bit ARM Android device, frida-server-XX.X.X-android-arm.xz if you have a 32-bit ARM Android device, frida-server-XX.X.X-android-x86_64.xz if you have a 64-bit x86 Android device and frida-server-XX.X.X-android-x86_64.xz if you have a 32-bit x86 Android device) Copy the frida-server binary on the device using ADB $ adb root $ adb push frida-server /data/local/tmp/ $ adb shell “chmod 755 /data/local/tmp/frida-server” Execute the frida-server binary on the device using ADB $ adb shell “/data/local/tmp/frida-server &”

In Android the best option is usually to use Frida in local mode, connecting the device to the computer with a USB cable.

3. Setting up the mobile environment on a non-Jailbroken iOS device (with Frida Gadget)

Additional requirements: the IPA of the application and a Mac computer (unfortunately to handle this situation you have to use a Mac!)

If you want to use Brida and Frida on a non-Jailbroken device you must have the IPA of the application. You need to patch the application with the Frida library (“Frida Gadget”) and then install the patched application on your device. The most comfortable way to accomplish this task is to use the great Objection tool, released by Leon Jacobs. You can find a detailed guide on how patch the application here.

After patching the application, you can install and execute it following this guide.

4. Setting up the mobile environment on a non-rooted Android device

At the moment, this mode is not recommended. You can use Objection to patch an Android binary but at the moment we haven’t tested Brida on a non-rooted Android device. We will update this guide when we have more information on this mode of operation.

Setting up Brida!

Now that you have configured your testing environment, it’s time to configure Brida itself. Let’g go to the “Configurations” tab of Brida.

Here, you have to input the following configuration parameters:

“Python binary path” is the path of the python binary. In most cases the default value is the correct one. “Pyro host” and “Pyro port” are the host and port on which the Pyro server (used by Brida to bridge Burp Suite and Frida) will be started. In most case you can leave the default values and Pyro server will be started on localhost:9999. “Frida JS file path” is the path of the Frida instrumentation JavaScript file, containing all Frida and Brida hooks and exports. To properly use Brida you have to insert the path of the JS file supplied with the Brida release (named “scriptBrida.js”) because this file contains Frida functions used by Brida itself. You can add your own Frida hooks and exports directly in this file. Application ID: this is the ID of the application that we are going to test on our mobile device. We will explain in a moment how to obtain this information from the device. “Frida Remote”/”Frida Local”: if you are using Frida USB mode of operation you have to select “Frida Local”; if you are using SSH port forwarding mode you have to choose “Frida Remote”.

Obtaining the Application ID of the target iOS application

Jailbroken device: on a Jaiblroken device you can use the “ipainstaller” tool to get application ID of all applications NOT installed from iTunes (command “ipainstaller -l”). You can use the Clutch tool to obtain application IDs of all applications installed from iTunes (command “Clutch -i”). Alternatively, you can extract that information from the IPA of the application itself (file: Payload/XXX.app/Info.plist)

on a Jaiblroken device you can use the “ipainstaller” tool to get application ID of all applications NOT installed from iTunes (command “ipainstaller -l”). You can use the Clutch tool to obtain application IDs of all applications installed from iTunes (command “Clutch -i”). Alternatively, you can extract that information from the IPA of the application itself (file: Payload/XXX.app/Info.plist) Non-jailbroken device: if you are using the Frida Gadget mode of operation (application patched with the Frida library) the application ID is always the same: “re.frida.Gadget”

Obtaining the Application ID of the target Android application

Rooted device: you can obtain the application ID of all installed applications using ADB with the following command: “adb shell pm list packages”. Alternatively, you can obtain the information from the Manifest file included in the application’s APK.

Let’s start the analysis

To execute our application with Brida we simply need to click first on “Start Server”, which starts Pyro4 server, and then “Spawn application” and our application will be spawned directly on our device!

In you are using Frida Gadget on a non-Jailbroken device the iter is slightly different, as described in the Objection Wiki. First you have to run your application in debug mode with ios-deploy (on the first run you have to run the command without the -m, in order to skip the installation of the app on the device):

ios-deploy --bundle Payload/APP.app -W -d -m 1 ios - deploy -- bundle Payload / APP . app - W - d - m

Once launched, the application is executed with LLVM but is stuck on start, waiting for a debugger. Then we can click on “Start server” and “Spawn application” on Brida and the application will be resumed and will be ready to be tested with Brida!

Just one note: if you are testing the application with Frida Gadget you can’t use the “Kill application” button of Brida to kill the application. You have to quit the application directly from the shell in which the ios-deploy command has been executed by typing the “quit” command. Then, if you want to run the application again, you have to repeat the described procedure.

Brida’s main menu

Brida’s main menu is on the right side, visible from all the tabs of Brida. The first entries of the menu are fixed, while the last part depends on the current tab.

Let’s see in detail how to use the fixed items of the menu. We will see the variable buttons when we will cover the different tabs of Brida:

“Start server”: starts the Pyro4 server. After Brida configuration, you have to start Pyro4 server in order to be able to use Brida.

“Kill server”: kills the Pyro4 server python process. You should click this button after you finish your analysis.

“Spawn application”: after starting Pyro4 server you can use this option to execute the target application on the mobile phone. The hooks defined in the JS file will be loaded and executed in the binary using Frida. From now on you can use all Frida and Brida functionalities.

“Kill application”: kills the application on the device. Note: if you kill and restart the application you have to add again all the hooks dynamically added from the Brida GUI.

“Reload JS”: you can use this option to reload the Frida JS file (for example after having edited it) without having to kill and re-spawn the application.

“Clear console”: clears Brida console.

Brida’s console

All output from Brida and from all Frida and Brida hooks is printed in a unified console, visible from all the tabs of Brida. We implemented this console in order to simplify mobile application analysis: with this console the tester can avoid switching tab repeatedly in order to see the output from the different Frida and Brida hooks and tools!

JS Editor

JS Editor tab allows to comfortably edit Frida JS instrumentation file (containing Brida default hooks/exports and the hooks/exports you add during your penetration test) directly from Burp Suite, without having to use a separate JS editor. The editor employs the great RSyntaxTextArea library of bobbylight, to provide also JS syntax highlighting. In order to load your JS Frida file, you have to click on “Load JS file” button (you already set the path of this file in the “Configurations” tab):

Then, when you want to save your job, you have only to click on the “Save JS file” button:

If you want to reload your Frida file (for example after having added a new Frida hook) without having to kill and re-spawn your application you can click on the “Reload JS” button in the menu on the right! 😉

Analyze binary

Now, let’s see one of the most important tab added in the new version of Brida: the “Analyze binary” tab. This tab shows a tree representation of the target binary, with a subtree containing imports and exports of all libraries used by the binary and a specific subtree (Java for Android and Objective-C for iOS) containing all the Java/Objective-C classes and methods of the binary.

To see this representation, you have to click on the “Load tree” button:

In this walkthrough we are using a iOS app so the first subtree, named “Objective-C”, contains all Objective-C classes of the application. If we double-click with the mouse on a class we obtain all the methods of that class (the same thing applies in an Android environment):

The second subtree, named “Modules”, contains all the libraries used by the target application. If we double-click on a library with the mouse we obtain a list of all imports and exports of that library:

At the bottom of the pane containing the subtree we have a “Search” form that can be used to search in all Objective-C classes and methods and in all the imports and exports of the libraries used by target application. Unfortunately, at the moment in Android it is only possible to search the imports and the exports of the libraries and not the Java classes and methods. This is due to a limitation of “API Resolver”, the component of Frida that implements this functionality. As an example, let’s see the results obtained searching for “decrypt” in our iOS test application:

Graphical inspection

From the “Analyze binary” tab, it is possible to graphically add inspection hooks to the Objective-C/Java methods of the target binary or to the exported functions of the loaded libraries. What do we mean for inspection hook? It is a block of code that is dynamically executed when the target method is executed on the device and that prints the arguments and the return value of that method.

Graphically inspecting a method is very simple with Brida. It is sufficient to click with the right button on an Objective-C/Java method or an exported function of a library and click “Inspect” or “Inspect with backtrace”. With the latter, when the target function is called in the binary the current backtrace (a list of the function calls that are currently active in the thread) will be printed in addition to the arguments and return value in the Brida console.

As an example, let’s intercept the “encryptRequest” function of the “Encryption” class. This is the output printed in the Brida console when the target function is called from the binary:

And this is the output if we use the “Inspect with backtrace!” functionality:

It is also possible to “Inspect” or “Inspect with backtrace” an entire Objective-C or Java class. In this case an inspection hook is added to every method of the target class. It is NOT possible to add an inspection hook to all the exported functions of a library (this is by choice, as too many hooks may crash the target application).

View current hooks

From the tab “Trap methods” it is possible to see all the functions currently hooked from the Analysis tab (your own hooks defined in the Frida JS file are not shown here).

From this tab you can detach ALL Frida hooks, by pressing the “Detach all” button (all hooks, including the ones defined in the Frida JS file). Unfortunately, it is not possible to detach hooks one-by-one due to a limitation of Frida itself.

Change return value

In the Analysis tab you can also add tamper hooks. If you click with the right button on an Objective-C/Java method or on an exported function of a library, you can select the option “Change return value” in order to add a tamper hook that dynamically changes the return value of that function every time it’s called by the target binary.

But, why have we implemented this functionality? Because it makes the bypass of some Security features very quick! Let’s consider for example a security feature implemented in the binary that stops the target application if it is running on a jaibroken/rooted device. After some reversing work we find a boolean function named “isJailbroken” that returns “true” if the device is jailbroken (and in this case the application stops for security reasons). In this situation we can simply click with the right button on the “isJailbroken” function, select “Change return value”, then “boolean” (or “int” or “ptr” depending on the particular function we are hooking) and select “False”. And the jailbreak check is bypassed without having to write a single line of code!

Execute method

Now, we are reversing a mobile iOS application (but it is exactly the same on Android!) that encrypts all the requests and the responses in the communications with the backend. After some reversing work, we find the functions responsible of the encryption/decryption tasks:

+ [Encryption encryptRequest:] + [Encryption decryptResponse:] 1 2 + [ Encryption encryptRequest : ] + [ Encryption decryptResponse : ]

Let’s try to use these functions directly from Burp Suite with Brida! For this task we can use the “Execute method” tab. The “Execute method” tab calls a Frida exported function that in turn will execute code directly on the mobile phone in the context of the target application.

First, we have to add to the Frida JS file two exported functions, one for decryption and one for encryption. The first one will take the cipher text as argument and then will kindly ask tthe mobile application to decrypt the cipher text in order to be able to return to us the clear-text value. The second one will do the opposite job. We can add the functions to the Frida JS file using Brida JS Editor pane:

Then we can call our exported functions directly from the “Execute method” tab of Brida! Let’s try to encrypt our clear-text value with the “encryptrequest” exported function:

And now, let’s do the opposite task with the “decryptresponse” exported function:

Context menu

Calling Frida exported functions from a specific tab is cool but not very useful besides for debugging purposes. The goal of Brida is to be able to handle penetration testing on complex mobile applications that implement strong security features, by using directly the mobile applications functions’ to overcome security features without having to reverse and re-implement them. In this case, the better approach is to code a custom plugin (as we will see in the next section) or, if we are only interested in manually testing the application without using the Burp Suite Scanner or the Burp Suite Intruder, we can use the Brida context menu options, supplied with Brida main plugin.

How do these options work? We have added to the context menu (the menu that opens in Burp Suite when you click with the right button) the following four entries:

Brida Custom 1

Brida Custom 2

Brida Custom 3

Brida Custom 4

The first two options appear when you click with the right button in an EDITABLE pane (for example the Request pane of the Repeater or the Intercept pane of the Proxy). The second two options appear when you click with the right button on an NON-EDITABLE pane (for example the Response pane of the Repeater or the Request or Response pane of all requests/responses saved in the HTTP history tab of the Proxy tool).

Starting from editable panes, if you select a portion of the text contained in an editable pane and click on “Brida Custom 1” (or “Brida Custom 2”), the Frida exported function “contextcustom1” (or “contextcustom2”) defined in supplied Frida JS file is executed. The selected portion of text highlighted in the editable pane is supplied to the function as argument. The value returned by the exported function will replace the selected portion of the editable pane.

If you use “Brida Custom 3” or “Brida Custom 4” from a non-editable pane the inner working is similar: the highlighted portion of the non-editable pane is supplied to the function as argument as before, but the return value is printed in a Java pop-up window (because the pane is non-editable).

Let’s see a practical example. This is one of the requests of the iOS application that we are testing:

As you can see the request and the response are encrypted, but thanks to our reversing job we found the functions used by the mobile application binary to handle encryption and decryption and we can now delegate the encryption and the decryption jobs to those functions via Brida:

+ [Encryption encryptRequest:] + [Encryption decryptResponse:] 1 2 + [ Encryption encryptRequest : ] + [ Encryption decryptResponse : ]

We will use “Context Custom 1” for the encryption and “Context Custom 3” for the decryption. First, we have to fill the content of Frida exported function “contextcustom1” and “contextcustom3” in the Frida JS file. Let’s start with the “contextcustom1” exported function:

The red-highlighted part of the code is the same we saw in the “Execute method” section. We simply take a reference to the “encryptRequest:” method of the “Encryption” class and we execute this method supplying as input the value we want to encrypt. The green-highlighted part is necessary because Brida passes the highlighted portion of the request encoded as a HEX String. Why this choice? In order to be able to handle binary data! In fact, this functionality works also if we highlight raw binary data in Burp Suite. For the same reason Brida expects the response from the exported function encoded as HEX String as well. JavaScript functions used to encode and decode in HEX Strings are supplied in the Brida JS file and should not be reimplemented.

So, after having added these four lines of JavaScript code to the Frida exports, we can directly use the encryptRequest function of the binary from Burp Suite Repeater. Let’s try it:

Great! Our string has been encrypted using the binary function!

Now let’s see the Frida exported code that handles the decryption of the responses:

As you can see, the code is very similar to contextcustom1, but this time it decrypts the encrypted content instead of encrypting clear-text messages. For the same reason of contextcustom1 we have input supplied as HEX String and we must return output encoded in the same way.

And now, let’s try our decryption code:

When we invoke the “Brida Custom 3” entry of our menu a window pops-up, showing the result of the decryption routine (we need a pop-up because the response pane is a non-editable pane).

So, now we are able to manually pentest the backend of target mobile application quite comfortably.

Almost done… writing a custom plugin!

“Manually” and “quite” are the keywords of my last sentence. Thanks to the context menu options and to Brida bridge we are able to handle this kind of encryption with a minimum reversing and coding effort, compared to what would be necessary to handle these situations without Brida.

But we can make a step further… Wouldn’t it be better to be able to insert our attack vector in clear-text and receive responses in clear-text too as in the following screenshot?

We can code a simple Burp Suite plugin that uses Brida to handle encryption completely transparently, as shown in the previous image. In this situation we simply input our clear-text attack vectors and our plugin will transparently encrypt them before sending them to the server. And when we receive the encrypted responses, our plugin will transparently decrypt them before showing them in Burp Suite. With this plugin we can avoid every time to:

Insert an attack vector Highlight the inserted attack vector Select “Brida Custom 1” to encrypt it Click “Go” Highlight the response body Select “Brida Custom 2” to decrypt it

But we have another huge advantage in coding a custom plugin that handle encryption transparently. If the encryption is handled transparently we can also use all the automatic tools of Burp Suite, like the Intruder and the Scanner! In fact, in this situation the Scanner will insert a clear-text attack vector in the request and will obtain a clear-text response that it can parse to understand if the attack vector succeeded in or not!

So, let’s see how to write a very simple Burp Suite plugin that uses Brida to transparently handle the encryption and the decryption of requests and responses. First, we can generate the code necessary to use Brida in our custom plugin directly using Brida itself. Let’s go to the “Generate stubs” tab of Brida and let’s click on “Java Stub” to generate code for our Java plugin or on “Python Stub” to generate code for our Python plugin:

Now you have to copy the generated code in your own plugin in order to be able to call directly mobile functions in your plugin using Frida, thanks to the bridge created by Brida. In this code you have to replace:

“METHOD_NAME”, highlighted in green, with the name of the Frida exported function that you want to use

“METHOD_ARG_1”, “METHOD_ARG_2”, …, highlighted in blue, with the arguments (if any) of the Frida exported function that you want to use

And that’s our plugin that transparently handles encryption/decryption in Repeater, Intruder and Scanner:

Burp Custom Plugin with Brida package burp; import java.io.PrintWriter; import java.util.Arrays; import org.apache.commons.lang3.ArrayUtils; import net.razorvine.pyro.PyroProxy; import net.razorvine.pyro.PyroURI; public class BurpExtender implements IBurpExtender, IHttpListener { private PrintWriter stdout; private PrintWriter stderr; private IBurpExtenderCallbacks callbacks; private IExtensionHelpers helpers; public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { // Set the name of the extension callbacks.setExtensionName("Brida Demo Search Plugin"); // Initialize stdout and stderr (configurable from the Extension pane) stdout = new PrintWriter(callbacks.getStdout(), true); stderr = new PrintWriter(callbacks.getStderr(), true); // Save references to useful objects this.callbacks = callbacks; this.helpers = callbacks.getHelpers(); // Register ourselves as an HttpListener, in this way all requests and responses will be forwarded to us callbacks.registerHttpListener(this); } public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) { // Process only Repeater, Scanner and Intruder requests if(toolFlag == IBurpExtenderCallbacks.TOOL_SCANNER || toolFlag == IBurpExtenderCallbacks.TOOL_REPEATER || toolFlag == IBurpExtenderCallbacks.TOOL_INTRUDER) { // Modify "test" parameter of Repeater requests if(messageIsRequest) { // Get request bytes byte[] request = messageInfo.getRequest(); // Get a IRequestInfo object, useful to work with the request IRequestInfo requestInfo = helpers.analyzeRequest(request); // Get "test" parameter IParameter contentParameter = helpers.getRequestParameter(request, "content"); if(contentParameter != null) { String urlDecodedContentParameterValue = helpers.urlDecode(contentParameter.getValue()); String ret = ""; // Ask Brida to encrypt our attack vector String pyroUrl = "PYRO:BridaServicePyro@localhost:9999"; try { PyroProxy pp = new PyroProxy(new PyroURI(pyroUrl)); ret = (String)pp.call("callexportfunction","encryptrequest",new String[]{urlDecodedContentParameterValue}); pp.close(); } catch(Exception e) { stderr.println(e.toString()); StackTraceElement[] exceptionElements = e.getStackTrace(); for(int i=0; i< exceptionElements.length; i++) { stderr.println(exceptionElements[i].toString()); } } // Create the new parameter IParameter newTestParameter = helpers.buildParameter(contentParameter.getName(), helpers.urlEncode(ret), contentParameter.getType()); // Create the new request with the updated parameter byte[] newRequest = helpers.updateParameter(request, newTestParameter); // Update the messageInfo object with the modified request (otherwise the request remains the old one) messageInfo.setRequest(newRequest); } // Response } else { // Get request bytes in order to check if the request contain "content" parameter byte[] request = messageInfo.getRequest(); IRequestInfo requestInfo = helpers.analyzeRequest(request); IParameter contentParameter = helpers.getRequestParameter(request, "content"); if(contentParameter != null) { // Get response bytes byte[] response = messageInfo.getResponse(); // Get a IResponseInfo object, useful to work with the request IResponseInfo responseInfo = helpers.analyzeResponse(response); // Get the offset of the body int bodyOffset = responseInfo.getBodyOffset(); // Get the body (byte array and String) byte[] body = Arrays.copyOfRange(response, bodyOffset, response.length); String bodyString = helpers.bytesToString(body); String ret = ""; // Ask Brida to decrypt the response String pyroUrl = "PYRO:BridaServicePyro@localhost:9999"; try { PyroProxy pp = new PyroProxy(new PyroURI(pyroUrl)); ret = (String)pp.call("callexportfunction","decryptresponse",new String[]{bodyString}); pp.close(); } catch(Exception e) { stderr.println(e.toString()); StackTraceElement[] exceptionElements = e.getStackTrace(); for(int i=0; i< exceptionElements.length; i++) { stderr.println(exceptionElements[i].toString()); } } // Update the messageInfo object with the modified request (otherwise the request remains the old one) byte[] newResponse = ArrayUtils.addAll(Arrays.copyOfRange(response, 0, bodyOffset),ret.getBytes()); messageInfo.setResponse(newResponse); } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 package burp ; import java . io . PrintWriter ; import java . util . Arrays ; import org . apache . commons . lang3 . ArrayUtils ; import net . razorvine . pyro . PyroProxy ; import net . razorvine . pyro . PyroURI ; public class BurpExtender implements IBurpExtender , IHttpListener { private PrintWriter stdout ; private PrintWriter stderr ; private IBurpExtenderCallbacks callbacks ; private IExtensionHelpers helpers ; public void registerExtenderCallbacks ( IBurpExtenderCallbacks callbacks ) { // Set the name of the extension callbacks . setExtensionName ( "Brida Demo Search Plugin" ) ; // Initialize stdout and stderr (configurable from the Extension pane) stdout = new PrintWriter ( callbacks . getStdout ( ) , true ) ; stderr = new PrintWriter ( callbacks . getStderr ( ) , true ) ; // Save references to useful objects this . callbacks = callbacks ; this . helpers = callbacks . getHelpers ( ) ; // Register ourselves as an HttpListener, in this way all requests and responses will be forwarded to us callbacks . registerHttpListener ( this ) ; } public void processHttpMessage ( int toolFlag , boolean messageIsRequest , IHttpRequestResponse messageInfo ) { // Process only Repeater, Scanner and Intruder requests if ( toolFlag == IBurpExtenderCallbacks . TOOL_SCANNER | | toolFlag == IBurpExtenderCallbacks . TOOL_REPEATER | | toolFlag == IBurpExtenderCallbacks . TOOL_INTRUDER ) { // Modify "test" parameter of Repeater requests if ( messageIsRequest ) { // Get request bytes byte [ ] request = messageInfo . getRequest ( ) ; // Get a IRequestInfo object, useful to work with the request IRequestInfo requestInfo = helpers . analyzeRequest ( request ) ; // Get "test" parameter IParameter contentParameter = helpers . getRequestParameter ( request , "content" ) ; if ( contentParameter ! = null ) { String urlDecodedContentParameterValue = helpers . urlDecode ( contentParameter . getValue ( ) ) ; String ret = "" ; // Ask Brida to encrypt our attack vector String pyroUrl = "PYRO:BridaServicePyro@localhost:9999" ; try { PyroProxy pp = new PyroProxy ( new PyroURI ( pyroUrl ) ) ; ret = ( String ) pp . call ( "callexportfunction" , "encryptrequest" , new String [ ] { urlDecodedContentParameterValue } ) ; pp . close ( ) ; } catch ( Exception e ) { stderr . println ( e . toString ( ) ) ; StackTraceElement [ ] exceptionElements = e . getStackTrace ( ) ; for ( int i = 0 ; i < exceptionElements . length ; i ++ ) { stderr . println ( exceptionElements [ i ] . toString ( ) ) ; } } // Create the new parameter IParameter newTestParameter = helpers . buildParameter ( contentParameter . getName ( ) , helpers . urlEncode ( ret ) , contentParameter . getType ( ) ) ; // Create the new request with the updated parameter byte [ ] newRequest = helpers . updateParameter ( request , newTestParameter ) ; // Update the messageInfo object with the modified request (otherwise the request remains the old one) messageInfo . setRequest ( newRequest ) ; } // Response } else { // Get request bytes in order to check if the request contain "content" parameter byte [ ] request = messageInfo . getRequest ( ) ; IRequestInfo requestInfo = helpers . analyzeRequest ( request ) ; IParameter contentParameter = helpers . getRequestParameter ( request , "content" ) ; if ( contentParameter ! = null ) { // Get response bytes byte [ ] response = messageInfo . getResponse ( ) ; // Get a IResponseInfo object, useful to work with the request IResponseInfo responseInfo = helpers . analyzeResponse ( response ) ; // Get the offset of the body int bodyOffset = responseInfo . getBodyOffset ( ) ; // Get the body (byte array and String) byte [ ] body = Arrays . copyOfRange ( response , bodyOffset , response . length ) ; String bodyString = helpers . bytesToString ( body ) ; String ret = "" ; // Ask Brida to decrypt the response String pyroUrl = "PYRO:BridaServicePyro@localhost:9999" ; try { PyroProxy pp = new PyroProxy ( new PyroURI ( pyroUrl ) ) ; ret = ( String ) pp . call ( "callexportfunction" , "decryptresponse" , new String [ ] { bodyString } ) ; pp . close ( ) ; } catch ( Exception e ) { stderr . println ( e . toString ( ) ) ; StackTraceElement [ ] exceptionElements = e . getStackTrace ( ) ; for ( int i = 0 ; i < exceptionElements . length ; i ++ ) { stderr . println ( exceptionElements [ i ] . toString ( ) ) ; } } // Update the messageInfo object with the modified request (otherwise the request remains the old one) byte [ ] newResponse = ArrayUtils . addAll ( Arrays . copyOfRange ( response , 0 , bodyOffset ) , ret . getBytes ( ) ) ; messageInfo . setResponse ( newResponse ) ; } } } } }

As you can see, our simple plugin transparently handles encryption without having to write a single line of encryption or decryption code!

Remember that you have to use both plugins, your custom plugin and Brida itself if you choose this mode of operation because your custom plugin uses the bridge that is loaded by Brida main plugin.

You can now load your new plugin and easily discover and exploit backend issues:

Game over! And this simple plugin is only an example of what you can accomplish with Brida. Thanks to Burp Suite Extender you can extend almost any Burp Suite component and thanks to Brida you can use mobile application functions inside your custom plugin.

And we have finally reached the conclusion of this endless blog post! 😀 Enjoy! 😀