Skip to main content

Invalid TCP segments created by macof

· 2 min read
Jan Starke
Senior Forensic Analyst

Some days ago, we used the tool macof, which is part of the dsniff package, in one penetration test. We observed that our attack had no effect to the hosts in the network, so we started sniffing around. Wireshark was our friend.

Wireshark identified our packets, generated by macof, as "invalid". It took some time for us to realize that IP Header value for Total Length was indeed wrong! We used macof to send TCP SYN segments to some specific port, so Total Length should be 40 (20 Byte IP Header + 20 Byte TCP Header), but macos generated packets with a value of 20.

So we started a little code reading session and found the following statements in macof.c:

libnet_build_tcp(sport, dport, seq, 0, TH_SYN, 512, 0, 0, LIBNET_TCP_H, NULL, 0, l, 0);

libnet_build_ipv4(LIBNET_TCP_H, 0, libnet_get_prand(LIBNET_PRu16), 0, 64, IPPROTO_TCP, 0, src, dst, NULL, 0, l, 0);

Obviously, the length of the IP Header is not included in this calculation. We changed the above statements to

libnet_build_tcp(sport, dport, seq, 0, TH_SYN, 512, 0, 0, LIBNET_TCP_H, NULL, 0, l, 0);

libnet_build_ipv4(LIBNET_IPV4_H+LIBNET_TCP_H, 0, libnet_get_prand(LIBNET_PRu16), 0, 64, IPPROTO_TCP, 0, src, dst, NULL, 0, l, 0);

with the result, that Wireshark didn't complain about our packets anymore.

And, more important, our attack did work now :-)

After the test, I sent an email to the author of macof and dsniff, including a patch of what we've done, but until today I received no answer. So, I'll publsh our patch here, and you are free to use it:

 diff -rupN dsniff-2.4_beta1-r6/macof.c dsniff-2.4_beta1-r6_FIX/macof.c
--- dsniff-2.4_beta1-r6/macof.c	2015-01-20 08:50:53.980054279 +0100
+++ dsniff-2.4_beta1-r6_FIX/macof.c 2015-01-20 08:51:24.220054894 +0100
@@ -134,7 +134,7 @@ main(int argc, char *argv[])
libnet_build_tcp(sport, dport, seq, 0, TH_SYN, 512,
0, 0, LIBNET_TCP_H, NULL, 0, l, 0);

- libnet_build_ipv4(LIBNET_TCP_H, 0,
+ libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_TCP_H, 0,
libnet_get_prand(LIBNET_PRu16), 0, 64,
IPPROTO_TCP, 0, src, dst, NULL, 0, l, 0);