[ Beneath the Waves ]

Multipurpose Man-in-the-Middle VM

article by Ben Lincoln


This guide describes the process I used to build the system used for the majority of the research in the Motorola Is Listening article. It's designed to be useful in a variety of situations - not just listening in on mobile device traffic.

This set of steps is provieded in lieu of a prebuilt VM, because I don't have time to make sure that the source code is included for every component, and I don't want to be responsible for a GPL or other open-source license violation.

Table of contents

  1. Goals
  2. Acknowledgements
  3. VM build and prerequisites
  4. Certificate authority setup
  5. Mallory setup
  6. Firefox setup
  7. OWASP ZAP setup
  8. Burp Suite setup
  9. Apache httpd setup
  10. XMPPPeek setup
  11. Suggestions
  12. Options for traffic routing
  13. Regarding the examples below
  14. Example: using OWASP ZAP and XMPPPeek to monitor traffic from Motorola phones
  15. Example: using Mallory
  16. Example: using socat to perform a basic SSL man-in-the-middle attack
  17. Troubleshooting


What you should end up with is a Linux VM running in VirtualBox that can intercept traffic between any two of a variety of interfaces.

One of those interfaces will generally be an internet- or intranet-facing NIC or a USB wireless adapter connected using pass-through to the guest OS.

