How to modify general TCP/IP traffic on the fly with Trudy

There are several great tools available to intercept network traffic. Scapy and Wireshark are great tools for passive sniffing and Scapy is also capable of sending additional packets.

In case you want to intercept traffic as a Man-in-the-Middle intermediary we can use many popular tools such as Fiddler, Burp Suite or OWASP ZAP. These are great tools which are, however, built for the HTTP(S) protocol only. What software to use if you need to modify general non-HTTP traffic?

This was exactly my issue when I've analyzed the Telegram IM (see more articles). Telegram uses its own homebrew protocol MTProto directly on top of the TCP/IP suite. Since HTTP or HTTPS is not used at all, the tools mentioned above are not applicable.

The first tool I've found with similar capabilities was Ettercap, which I've already used to perform the MiM setup itself. It provides a simple filtering interface allowing to modify the data routed through. Unfortunately, Ettercap requires the filters to be written in its own language which is quite limiting and was insufficient for my needs at that time.

I finally came across two tools that seemed to solve my problems: Mallory and Trudy. The Mallory software may be found on github and there is a talk about it on youtube from the Black Hat USA conference in 2010. Some time passed since and the project seems to be abandoned. Let's have a look closer look on Trudy, which I've finally successfully used. Trudy was written by @kelbyludwig and its source code is available on github as well.

Trudy

The Trudy software can modify any TCP traffic and it is most likely inspired by the Mallory software mentioned in the previous section. As its documentation states, Trudy is "a transparent proxy that can modify and drop traffic for arbitrary TCP connections". All traffic is routed through Trudy which then applies so called modules to alter it.

Trudy modules are bulks of preprogrammed code to perform modifications desired by the user. Trudy provides an example stub of such a module, and users are encouraged to implement it. Because Trudy is written in Go, all modules are to be written in Go as well. To route the traffic and setup the environment properly, a prepared virtual machine is available.

Virtual machine setup

The VM installs all the required software and Trudy itself as well. Then it routes all the traffic in and out of Trudy using iptables. Trudy receives all the traffic, modifies it based on the used module and sends it back to internet as seen in the following Figure:

Trudy module

The implementation of a module for Trudy is quite straightforward. Trudy
calls specific methods in fixed order, each designed for one particular action.
The methods of a single module are as follows:

  • Deserialize() converts the raw payload into a known structure of data (e.g. HTTP)
  • Drop() if true is returned, the whole packet is discarded
  • DoMangle() if true is returned, Mangle() is called
  • Mangle() alters the payload
  • DoIntercept() if true is returned, the data are sent to the Trudy in- terceptor 19
  • DoPrint() if true is returned, PrettyPrint() is called
  • PrettyPrint() prints data in a human friendly format
  • Serialize() converts the data back to raw payload if it were previously deserialized
  • BeforeWriteTo() actions taken before the data are written to one side or the other
  • AfterWriteTo() actions taken after the data are written to one side or the other

Example

This dead simple example of a module cripples all incoming traffic received from an IP address 139.59.129.86 on port 80. It does so by rewriting the whole TCP/IP payload to zeros.

The main part of the module uses the DoMangle() and Mangle() functions:

func (input Data) DoMangle() bool {  
    if input.ServerAddr.String() == "139.59.129.86:80" {
        return true
    }
    return false
}

func (input *Data) Mangle() {  
    for i := range input.Bytes {
        input.Bytes[i] = 0x00
    }
}

The DoMangle() function limits the mangling to our specified IP address and Mangle() does the actual work.

Our test IP address was not chosen randomly, but rather corresponds to a domain of mine - nohttps.susanka.eu. After setting up Trudy with this example module, we can try to access the site via regular browser. The request will work fine but the response will get rewritten with zeros. The browser is obviously unable to parse the response and will eventually time out.

We may confirm this behaviour using WireShark. The picture below shows the modified response. The blue box is the TCP/IP payload - full of zeros as anticipated. The TCP/IP headers are left untouched (before the blue box).

You may find the whole module on my gist. It additionally enables console printing to give you an idea what's going on.

You can use Trudy for a numerous different use cases, it provides an easy interface to alter generic TCP/IP traffic on the air.