Capture your Mobile Application's Network Logs from Automation - Part 2

Let's intercept network logs from automation framework

In Part-1 of this tutorial, we learned how to intercept HTTPS Requests using MITM Proxy.

In Part-2 will use a proxy Java Client (https://github.com/appium/mitmproxy-java) to intercept and capture requests from our automation framework.


What is mitmproxy java client?

mitmproxy-java starts a WebSocket server and a Python plugin for mitmproxy connects to it and sends requests over. The two communicate via binary messages.

Pre-Requisites

  • mitmproxy v9must be installed and runnable from the terminal. If the installation method is a prebuilt binary or homebrew, install websockets manually since those packages are missing the Python websockets module. Install via pip or from the source.

  • Python 3.6 and above, since we use the new async/await syntax in the mitmproxy plugin

  • pip3 install websockets

Maven:

<dependency>
  <groupId>io.appium</groupId>
  <artifactId>mitmproxy-java</artifactId>
  <version>2.0.2</version>
</dependency>

The latest version of code is still not available in mitm artifactory, please clone and build your own local jar to use this.

Once installed add MITMProxy until in our framework

Create class to add timestamp in captured data

import io.appium.mitmproxy.InterceptedMessage;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.Date;

/**
 * Stores intercepted message along with timestamp
 */
public class InterceptedMessages{
    @Accessors(chain = true)
    @Getter@Setter
    private Date timestamp;
    @Accessors(chain = true)
    @Getter@Setter
    private InterceptedMessage interceptedMessage;
}

Add handler to start/stop proxy

import com.project.automation.InterceptedMessages;
import io.appium.mitmproxy.InterceptedMessage;
import io.appium.mitmproxy.MitmproxyJava;
import lombok.Getter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * Man In The Middle Proxy Utility
 */
public class MITMProxy {
    @Getter
    private final List<InterceptedMessages> networkCalls = new ArrayList<>();

    private static MITMProxy proxyInstance = null;
    MitmproxyJava proxy;

    private MITMProxy(){
        startProxyListener();
    }
    public static MITMProxy getProxy()
    {
        if (proxyInstance == null)
            proxyInstance = new MITMProxy();
        return proxyInstance;
    }
    private void startProxyListener() {
        System.out.println("Starting Proxy Listener");
        List<String> extraMitmproxyParams = Arrays.asList(
                "--showhost",
                "<domain-name-filter>");
        int mitmproxyPort = 8090;
        this.proxy = new MitmproxyJava(
                getMitmDumpPath(), (InterceptedMessage m) -> {
            InterceptedMessages message = new InterceptedMessages()
                    .setTimestamp(new Date())
                    .setInterceptedMessage(m);
            networkCalls.add(message);
            return m;
        }, mitmproxyPort, extraMitmproxyParams);

        try {
            String processId = ProcessExecutor
                    .executeCommandSync("lsof -t -i:" + mitmproxyPort + " -sTCP:LISTEN")
                    .replaceAll("\\s", "");
            if(!processId.isEmpty())
                ProcessExecutor.executeCommandSync("kill -9 " + processId);
            this.proxy.start();
        } catch (IOException | TimeoutException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Proxy Listener Started");
    }

    private String getMitmDumpPath() {
            String result = ProcessExecutor
                    .executeCommandSync("whereis mitmdump");
            result = result.split("mitmdump: ")[1];
            result = result.substring(0, result.indexOf('\n'));
            result = result.split(" ")[0];
            System.out.println("mitmdump path is: " + result);
            return result;
    }


    public void stopProxyListener() {
        System.out.println("Stopping Proxy Listener");
        try {
            this.proxy.stop();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Proxy Listener Stopped");
    }
}

Start Proxy Using

MITMProxy.getProxy();

Fetch intercepted data using

networkLogMessage = MITMProxy.getProxy().getnetworkCalls()

Stop Proxy Using

MITMProxy.getProxy().stopProxyListener();