Nmap Development mailing list archives

[Exp PATCH] Send actual IGMP header when using -sO


From: Kris Katterjohn <katterjohn () gmail com>
Date: Mon, 15 Jan 2007 16:40:39 -0600

The attached patch (/nmap-exp/kris SVN r4354) adds build_igmp_raw() to
build IGMP packets and uses it to send IGMP packets used for -sO with an
actual header. The SVN log below explains a bit more:

------------------------------------------------------------------------
r4354 | kris | 2007-01-15 16:32:02 -0600 (Mon, 15 Jan 2007) | 1 line

Add build_igmp_raw() so that we can easily build IGMP packets and use it
for -sO. I have found that, like ICMP, TCP, and UDP, systems respond
more to packets with an actual IGMP header. The RFC says they MUST
verify the checksum, so that's probably the sole reason it's always
open|filtered instead of open (for me, anyway).  All of the types seem
to have the checksum in the same place in the packet, so if the checksum
_is_ the reason I can pick it up now, it should pick them all up and at
least tell us if it's actually open or not even if the rest of the
header is bogus.
------------------------------------------------------------------------

I have tested it and it seems to work great. If anyone else can test
this out further and leave me some feedback, it will really be appreciated.

Thanks a lot,
Kris Katterjohn
Index: kris/tcpip.cc
===================================================================
--- kris/tcpip.cc       (revision 4353)
+++ kris/tcpip.cc       (revision 4354)
@@ -1447,7 +1447,67 @@
                    packetlen);
 }
 
+/* Builds an IGMP packet (including an IP header) by packing the fields
+   with the given information.  It allocates a new buffer to store the
+   packet contents, and then returns that buffer.  The packet is not
+   actually sent by this function.  Caller must delete the buffer when
+   finished with the packet.  The packet length is returned in packetlen,
+   which must be a valid int pointer.
+ */
+u8 *build_igmp_raw(const struct in_addr *source, const struct in_addr *victim, 
+                  int ttl, u16 ipid, u8 tos, bool df,
+                  u8 *ipopt, int ipoptlen,
+                  u8 ptype, u8 pcode,
+                  char *data, u16 datalen, u32 *packetlen) {
+ struct {
+   u8 igmp_type;
+   u8 igmp_code;
+   u16 igmp_cksum;
+   u32 var; /* changes between types, unused. usually group address. */
+   u8 data[1500];
+ } igmp;
+ u32 *datastart = (u32 *) igmp.data;
+ int dlen = sizeof(igmp.data); 
+ int igmplen = 0;
+ char *pkt = (char *) &igmp;
 
+ igmp.igmp_type = ptype;
+ igmp.igmp_code = pcode;
+
+ if (ptype == 0x11) { /* Membership Query */
+   igmplen = 8;
+ } else if (ptype == 0x12) { /* v1 Membership Report */
+   igmplen = 8;
+ } else if (ptype == 0x16) { /* v2 Membership Report */
+   igmplen = 8;
+ } else if (ptype == 0x17) { /* v2 Leave Group */
+   igmplen = 8;
+ } else if (ptype == 0x22) { /* v3 Membership Report */
+   igmplen = 8;
+ } else {
+   fatal("Unknown igmp type (%d) in build_igmp_raw", ptype);
+ }
+
+ if (datalen > 0) {
+   igmplen += MIN(dlen, datalen);
+   memset(datastart, 0, MIN(dlen, datalen));
+ }
+
+ igmp.igmp_cksum = 0;
+ igmp.igmp_cksum = in_cksum((unsigned short *)pkt, igmplen);
+
+ if (o.badsum)
+   --igmp.igmp_cksum;
+
+ return build_ip_raw(source, victim,
+                    IPPROTO_IGMP,
+                    ttl, get_random_u16(), tos, df,
+                    ipopt, ipoptlen,
+                    pkt, igmplen,
+                    packetlen);
+}
+
+
 /* A simple function I wrote to help in debugging, shows the important fields
    of a TCP packet*/
 int readtcppacket(const u8 *packet, int readdata) {

Index: kris/tcpip.h
===================================================================
--- kris/tcpip.h        (revision 4353)
+++ kris/tcpip.h        (revision 4354)
@@ -464,6 +464,10 @@
 };
 #endif /* HAVE_STRUCT_ICMP */
 
+/* Some systems might not have this */
+#ifndef IPPROTO_IGMP
+#define IPPROTO_IGMP 2
+#endif
 
 /* Prototypes */
 /* Converts an IP address given in a sockaddr_storage to an IPv4 or
@@ -575,6 +579,19 @@
                   u16 seq, unsigned short id, u8 ptype, u8 pcode,
                   char *data, u16 datalen, u32 *packetlen);
 
+/* Builds an IGMP packet (including an IP header) by packing the fields
+   with the given information.  It allocates a new buffer to store the
+   packet contents, and then returns that buffer.  The packet is not
+   actually sent by this function.  Caller must delete the buffer when
+   finished with the packet.  The packet length is returned in packetlen,
+   which must be a valid int pointer.
+ */
+u8 *build_igmp_raw(const struct in_addr *source, const struct in_addr *victim, 
+                  int ttl, u16 ipid, u8 tos, bool df,
+                  u8* ipopt, int ipoptlen,
+                  u8 ptype, u8 pcode,
+                  char *data, u16 datalen, u32 *packetlen);
+
 /* Builds an IP packet (including an IP header) by packing the fields
    with the given information.  It allocates a new buffer to store the
    packet contents, and then returns that buffer.  The packet is not

Index: kris/scan_engine.cc
===================================================================
--- kris/scan_engine.cc (revision 4353)
+++ kris/scan_engine.cc (revision 4354)
@@ -2186,6 +2186,14 @@
                                o.extra_payload, o.extra_payload_length,
                                &packetlen);
        break;
+      case IPPROTO_IGMP:
+       packet = build_igmp_raw(&o.decoys[decoy], hss->target->v4hostip(),
+                               o.ttl, ipid, IP_TOS_DEFAULT, false,
+                               o.ipoptions, o.ipoptionslen,
+                               0x11, 0,
+                               o.extra_payload, o.extra_payload_length,
+                               &packetlen);
+       break;
       case IPPROTO_UDP:
        packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(),
                               o.ttl, ipid, IP_TOS_DEFAULT, false,

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: