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:
- [Exp PATCH] Send actual IGMP header when using -sO Kris Katterjohn (Jan 15)
- Re: [Exp PATCH] Send actual IGMP header when using -sO Fyodor (Jan 15)