tcpprox - An intercepting TCP proxy

On numerous occasions I’ve run into custom binary network protocols that I’ve wanted to reverse. The usual goto here is to fireup wireshark/tcpdump and view the traffic as it goes accross the wire. This works really well in most cases, but how about traffic that uses TLS to encrypt the traffic? Unless you have the private key for the server, you are stuck with viewing encrypted traffic in wireshark. Not ideal for reverse engineering.

To overcome this, I decided to find a TCP proxy capable of intercepting TLS traffic and allowing me to view the raw, unencrypted protocol, basically the same thing as what you get when using mitmproxy or Burp. Unfortunately I wasn’t able to find anything to match my needs (admittedly I did a very lazy search and decided it’s more fun to implement my own anyway). Armed with an excuse to do some more coding, tcpprox.go was born. The basic idea was to have two operating modes, plain-text and TLS enabled.

Plain-text:

In this mode we setup a listen-connect proxy (bascially a socat tunnel), where we accept a connection, establish another connection to our target server, and then shunt all traffic between the two. Simple. This works great but doesn’t really give you anything more than wireshark or tcpdump would. Natuarlly this is extendable and I’ve used it to modify traffic in-line, something along the lines of s/\x00\x01\x00\x01/\x01\x00\x01\x00/g where we simply replace byte patterns. Most of the time the nice hex-dump view is enough and what’s needed to understand a protocol’s functinality.

TLS:

Here we setup a proper mitm proxy, where we still do a listen-connect proxy, however everything gets wrapped in TLS. This is where tcpprox has really worked well for me in the past. Especially when working on the RPC/HTTP component of Ruler, as it allowed me to actually see what is going on. Trying to use Burp/Fiddler on this traffic was usueless, as these proxies showed the first bit of the connection, the initial HTTP message, but failed to display the streaming data. Burp didn’t show anything, while Fiddler stated that “RPC traffic can not be inspected”.

With tcpprox, I was able to mitm the HTTPS connection (as HTTPS is a TLS-TCP connection with HTTP traffic), and inspect the traffic flowing between the client and server. Here it was possible to spot the DCERP traffic going across the wire and figure out what is needed to setup a correct connection.

From Client [0]:
00000000  05 00 0b 13 10 00 00 00  74 00 00 00 01 00 00 00  |........t.......|
00000010  f8 0f f8 0f 00 00 00 00  02 00 00 00 00 00 01 00  |................|
00000020  00 db f1 a4 47 ca 67 10  b3 1f 00 dd 01 06 62 da  |....G.g.......b.|
00000030  00 00 51 00 04 5d 88 8a  eb 1c c9 11 9f e8 08 00  |..Q..]..........|
00000040  2b 10 48 60 02 00 00 00  01 00 01 00 00 db f1 a4  |+.H`............|
00000050  47 ca 67 10 b3 1f 00 dd  01 06 62 da 00 00 51 00  |G.g.......b...Q.|
00000060  66 58 3d 79 6b 7b 87 5f  5e 16 86 72 3c ff b6 38  |fX=yk{._^..r<..8|
00000070  01 00 00 00                                       |....|

From Server [1]:
00000000  35 34 0d 0a 05 00 0c 13  10 00 00 00 54 00 00 00  |54..........T...|
00000010  01 00 00 00 f8 0f f8 0f  e4 cd 63 09 05 00 36 30  |..........c...60|
00000020  30 31 00 00 02 00 00 00  00 00 00 00 04 5d 88 8a  |01...........]..|
00000030  eb 1c c9 11 9f e8 08 00  2b 10 48 60 02 00 00 00  |........+.H`....|
00000040  02 00 02 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  0d 0a                    |..........|