The other interface could be a bridged interface (as long as it's not connected to a regular network), a USB ethernet NIC also connected using USB pass-through (this is how I usually set mine up), a virtual AP created in hostapd, etc.

The tools that will be set up at the end of the process include:


This document is based in part on the work of numerous other authors. In addition to the tool authors themselves, some steps are based on one or more of the following external articles. I would suggest reading them, because they provide a wealth of additional information that is not included here.

VM build and prerequisites

I am not actually a huge Ubuntu fan[1], but because a lot of security tools are built with Ubuntu in mind (particularly Mallory), this system will be Ubuntu-based. Don't worry, it will look more like regular Debian, or security-tool-customized versions of Ubuntu (Samurai WTF, Backtrack, etc.) by the end.

There is an assumption made here that you've used a modern Linux system and built at least a basic VM in VirtualBox before. If not, you will need to refer to documentation elsewhere as necessary.

  1. Go to the Ubuntu desktop download site and choose the 12.04 LTS release. This guide was tested with the 64-bit version, and has not been tested with the 32-bit version. It is very important to use the desktop version, because Ubuntu Server is missing a bunch of components that will be necessary later. I'm sure you could make it work with Server, but if you want to go that route, you're on your own.
  2. If you don't already have it installed, download and install VirtualBox. You can probably make this work on another platform (e.g. VMWare), but VirtualBox is the one I used because it's free and works really well. Make sure you have the Extension Pack for your version of VirtualBox as well.
  3. Once the Ubuntu ISO finishes downloading, start up VirtualBox.
  4. Make a new VM. I named mine We Listen in honour of the folks at Motorola, but you can call yours whatever you like.
  5. I gave mine two virtual CPUs, 2GB of RAM, and a dynamically-allocated 40GB virtual disk image. You can probably get away with less, but I didn't want to run into performance issues or run out of disk space when doing captures.
  6. You'll need at least one virtual NIC that can be configured as a bridged NIC. It doesn't need to be set up as bridged until later - if it works better to leave it as NAT until then, that's fine.
  7. Mount the Ubuntu ISO in the virtual CD/DVD drive, boot the VM, and proceed through the install process. Nothing here should have a major impact on the final result, so feel free to customize the name, user account, filesystem, etc., as you like. I generally kept things at the default setting other than system and user name.
  8. After the installation completes, open up a terminal window. If you haven't used Unity before, here's one way to get to a terminal window. This is the only time you'll need to do this - Unity will be disabled in a few steps. There are screenshots of this further down the page.
    1. Click the Ubuntu button.
    2. Click the ruler/pencil/pen button at the bottom of the screen.
    3. Click Installed.
    4. Scroll down to Terminal, and click on that.
  9. Run these commands:


    sudo apt-get update

    sudo apt-get upgrade

    sudo apt-get install gnome-shell autoconf automake bison build-essential flex gcc g++ libtool m4 make libreadline-dev libreadline6 libreadline6-dev socat hostapd mercurial python-pyasn1 python-netfilter libnetfilter-conntrack-dev python-dev python-setuptools libnetfilter-conntrack3-dbg python-paramiko python-imaging qt-sdk python-qt4 dnsmasq phonon phonon-backend-gstreamer linux-source kernel-package libncurses-dev ncurses-dev vim fonts-ipafont-gothic fonts-ipafont-mincho ttf-telugu-fonts ttf-oriya-fonts ttf-kannada-fonts ttf-bengali-fonts apache2 wireshark bridge-utils openjdk-7-jre linux-headers-$(uname -r)

  10. After 1+GB of download/install completes, reboot the VM.
  11. Before you log on, click the Ubuntu button and select Gnome Classic. This will prevent you from having to deal with Unity ever again, at least as the current user.
  12. Install the VirtualBox Guest Additions using the normal process. All of the prerequisites should have been installed as part of the giant apt-get install command, above.
  13. Once the additions are installed, but before rebooting, perform the following steps:
    1. Edit the file /etc/sysctl.conf (using e.g. (nano, vim, or gedit).
    2. Uncomment the line which reads:



    3. Save the file and exit.
  14. If you wish, perform the following additional, optional steps to give yourself unlimited scrollback and make the terminal colours more printout-friendly:
    1. In the Terminal window, open the Edit menu and choose Profile preferences.
    2. Switch to the Colors tab.
    3. Uncheck Use colors from system theme.
    4. Select Black on white from the Built-in schemes menu.
    5. Switch to the Scrolling tab.
    6. Check the Unlimited box, then click Close.
  15. If you wish, run the following command to reset the minimalist/popup scrollbars in Ubuntu to something that's more helpful when used frequently:


    gsettings set org.gnome.desktop.interface ubuntu-overlay-scrollbars false

  16. Perform any other basic OS configuration you would typically do. For example, I have a standard script that mounts several VirtualBox shared folders for easy access between guest VMs as well as the host OS. I drop this in /etc/init.d/ and configure it to run at the appropriate times with sudo update-rc.d mountshares.sh defaults.
  17. Reboot the system again.
  18. Run the following commands to install a required Python library and Mallory (note: you really do have to run the Mallory install script twice):


    sudo easy_install pynetfilter_conntrack

    cd ~

    hg clone http://bitbucket.org/IntrepidusGroup/mallory

    cd mallory

    sudo ./mallory_install.sh

    sudo ./mallory_install.sh

Navigating to the Terminal in Unity
[ Steps 1 and 2 ]
Steps 1 and 2
[ Step 3 ]
Step 3



Certificate authority setup

If you work on more than one or two SSL-interception projects, it can get pretty tedious importing the root CA certs for various tools onto the devices you test with. So the next phase of this build process is to set up a certificate authority, which will then be used to sign most other certificates generated by the system. This means you should only have to import between one and three certificates into your test client devices' trusted CA stores, rather than one for literally every tool/MitM setup.

  1. Edit the file /etc/ssl/openssl.cnf using the editor of your choice (nano, vim, gedit, etc.), and make the following changes:
    In the [ CA_default ] section:
    1. Change default_days to 7300, which should make any manually-issued certificates good for twenty years. You would almost certainly never want to do this with a production CA, but for MitM it means you shouldn't have to worry about them expiring in the middle of your testing.
    2. Change default_crl_days to 7300. This should prevent clients from checking the certificate revocation list for issued certificates more frequently than every twenty years. Again, you wouldn't want to do this with a production CA, but since your CRL almost certainly won't be accessible to client systems, it will help prevent lag/timeouts when those clients try to check the CRL and fail.

    In the [ policy_match ] section:
    1. Change everything to optional except commonName. This will allow your CA to sign certificates whose organization name and other attributes don't match that of the CA cert itself, just like the real CAs (VeriSign, GoDaddy, etc.).

    In the [ req ] section:
    1. Change default_bits to 2048. This will cause issued certificates to be compliant with newer security measures that require a minimum of 2048 bits. The default of 1024 will result in errors in e.g. newer versions of Java.
    2. Customize the other settings for your location, or for the most common location you plan to issue certificates for. For example, you can make the country code US so that it will be the default, rather than having to type it for every certificate to override the default of AU.
  2. Save the file and exit.
  3. Run the following commands:


    cd ~

    mkdir ca

    cd ca

    /usr/lib/ssl/misc/CA.pl -newca

  4. Press enter.
  5. Enter a passphrase for the PEM file containing the CA private key. You'll be stripping this out shortly, so feel free to use something terrible and offensively-insecure like 12345, or NYSE123+, where NYSE is the stock-trading symbol of the company you work for (MSFT, LMT, FLIR, etc.)
  6. When prompted for the properties of the CA certificate, my recommendation is that you attempt to mimic a genuine commercial CA root certificate. These properties shouldn't be important, but you never know when you'll run across software written by a developer who tried to roll their own faux-certificate-pinning code that checks to make sure that the human-readable properties of the certificate match some "known-good" values. If you want to go this route, visit your favourite SSL-enabled website, view the certificate, and make a note of the root CA properties.
    This does have the downside of making it harder to find your certificate when you go to remove it from the devices at the end of your testing, so you could use something easier to find instead, like National Security Agency for the organization name, Fort Meade for the city, and Maryland for the state/province.
  7. Run the following commands to rename the passphrase-protected private key (in case you need it later), and generate a horribly-insecure non-passphrase-protected version, which is required for most of the ways it will be used later. You'll be prompted for the passphrase when running the second command - it's the same one you entered above when creating the CA.


    mv ~/ca/demoCA/private/cakey.pem ~/ca/demoCA/private/cakey.pem-01

    openssl rsa -in ~/ca/demoCA/private/cakey.pem-01 -out ~/ca/demoCA/private/cakey.pem

    WARNING: you just removed the passphrase protection from the CA certificate's private key. Do not do this for actual production CA certificates unless you really know what you're doing!

For examples of how to manually generate one-off certificates signed by the CA, see the XMPPPeek and socat sections, below.

Mallory setup

  1. Back up the default Mallory CA cert/key and insert the ones generated above, by running the following commands:


    sudo mv ~/mallory/current/src/ca/ca.cer ~/mallory/current/src/ca/ca.cer-01

    sudo mv ~/mallory/current/src/ca/ca.key ~/mallory/current/src/ca/ca.key-01

    sudo cp ~/ca/demoCA/cacert.pem ~/mallory/current/src/ca/ca.cer

    sudo cp ~/ca/demoCA/private/cakey.pem ~/mallory/current/src/ca/ca.key

  2. Disable the three built-in HTTP plugins, which will cause all sorts of problems for most traffic, by editing the file ~/mallory/current/src/plugin_managers/http_plugin_manager.py using your favourite editor.
    Comment out these three lines (add a # at the beginning of the line):


    plugs.append(SessionHijack ())



    Save the file and exit.

Firefox setup

Firefox can be an extremely-useful tool when evaluating web applications, thanks to add-ons like Firebug, NoScript, FoxyProxy, and the various user-agent-spoofing components. As an added bonus, it doesn't send every keystroke that you type in the "address" bar to Google. Such use is outside the scope of this document. These steps are mostly a reminder to turn off its silent background-activity options so that your intercepting proxy logs stay as clean as possible.

  1. Launch Firefox (Applications -> Internet -> Firefox.
  2. [optional] Go to about:config and set browser.urlbar.trimURLs to false. This will disable the poorly-thought-out "feature" in which Firefox doesn't explicitly tell you if a URL is HTTP or not.
  3. Open the Firefox preferences (Edit -> Preferences).
  4. Switch to the Security tab.
  5. Uncheck Block reported attack sites, Block reported web forgeries, and Remember passwords for sites.
  6. Switch to the Advanced tab.
  7. Switch to the Data Choices sub-tab.
  8. Uncheck Enable Firefox Health Report and Enable Crash Reporter.
  9. Switch to the Update tab. Disable all automatic updates.
  10. Close out of Firefox preferences.


  1. In a web browser (I used Firefox), open the URL http://code.google.com/p/zaproxy/downloads/list.
  2. Download the current ZAP package (e.g. ZAP_2.1.0_Linux.tar.gz).
  3. Switch to a terminal, move the tarball to your home directory, unpack it, and then run ZAP for the first time. For example, Firefox places downloads in ~/Downloads by default, so the series of commands (for the 2.1.0 release of ZAP) would be:


    cd ~

    mv Downloads/ZAP_2.1.0_Linux.tar.gz ~/

    tar -xzvf ZAP_2.1.0_Linux.tar.gz

    cd ZAP_2.1.0_Linux


  4. If you receive an error indicating that ZAP requires version 1.7 or later of the JRE, execute the following command to work around a bug in the OpenJDK:


    sudo update-java-alternatives --set java-1.7.0-openjdk-amd64

    You should then be able to run the ./zap.sh command successfully.
  5. Choose to generate an SSL certificate - as of this writing, ZAP doesn't provide a straightforward way to import your own CA cert and key.
  6. Click the Save button to export the CA SSL certificate to your home directory (e.g. as owasp_zap_root_ca.cer).
  7. Since you are going to be using ZAP to intercept client traffic, you'll need to configure it to listen on an interface other than the loopback (
    1. In the Options window (Tools -> Options), switch to the Local proxy tab.
    2. In the Address field, enter the IP address of an interface which client traffic will be able to be routed. This will typically be the IP address of the internet-facing interface on the VM, because the client-facing interface may be configured for traffic-forwarding, in which case such traffic will never reach a port listening on that interface.
    3. In the Port field, make sure the value is either the default (8080), or some other port >= 1024, so that you don't have to run ZAP as root. I typically pick an unusual high port so that the listener doesn't conflict with other server components that I might install.
    4. Click OK.

    WARNING: you just set up an unauthenticated proxy service which is potentially accessible to other clients on the network. Make sure it is not exposed to untrusted devices, especially if you configure ZAP to proxy through an upstream server using credentials!
  8. Close out of ZAP.

Burp Suite setup

Since the purpose of this document is to describe a tool for intercepting communication (not necessarily modifying it), the Free version of Burp Suite is probably not going to be as useful as OWASP ZAP. However, it never hurts to have it installed. If you have a license for the Professional version, it has numerous capabilities that ZAP does not, so (again, assuming you have a license) installing it on this system would be ideal.

This section assumes you have at least some minimal experience with Burp. If you don't, and you're not feeling adventurous, you can skip to the next section.

Unsolicited plug: I think Burp is a really outstanding tool. If you are doing professional pen-testing or reverse-engineering of anything web-related, the $300/year/user price is well worth paying. It will do more, and generally do it better, than any other tool that I've used (even tools costing thousands of dollars). This is an opinion I've heard from numerous other security professionals, including SANS instructors. However, I recognize that many of the people reading this may not have the funds to purchase such a license, especially if they're doing hobby/outside-of-work testing like I was for the Motorola Is Listening article.

  1. In a web browser, visit the Burp Suite site. If you have a license for the Professional version, download that. Otherwise, download the Free version.
  2. Move the JAR file to a more appropriate location and then start Burp. E.g. if you downloaded the Free version of Burp 1.5 using Firefox, the series of commands would be:


    cd ~

    mkdir burp

    mv Downloads/burpsuite_free_v1.5.jar ~/burp/

    cd ~/burp

    java -jar burpsuite_free_v1.5.jar

  3. Perform any configuration you would typically do for Burp.
  4. Similarly to ZAP, in order to use Burp to view the traffic from client devices, you'll need to bind its proxy to an interface other than the loopback (, which is the default setting. Typically, you would want to use the IP address of the internet-facing interface, because the client-facing interface may be configured for traffic-forwarding and therefore Burp will never see it. If you are using the Professional version, you can configure it to listen on all available IPs and save yourself some hassle later.
    WARNING: you just set up an unauthenticated proxy service which is potentially accessible to other clients on the network. Make sure it is not exposed to untrusted devices, especially if you configure Burp to proxy through an upstream server using credentials!
  5. If you have a license for the Professional version, you can import the root CA and private key generated in the certificate authority section. In version 1.5.12, go to the Proxy tab, the Options sub-tab, the Proxy Listeners section of that sub-tab, and click on the CA certificate button.
  6. If you are using the Free version and wish to use Burp to intercept SSL traffic from client devices, you'll need to obtain the CA certificate that's built-into Burp, and to my knowledge there isn't an option in Burp itself to do this. Here are the steps I used:
    1. Set up your browser to proxy through Burp, and access at least one HTTPS URL.
    2. You will receive a certificate warning. Use the browser's functionality to view the cert.
    3. View the certificate chain, and export the root certificate (Portswigger CA) - highlighted in the screenshot - as ~/PortSwiggerCA.crt.
  7. Close out of Burp.
CA Certificates in Burp
[ Burp Free - CA cert [1/2] ]
Burp Free - CA cert [1/2]
[ Burp Free - CA cert [2/2] ]
Burp Free - CA cert [2/2]
[ Burp Pro - Import CA cert ]
Burp Pro - Import CA cert

The first two screenshots go with the "how to export the CA cert from the Free version of Burp" steps. The third shows the location of the button allowing you to import your own root CA cert and key in the Professional version.


Apache httpd setup

When performing the type of testing this system is intended to be used for, you'll frequently need a quick way to get content to the client devices you're testing with. Particularly in the case of iOS, Android, and other mobile devices, the manufacturers make this annoyingly hard to do other than if the content is accessible through a web server. As a result, that's exactly what you'll set up here - a minimal Apache httpd web server where you can drop files that the clients will need to access. As long as it's configured correctly, any client that can connect to the internet through your intercepting VM should also be able to access the files you host there.

This is particularly useful for the root CA and other SSL certificates, which will be copied to the HTTP-accessible directory as part of these instructions.

WARNING: you are setting up a web service on your interception system. As long as you remember to keep it updated with patches, this should not be a problem - the attack surface is very small. However, be aware that you are opening yourself up to possible compromise if you use this system to intercept traffic from hostile clients. It is advisable to frequently snapshot the VM in VirtualBox so that if this happens, you can revert to an uncompromised snapshot.

  1. Open the file /etc/apache2/ports.conf in your favourite editor. You will need to use sudo in order to obtain write access.
  2. Replace both occurrences of :80 with :62674 to avoid potential conflicts with other traffic/listeners you want to set up. You can use another port number if you like, as long as you keep it consistent throughout all of the steps that refer to port 62674.
  3. Save and exit.
  4. Open the file /etc/apache2/sites-available/default in your favourite editor. You will need to use sudo in order to obtain write access.
  5. Replace the single occurrence of :80 with :62674.
  6. Save and exit.
  7. Execute the following commands to create a directory structure for the certificates, and copy the necessary certificates into them. Note that .crt extensions are used here because I've found that that's the most reliable way of ensuring they open in the native certificate management utility on most/all client devices.


    sudo rm /var/www/index.html

    sudo mkdir /var/www/general

    sudo mkdir /var/www/zap

    sudo mkdir /var/www/burp

    sudo cp ~/ca/demoCA/cacert.pem /var/www/general/cacert.crt

    sudo cp ~/owasp_zap_root_ca.cer /var/www/zap/zap_ca.crt

    sudo cp ~/PortSwiggerCA.crt /var/www/burp/PortSwiggerCA.crt

  8. Reboot the system, or run sudo /etc/init.d/apache2 restart if you don't feel like rebooting.
Browsing to certificates hosted by httpd from a client device
[ Browing to certs ]
Browing to certs



XMPPPeek setup

  1. In your web browser, visit the XMPPPeek download page (XMPPPeek), and download the current version.
  2. Create a working directory for XMPPPeek, move the archive there, and unpack it. If you used Firefox for the download, the series of commands would be:


    cd ~

    mkdir xmpppeek

    mv Downloads/xmpppeek-0.1a.tar.gz ~/xmpppeek/

    cd xmpppeek

    tar -xzvf xmpppeek-0.1a.tar.gz

    chmod +x *.sh

    chmod +x *.py


If you are going to be coordinating logs captured on multiple systems, I strongly suggest making sure they are all synced to the same NTP source. For example, I tend to run Burp Suite on a Windows system, so I configure that system to sync to time.nist.gov, and then sync my Ubuntu traffic-interception system to the same source using this command:

sudo ntpdate time.nist.gov

This is especially important when trying to determine cause-and-effect during reverse-engineering. For example, if you are trying to pin down whether XMPP traffic is triggering a sync over HTTP/HTTPS, or whether the XMPP traffic is some sort of post-sync confirmation mechanism :).

The apt-get install command at the beginning of this document includes Wireshark. Using Wireshark is outside the scope of this article, but can be very useful for troubleshooting problems with your configuration as well as intercepting unencrypted traffic.

Also included is hostapd, which allows a Linux system with a wireless adapter to be configured as if it were a hardware wireless access point. If you can get this working, it should save you from having to lug around an actual AP.

Options for traffic routing

A VM configured in this way allows for numerous network configurations depending on the goals of the user, and is particularly flexible when the VM is running on a laptop or other portable device.

Some examples of what can be used as the internet-facing interface:

Some examples of what can be used as the client-facing interface:

Some combination of those options should allow most types of client traffic to be intercepted. I typically use a bridged network adapter or a USB wifi adapter as the internet-facing interface, and a USB ethernet NIC as the client-facing interface. I then connect an old wireless AP to the ethernet NIC, and it's that AP that clients connect to.

Remember that if you're using a virtual NIC for the internet-facing interface, it must be set up as bridged for some of the tools described in this article to work. If you configured it as NAT to download everything, remember to switch it to bridged before trying to intercept traffic using e.g. Mallory. If you're just using ZAP or Burp Suite, you can use a NAT interface for that purpose, but you still need a bridged interface for the client(s) to connect on.

Regarding the examples below

In the interest of keeping the examples concise and (hopefully) easier-to-follow, the following assumptions are made. If you are using a different tool or configuration, you will need to modify the steps accordingly.

Example: using OWASP ZAP and XMPPPeek to monitor traffic from Motorola phones

This example should let you replicate the results I obtained in the Motorola Is Listening article, as long as you use a phone that communicates with the Blur service.

WARNING: a friendly reminder, these instructions are not intended to be used to attack, scan, probe, or otherwise interfere with Motorola's Blur servers, or any other servers belonging to Motorola. They are only intended to allow lawful customers of Motorola devices to determine via passive data capture if any traffic is being sent from their device to Motorola, possibly without their knowledge or consent.

Phase 1: monitor HTTP/HTTPS traffic with ZAP

  1. Temporarily modify the ~/xmpppeek/startgateway.sh file to not intercept TCP port 5222. Open it in your favourite editor and comment out this line (add a # at the beginning of the line):


    iptables -t nat -A PREROUTING -i $lanInt -p tcp --dport 5222 -j DNAT --to-destination
    Save the file and exit.

  2. Run the following commands to set up dnsmasq on the client-facing interface, and enable traffic-forwarding from that interface to the internet-facing interface:


    cd ~/xmpppeek

    sudo ./startgateway.sh

  3. When prompted for the WAN interface, enter the name of the internet-facing interface (e.g. eth0).
  4. When prompted for the LAN interface, enter the name of the client-facing interface (e.g. eth1).
  5. Verify that client devices can obtain an address via DHCP (it should be on, unless you've edited the scripts), and that they can connect to the internet. If they can't do one of those things, you'll need to perform some low-level troubleshooting using e.g. Wireshark.
  6. From the client device(s), access the minimal Apache http website you set up earlier in this document. E.g. if the internet-facing interface has an IP of, and you followed the instructions to the letter, you would access in the browser on those devices.
  7. Browse to, and install, all of the root CA certificates on that site.
  8. Optionally, reboot the client device(s) to make sure that all running processes are restarted and pick up the revised set of trusted root CA certificates.
  9. Start ZAP, using e.g. the following commands:


    cd ~/ZAP_2.1.0


  10. Configure the client device(s) to use ZAP as a web proxy. For example, if the internet-facing interface on the VM has the IP, and you configured ZAP to listen on that IP and on port 9876, enter those values in the proxy configuration on the client device(s).
  11. Verify that you can access HTTP content on the client device(s), and that the traffic shows up in the ZAP proxy history.
  12. Verify that you can also access HTTPS content on the client devices, that the traffic shows up in the ZAP proxy history, and that the client device does not give you a certificate warning.
  13. In ZAP, set up your session to be auto-saved so that you don't lose any proxy history. Click the floppy disk icon in the toolbar, or from the File menu, select Persist Session.

Phase 2: determine which Blur XMPP server the phone is attempting to communicate with

  1. Option A - monitor traffic using Wireshark
    If you are experienced with Wireshark, this is the fastest way to obtain this information. If you are not experienced with Wireshark, it's unlikely you'll be able to follow these steps.
    1. Start a Wireshark capture on all interfaces.
    2. Optionally, to make the traffic of interest easier to find, set a display filter of tcp.port == 5222.
    3. Reboot the client device.
    4. Within a minute or two, you should see entires in your Wireshark capture. The first part of each XMPP session takes place over an unencrypted channel, so if you do use the Follow TCP stream function, you should see something like what is shown in the screenshot below. From this data, it's possible to determine several things of interest, at least two of which will be important in Phase 3, below.
      1. The phone is trying to connect to jabber-cloud112-blur.svcmot.com. This may be different for devices that you test with.
      2. The common name on the certificate the server is sending back is *.svcmot.com.
      3. In case you would like to forge a certificate that's as close a match as possible (from a human-readable perspective), the other properties of the certificate are also visible (e.g. the organization is Motorola Mobility, LLC, the city is Libertyville (hah!), the state is IL, and the country is US).
    5. This is all the information you need to proceed to Phase 3, below. Skip the Option B section unless you were unsuccessful with Wireshark.
  2. Option B - analyze check-in data
    If you are more comfortable hex-editing files than using Wireshark, you can follow the instructions in the Motorola Is Listening article (in the Steps to reproduce - check-in data decompression section) to determine the name of the XMPP server the phone is trying to communicate with.
    1. Make sure ZAP is still capturing traffic.
    2. Reboot the client device.
    3. Wait for a reasonably large HTTPS request to be sent to the check-in web service (e.g. on my phone, it was an HTTPS POST to a URL beginning with https://ws-cloud112-blur.svcmot.com:443/blur-services-1.0/ws/checkin/).
    4. Decompress the data, using the instructions in the other article.
    5. It may take a few tries, but sooner or later you should find a set of data that includes a line like this:


      Preparing to connect user XXXXXXXXXXXXXXXX to service: jabber-cloud112-blur.svcmot.com on host: jabber-cloud112-blur.svcmot.com and port: 5222

    6. This method won't tell you the common name on the certificate that the Blur service is sending to the client, but you can almost certainly just use *.svcmot.com.
    7. Proceed to Phase 3, below.
Finding the client's Blur server in a Wireshark capture
[ XMPP destination ]
XMPP destination



Phase 3: configure XMPPPeek to intercept the XMPP traffic

  1. Power off the client device(s).
  2. Undo the modification you made to the ~/xmpppeek/startgateway.sh script earlier. Open it in your favourite editor and uncomment this line (remove the # from the beginning of the line):

    #iptables -t nat -A PREROUTING -i $lanInt -p tcp --dport 5222 -j DNAT --to-destination

    Save the file and exit.
  3. Rerun that script just as you did earlier, e.g. by running this command and answering the prompts the same way:


    sudo ./startgateway.sh

  4. Generate an SSL certificate that matches the common name the client device is expecting (e.g. *.svcmot.com), and chain it together with your forged CA root certificate:
    1. Execute these commands:


      cd ~/xmpppeek

      /usr/lib/ssl/misc/CA.pl -newreq

    2. When prompted for a passphrase, just like with the CA certificate generation, it doesn't matter what you use (as long as you remember what it is), because it will be stripped out shortly.
    3. When prompted for the certificate properties, you can probably use whatever values you like, other than that the common name must be correct (e.g. *.svcmot.com). If you want to help make sure not to run afoul of any faux-certificate-pinning code on the client, make all of the properties match as closely as possible.
    4. Execute these commands, entering Y when prompted by openssl, and entering the passphrase you just picked when prompted for that:


      cd ~/ca

      openssl ca -in ~/xmpppeek/newreq.pem -out ~/xmpppeek/svcmot.crt -keyfile ~/ca/demoCA/private/cakey.pem -cert ~/ca/demoCA/cacert.pem

      cd ~/xmpppeek

      openssl rsa -in newkey.pem -out svcmot.key

      cat ~/xmpppeek/svcmot.crt >> ~/xmpppeek/svcmot-chained.crt

      cat ~/ca/demoCA/cacert.pem >> ~/xmpppeek/svcmot-chained.crt

  5. Assuming you have not encountered any errors, start XMPPPeek with a command like the following (substitute the correct destination host name as appropriate):


    python ./xmpppeek.py jabber-cloud112-blur.svcmot.com svcmot-chained.crt svcmot.key

  6. Power the client device(s) back on, and you should see the XMPP traffic being captured by XMPPPeek, as well as still seeing the HTTP and HTTPS traffic in ZAP.
  7. If you fail to see the expected traffic, and especially if the traffic stops after XMPPPeek opens the encrypted channel to the client, it wouldn't hurt to explicitly install the forged *.svcmot.com certificate on the client device as well - just copy it to /var/www/ and access it like you did the CA certificates. The use of the chained certificate should prevent having to do this, however.
Generating a forged certificate for use with the XMPP traffic
[ Certificate request ]
Certificate request
[ Signing the certificate ]
Signing the certificate
[ Installing the certificate on the client device ]
Installing the certificate on the client device



Example: using Mallory

My experience so far is that while Mallory is an impressive tool with an awful lot of potential, it is also finnicky and some of the functionality doesn't work as expected. However, these steps should give you some idea of what it's capable of. Please note that I did not use this for my actual Motorola phone testing, because as of this writing Mallory doesn't handle XMPP-over-TLS correctly.

For a more in-depth real-world description of using Mallory, I thought Mallory MITM + FIX SSL Decryption (by Paul Ambrosini) was really good.

  1. If you've been using the system in other ways, it wouldn't hurt to reboot before going any further.
  2. Open a terminal window and run this series of commands. You will need to substitute the name of your internet-facing and client-facing interfaces if they're not eth0 and eth1. You will also need to substitute the IP address of an upstream DNS server in place of Your client will not be able to make DNS queries against the client-facing interface while Mallory is running, and this dnsmasq configuration tells clients to use an upstream DNS server instead.


    sudo /etc/init.d/dnsmasq stop

    sudo dnsmasq --interface eth1 --no-hosts --no-poll --except-interface=lo --listen-address= --dhcp-range=,,60m --dhcp-option=option:router, --dhcp-option=6,, --dhcp-lease-max=50 --pid-file=/var/run/nm-dnsmasq-eth1.pid

  3. Verify that your client device(s) can connect to the client-facing interface, receive configuration via DHCP, and connect to the internet.
  4. Open two more terminal windows. In both of them, run this command:


    cd ~/mallory/current/src

  5. In the first window, run this command:


    sudo python ./mallory.py

  6. In the second window, run this command:


    sudo python ./launchgui.py

    Mallory should now be running, and the GUI control window should also be open.
  7. In the Interfaces tab:
    1. Check the Perform MitM box for the client-facing interface (e.g. eth1).
    2. Check the Outbound Interface box for the internet-facing interface (e.g. eth0).
    3. Click the Apply Configuration button.
  8. Switch to the Protocols tab.
  9. All of the protocols are disabled (commented-out) by default. Here is an example set that should cause Mallory to intercept HTTP (on TCP port 80), HTTPS (on TCP port 443), SSH (on TCP port 22), and Google's own SSL-encrypted XMPP/Jabber-type protocol (on TCP port 5228):







    Paste that block of text into the field, replacing its current contents, then click the Apply button.
  10. Switch to the Rules tab.
  11. Mallory should include a default Debug All rule. If it doesn't, here's how to make your own:
    1. Click the new rule button (the green circle with a white plus sign in it).
    2. In the Name field, enter Debug All.
    3. Make sure Direction is set to Both.
    4. Set the Type to Debug.
    5. Set Passthru to Yes.
    6. Click the Save Rule button.
  12. Optionally, you can add a couple of rules that will attempt to prevent webservers from sending gzipped/compressed data to clients, which will make the content easier to read when it's intercepted. These rules are based on the ones described by Ascetik in Mallory MiTM Proxy as a Wireless Access Point (Part 2 of 2), although I made them specific to these two ports so as not to interfere with other similar data.
    1. Click the new rule button (the green circle with a white plus sign in it).
    2. In the Name field, enter Strip content-encoding from HTTP.
    3. Set Direction is set to C2S.
    4. In the Port field, enter 80.
    5. Set the Type to Muck.
    6. In the Muck field, enter Accept-Encoding: gzip.*/X-Not-Used-HTTP: 12345/1.
    7. Set Passthru to Yes.
    8. Click the Save Rule button.
    9. Move the new rule up to the top of the list.
    10. Click the new rule button (the green circle with a white plus sign in it).
    11. In the Name field, enter Strip content-encoding from HTTPS.
    12. Set Direction is set to C2S.
    13. In the Port field, enter 443.
    14. Set the Type to Muck.
    15. In the Muck field, enter Accept-Encoding: gzip.*/X-Not-Used-HTTPS: 12345/1.
    16. Set Passthru to Yes.
    17. Click the Save Rule button.
    18. Move the new rule up to the top of the list.
  13. Switch to the Streams tab.
  14. Click the Intercept and Auto Send toggle-buttons.
  15. On your client device, make sure you have any necessary root CA certs installed (see previous sections), then attempt to access HTTP, HTTPS, and SSH services.
  16. For HTTP/HTTPS, you should see the traffic appear in Mallory's Streams tab. You can play around with using the interception features for this - it's not nearly as comprehensive as Burp or ZAP, but you can probably do some fun stuff.

  17. SSH traffic will not appear in the Streams tab, but you can verify that Mallory is performing a MitM against it because by default it will send a message reading "Things just got real" as a banner when an SSH connection is established. Although I haven't found a built-in way for the traffic to be logged, there is a really neat feature that I haven't seen discussed as widely as it should be: once a client has established a man-in-the-middled SSH session through Mallory, Mallory makes a telnet interface available to piggyback your own SSH shell on top of the legitimate client session.
    1. From the Linux VM that Mallory is running on, telnet to port 20765 on localhost.
    2. Select the appropriate session.
    3. Execute commands as the user who initiated the legitimate SSH connection (see screenshot below).
  18. Most of the power of Mallory is supposedly in writing your own Python code for it to execute, which is well outside the scope of this writeup. But this should give you some idea of what's possible.
Mallory configuration and SSH-hijacking
[ Debug All rule ]
Debug All rule
[ HTTP encoding-header-stripping rule ]
HTTP encoding-header-stripping rule
[ HTTPS encoding-header-stripping rule ]
HTTPS encoding-header-stripping rule
[ A sign that Mallory is listening in on this SSH session ]
A sign that Mallory is listening in on this SSH session
[ Taking advantage of the SSH session ]
Taking advantage of the SSH session



Example: using socat to perform a basic SSL man-in-the-middle attack

The socat utility allows you to perform a barebones SSL MitM attack using a single command (assuming you've set up the certificate you want to use ahead of time). This can be handy if you're working with a non-HTTPS protocol, as long as it uses SSL/TLS from the beginning. If it uses negotiated encryption like IMAP or XMPP, this won't work. This method also won't work for SSH connections. It will work for HTTPS, even though a tool like ZAP or Burp Suite is generally a better choice. Because HTTPS is the most common protocol that this method can be used with, it's the one that will be used for this example, since it's more likely that you'll be able to try it out for yourself.

The utility itself is tiny, so including it in this build was a no-brainer - you never know when it will come in handy.

  1. Examine the SSL certificate for the target site or system to find the common name. For example, if you want to intercept traffic to https://www.secureideas.com/, open that site in your browser and look at the SSL certificate. In the case of that site, the common name is *.secureideas.com.
  2. Create a working directory and generate an SSL certificate that matches the common name the client device is expecting (e.g. *.secureideas.com), and chain it together with your forged CA root certificate:
    1. Execute these commands:


      cd ~

      mkdir socat

      cd ~/socat

      /usr/lib/ssl/misc/CA.pl -newreq

    2. When prompted for a passphrase, just like with the CA certificate generation, it doesn't matter what you use (as long as you remember what it is), because it will be stripped out shortly.
    3. When prompted for the certificate properties, you can probably use whatever values you like, other than that the common name must be correct (e.g. *.secureideas.com). If you want to help make sure not to run afoul of any faux-certificate-pinning code on the client, make all of the properties match as closely as possible.
    4. Execute these commands, entering Y when prompted by openssl, entering the passphrase you just picked when prompted for that, and replacing secureideas with the name of your actual target:


      cd ~/ca

      openssl ca -in ~/socat/newreq.pem -out ~/socat/secureideas.crt -keyfile ~/ca/demoCA/private/cakey.pem -cert ~/ca/demoCA/cacert.pem

      cd ~/socat

      openssl rsa -in newkey.pem -out secureideas.key

      cat ~/socat/secureideas.crt >> ~/socat/secureideas-chained.crt

      cat ~/ca/demoCA/cacert.pem >> ~/socat/secureideas-chained.crt

  3. Assuming no errors occurred, start the socat-based listener using this command, again replacing secureideas with the name of your actual target, and of course changing other options you'd like (using a port other than 9001 for the listener, etc.).


    socat -v OPENSSL-LISTEN:9001,bind=,reuseaddr,fork,cert=secureideas-chained.crt,key=secureideas.key,verify=0 OPENSSL-CONNECT:www.secureideas.com:443,verify=0 2>>~/socat/log-secureideas.txt

  4. If you are returned to a prompt, something went wrong and you should examine the log. Otherwise, you can proceed to use iptables to reroute traffic to your socat listener. You'll need to know the destination IP that the client is trying to connect to in order for this syntax to work. Use that instead of in the example below. You should do this after setting up iptables to forward all traffic between interfaces, e.g. using the startgateway.sh script that's included with XMPPPeek.


    sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -d --dport 443 -j DNAT --to-destination

  5. Now, when a client tries to connect to the target using the client-facing interface on your Linux VM, it will be re-routed through the socat listener, and all traffic will be logged (to ~/socat/log-secureideas.txt if you use the same location as in the example above).

This probably goes without saying, but you really don't want to practice attacks against the actual Secure Ideas website.

Again, this is an extremely barebones MitM attack - if you actually use it for HTTPS traffic, most of the content is going to be compressed, and you'll need to extract it from the log file and run it through a gzip decompressor to see the actual HTML and whatnot.


This section is going to be pretty minimal for now, until I start getting feedback on problems that others ran into.

Some models of Android device refuse to install the forged root CA certificate(s), and return a No certificate to install error.

I ran into this problem on an Android 3.x device. Upgrading it to 4.x didn't address the problem. What I did in the end was open the certificate files in a text editor and remove the human-readable parts (everything other than the base64-encoded data between the BEGIN CERTIFICATE and END CERTIFICATE tags). Since I hadn't tried that before the upgrade, I'm not sure if the same thing would have worked on the device while it was running Android 3.x.

The client-facing interface keeps resetting to DHCP-configured and disconnecting clients

On one of the VMs I set up using these instructions (but not the other!), the client-facing USB ethernet NIC would accept its configuration, but within a minute or two, reset to DHCP-configured. You may not need to perform the following steps, but if you run into the same problem, here's the configuration I used:

  1. Edit /etc/NetworkManager/NetworkManager.conf using your favourite editor.
  2. Modify this line:



    ...to read:



  3. Save and close.
  4. Execute the following command to back up your existing network configuration:


    sudo cp /etc/network/interfaces /etc/network_interfaces-01

  5. Edit /etc/network/interfaces using your favourite editor.
  6. Delete all of the content except for these lines:


    auto lo

    iface lo inet loopback

  7. Save and close.
  8. Reboot the system.
  9. From the Applications menu in Ubuntu, navigate to System Tools -> System Settings -> Network.
  10. Find the NIC you want to use for the client-facing interface.
  11. Under IPv4 Settings, change its Method to Manual.
  12. Give it the address of and netmask of 24.
  13. Save and close.
  14. Reboot the system again.

An Alfa AWUS036NH or AWUS036NHR is being used as the internet-facing interface, and it stops working every few minutes until it's disconnected and reconnected

This is a bug in either Ubuntu specifically or the Linux kernel that 12.04 LTS uses. The Backtrack developers seem to have found a way to avoid this, but I'm not sure what it is. Sadly, you'll need to use a different type of USB wireless adapter unless someone can tell me how to work around the bug in Ubuntu 12.04 LTS.

1. I tend to like regular Debian, openSUSE, or Fedora, in terms of the major distributions. Ubuntu lost me when their developers started coming up with wacky stuff like Unity.
2. A VirtualBox NAT connection won't work. I'm not actually sure why, although I've read the same thing elsewhere without seeing a good explanation.
[ Page Icon ]