Cedric’s Cruft

  • Blog
Browse: Home > Tracing API calls in Burp with Frida

Tracing API calls in Burp with Frida

A few weeks ago I was performing a security test on a mobile banking application. The application was using a framework that provided additional obfuscation and encryption on top of the TLS connection it used to communicate with the remote server. I used Frida to intercept and dump the plaintext requests/responses before the encryption took place. I wanted to modify intercepted API calls and see how the remote server responded, but this required me to modify the Frida script each time.

Burp is really my tool of choice for (web) backend testing, and a mobile backend should not be that much different. I wanted to make Burp work together with Frida, and intercept/modify API calls in Burp. I did not go as far as creating a Burp plugin, but using a small script we can already get started with intercepting API calls. This spared me the trouble of modifying the frida-trace handler script each time I wanted to modify an API parameter.

Intercepting API requests with Burp does not require a lot of work:

  1. Set up a Burp listener (e.g. listen port 26080) redirecting traffic to an echo server (e.g. port 27080) in invisible proxy mode
  2. Have an echo server listening on port 27080 (which just echoes back the request)
  3. Use Frida to synchronously send an HTTP request to the Burp listener with as payload the API call data

Burp will receive the API request sent by Frida. The user can then modify the call in transit in Burp, which then forwards the data to the echo server. The echo server will simply reflect the (modified) request in the response, which is received back by the Frida code.

Set up Burp listener

Let’s start with setting up a Burp listener. Here, I’ve used listener port 26080 in invisible proxy mode:

Setting up a Burp listener redirecting to the echo server.

Python tracer code

I opted to extend (or rather monkey patch) the existing frida-trace code, in order to have the same flexibility of the tracing tool.

The following Python code extends the frida-trace code to work together with a server you forward the API call to. It does this by sending an HTTP request to the local Burp listener we created. You could also add metadata in the HTTP headers about the API call, or specify a URL path to distinguish between different API calls, which will be visible in Burp.

The current code might be version dependent: I don’t know what will change in future versions, though it currently works with Frida 8.2.2.

burp-tracer.py
Python
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
from frida import tracer
import requests
 
BURP_HOST = "localhost"
BURP_PORT = 26080
 
def frida_process_message(self, message, data, ui):
    handled = False
 
    if message['type'] == 'input':
        handled = True
    elif message['type'] == 'send':
        stanza = message['payload']
 
        if stanza['from'] == '/http':
            req = requests.request('FRIDA', 'http://%s:%d/' % (BURP_HOST, BURP_PORT), headers={'content-type':'text/plain'}, data=stanza['payload'])
            self._script.post({ 'type': 'input', 'payload': req.content })
            handled = True
 
    if not handled:
        self.__process_message(message, data, ui)
 
tracer.Tracer.__process_message = tracer.Tracer._process_message
tracer.Tracer._process_message = frida_process_message
 
if __name__ == '__main__':
    print("[x] To intercept in Burp, set up an invisible proxy listening on port %d, forwarding to the echo server." % BURP_PORT)
    tracer.main()

Trace handler script

The following example could be used to intercept read() calls in the onLeave function. This should be easily adaptable for your own usecase. We only need to forward/intercept the arguments that we want to tamper with.

I’ve implemented this by using the Frida send() API. This call is received by the Python code, which then responds back to the handler script. The script waits synchronously for a response (while we are performing modifications in Burp), and then executes the callback function.

__handlers__/libc_2.19.so/read.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
    onEnter: function (log, args, state) {
        log("read(" + "fd=" + args[0]+ ", buf=" + args[1]+ ", count=" + args[2] + ")");
        state.buf = args[1]
    },
 
    onLeave: function (log, retval, state) {
        send({from: '/http', payload: Memory.readUtf8String(state.buf)})
        var op = recv('input', function(value) { // callback function
            log("Forwarding mitm'ed content: " + value.payload)
            Memory.writeUtf8String(state.buf, value.payload)
        });
        op.wait();
    }
}

Echo server

The following script is a small implementation of an echo server that responds to “FRIDA” requests and echoes back the request payload. This could be extended as well with your own logic to modify requests on-the-fly (although you could just as well implement that directly in your Frida scripts).

echo.py
Python
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
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from optparse import OptionParser
 
ECHO_PORT = 27080
 
class RequestHandler(BaseHTTPRequestHandler):
 
    def do_FRIDA(self):
        request_path = self.path
 
        request_headers = self.headers
        content_length = request_headers.getheaders('content-length')
        length = int(content_length[0]) if content_length else 0
 
        self.send_response(200)
        self.end_headers()
 
        self.wfile.write(self.rfile.read(length))
 
def main():
    print('Listening on localhost:%d' % ECHO_PORT)
    server = HTTPServer(('', ECHO_PORT), RequestHandler)
    server.serve_forever()
 
if __name__ == "__main__":
    print("[x] Starting echo server on port %d" % ECHO_PORT)
    main()

Demo

Here’s the code in action:

Frida tracing with Burp interception

SANS Holiday Hack Challenge 2015 writeupAdding an external hard drive to the Unifi Cloud Key Gen2 Plus
cedric

Uncategorized

8 Jan 2017

Recent Posts
  • Adding an external hard drive to the Unifi Cloud Key Gen2 Plus
  • Tracing API calls in Burp with Frida
  • SANS Holiday Hack Challenge 2015 writeup
  • SECCON 2015 – Reverse engineering Android APK 2 – 400 writeup
  • WordPress up to version 4.1.2 Stored XSS vulnerability
Recent Comments
    Archives
    • February 2022
    • January 2017
    • January 2016
    • December 2015
    • April 2015
    • June 2014
    • December 2013
    © 2013-2022 Cedric Van Bockhaven