From Client [0]:
00000000  05 00 00 03 10 00 00 00  88 01 00 00 04 00 00 00  |................|
00000010  88 01 00 00 00 00 0a 00  68 00 00 00 00 00 00 00  |........h.......|
00000020  68 00 00 00 2f 6f 3d 65  76 69 6c 63 6f 72 70 2e  |h.../o=evilcorp.|
00000030  6c 6f 63 61 6c 2f 6f 75  3d 65 78 63 68 61 6e 67  |local/ou=exchang|
00000040  65 20 61 64 6d 69 6e 69  73 74 72 61 74 69 76 65  |e administrative|
00000050  20 67 72 6f 75 70 20 28  66 79 64 69 62 6f 68 66  | group (fydibohf|
00000060  32 33 73 70 64 6c 74 29  2f 63 6e 3d 72 65 63 69  |23spdlt)/cn=reci|
00000070  70 69 65 6e 74 73 2f 63  6e 3d 70 72 69 64 65 20  |pients/cn=henry.|
00000080  6d 61 70 68 69 73 61 38  66 65 00 00 00 00 00 00  |hammond8fe......|
00000090  fe da 2f d2 00 00 00 00  e4 04 00 00 09 04 00 00  |../.............|
000000a0  09 04 00 00 ff ff ff ff  01 00 0f 00 03 13 e8 03  |................|
000000b0  00 00 00 00 c6 00 00 00  00 00 04 00 be 00 be 00  |................|
000000c0  36 00 01 02 a0 86 01 00  01 00 00 00 00 00 00 00  |6...............|
000000d0  00 00 00 00 00 00 20 00  00 00 00 00 02 00 00 00  |...... .........|
000000e0  45 00 74 00 68 00 65 00  72 00 6e 00 65 00 74 00  |E.t.h.e.r.n.e.t.|
000000f0  20 00 32 00 00 00 18 00  01 18 01 00 00 00 3e b3  | .2...........>.|
00000100  55 6a b6 8f af b3 3f 9a  e2 49 35 c1 e7 df 1c 00  |Uj....?..I5.....|
00000110  02 04 01 00 00 00 b8 bd  2f a9 f2 1c 30 c4 15 40  |......../...0..@|
00000120  3b 80 d9 cb 83 7f 1b 00  00 00 34 00 02 0b 01 00  |;.........4.....|
00000130  00 00 9d ef d1 39 0b 47  3c b1 06 e5 c4 00 1e 1b  |.....9.G<.......|
00000140  d7 c2 4f 00 00 00 4f 00  55 00 54 00 4c 00 4f 00  |..O...O.U.T.L.O.|
00000150  4f 00 4b 00 2e 00 45 00  58 00 45 00 00 00 22 00  |O.K...E.X.E...".|
00000160  01 4a 90 93 1e 7e 90 ce  05 76 23 b1 16 a7 12 d4  |.J...~...v#.....|
00000170  70 be 00 00 00 00 05 00  00 00 01 00 00 00 00 00  |p...............|
00000180  c6 00 00 00 08 10 00 00                           |........|

Using tcpprox:

Firstly, grab the source from Github - https://github.com/staaldraad/tcpprox. You’ll need a Go environment setup, sorry not going to help with this.

To use it without building,

go run tcpprox.go -l 127.0.0.1 -p 80 -r google.com:80

Our options are,

-l local IP address to listen on
-p local port to listen on
-r remote-ip/host:remote-port

Using tcpprox in TLS mode:

You can simply start tcpprox with the -s to signal that it should use TLS. By default tcpprox will generate a certificate for the session:

go run tcpprox.go -s -l 127.0.0.1 -p 443 -r google.com:443

If you want to use a custom certificate, you’ll need to generate a valid TLS certifcate here, and name it server.{key,crt} as I’m lazy. The easiest is to use the following commands with OpenSSL:

openssl genrsa -out server.key 2048 openssl req -new -x509 -key server.key -out server.pem -days 365

Then convert it to DER format:

openssl x509 -in server.pem -out server.crt -outform der

Finally you have the option of specifying everything in a config file and tcpprox will use these options to automatically generate a TLS certificate for you, ect ect.

{
    "remotehost":"targethost.com:1990",
    "localhost":"0.0.0.0",
    "localport":1990,
    "TLS":{
            "Country":["GB"],
            "Org":["YourOrg"],
            "CommonName":"*.domain.com"
    },
    "Certfile":""
}

Start tcpprox with the config file:

go run tcpprox.go -s -c config.json

Hopefully this helps you to proxy, view and modify some TCP traffic in the future. As always, issues, suggestions and PRs are most welcome.