Nmap Development mailing list archives

[PATCH] New output format (-oP): Pcap savefile


From: Kris Katterjohn <katterjohn () gmail com>
Date: Sun, 30 Dec 2007 02:13:14 -0600

Hi everyone!

I had an idea back during the GSoC, which I finally implemented (patch attached) :)

The idea is for a new output option that saves packets in the pcap savefile format. I've selected -oP for this, but changing it is no big deal.

So not only can you save the scan for viewing in tcpdump or Wireshark later, but the extra network traffic that would be captured running a sniffer at the time aren't getting saved.

There are some downsides, though:

1) It only handles raw IP packets, no ARP or connect() calls. Connect() doesn't work for obvious reasons. ARP doesn't work because the savefile must be set up initially with a DLT type, and we can't switch between the two different protocols with it. There's no "catch-all" type that I see that works like Nmap does. ARP is only used for pinging on a local network, so this isn't a huge downside. Any ideas on this is appreciated.

2) Going along with #1, anything that uses Nsock (DNS, version detection, NSE) won't get logged by this.

I've also attached a capture file from a scan like this:

nmap -p21-25,80,110 -oP test.pcap scanme.insecure.org

Do "tcpdump -r test.pcap" or open it in Wireshark to test.

So what do you guys think?

Thanks,
Kris Katterjohn
Index: nmap.cc
===================================================================
--- nmap.cc     (revision 6658)
+++ nmap.cc     (working copy)
@@ -290,8 +290,8 @@
        "  --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address\n"
        "  --badsum: Send packets with a bogus TCP/UDP checksum\n"
        "OUTPUT:\n"
-       "  -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,\n"
-       "     and Grepable format, respectively, to the given filename.\n"
+       "  -oN/-oX/-oS/-oG/-oP <file>: Output scan in normal, XML, s|<rIpt kIddi3,\n"
+       "     Grepable, and Pcap format, respectively, to the given filename.\n"
        "  -oA <basename>: Output in the three major formats at once\n"
        "  -v: Increase verbosity level (use twice for more effect)\n"
        "  -d[level]: Set or increase debugging level (Up to 9 is meaningful)\n"
@@ -471,7 +471,7 @@
   char *idleProxy = NULL; /* The idle host used to "Proxy" an idle scan */
   int num_host_exp_groups;
   char *machinefilename = NULL, *kiddiefilename = NULL, 
-    *normalfilename = NULL, *xmlfilename = NULL;
+    *normalfilename = NULL, *xmlfilename = NULL, *pcapfilename = NULL;
   time_t now;
   struct tm *tm;
   HostGroupState *hstate = NULL;
@@ -563,6 +563,7 @@
       {"oS", required_argument, 0, 0},
       {"oH", required_argument, 0, 0},  
       {"oX", required_argument, 0, 0},  
+      {"oP", required_argument, 0, 0},  
       {"iL", required_argument, 0, 'i'},  
       {"iR", required_argument, 0, 0},
       {"sI", required_argument, 0, 0},  
@@ -831,6 +832,8 @@
        fatal("HTML output is not directly supported, though Nmap includes an XSL for transforming XML output into 
HTML.  See the man page.");
       } else if (strcmp(long_options[option_index].name, "oX") == 0) {
        xmlfilename = logfilename(optarg, tm);
+      } else if (strcmp(long_options[option_index].name, "oP") == 0) {
+       pcapfilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oA") == 0) {
        char buf[MAXPATHLEN];
        Snprintf(buf, sizeof(buf), "%s.nmap", logfilename(optarg, tm));
@@ -1246,6 +1249,11 @@
     log_open(LOG_SKID, o.append_output, kiddiefilename);
   if (xmlfilename)
     log_open(LOG_XML, o.append_output, xmlfilename);
+  if (pcapfilename) {
+    o.pcaplogfd = pcap_open_dead(DLT_RAW, 1500);
+    if (!(o.pcaplog = pcap_dump_open(o.pcaplogfd, pcapfilename)))
+      fatal("Failed to open pcap savefile %s for writing", pcapfilename);
+  }
 
   if (!o.interactivemode) {
     char tbuf[128];
@@ -2624,6 +2632,11 @@
 
   fflush(stderr);
   log_close(LOG_MACHINE|LOG_NORMAL|LOG_SKID);
+  if (o.pcaplog) {
+    pcap_dump_flush(o.pcaplog);
+    pcap_dump_close(o.pcaplog);
+    pcap_close(o.pcaplogfd);
+  }
   if (abt) abort();
   exit(1);
 }
Index: NmapOps.cc
===================================================================
--- NmapOps.cc  (revision 6658)
+++ NmapOps.cc  (working copy)
@@ -242,6 +242,8 @@
   maimonscan = idlescan = finscan = udpscan = ipprotscan = noresolve = 0;
   append_output = 0;
   memset(logfd, 0, sizeof(FILE *) * LOG_NUM_FILES);
+  pcaplogfd = NULL;
+  pcaplog = NULL;
   ttl = -1;
   badsum = 0;
   nmap_stdout = stdout;
Index: tcpip.cc
===================================================================
--- tcpip.cc    (revision 6658)
+++ tcpip.cc    (working copy)
@@ -1353,6 +1353,9 @@
 
  PacketTrace::trace(PacketTrace::SENT, packet, len); 
 
+ if (o.pcaplog)
+   log_pcap(NULL, (u_char *) packet, len);
+
 return res;
 }
 
@@ -1386,6 +1389,8 @@
     } else ethsd = eth->ethsd;
     res = eth_send(ethsd, eth_frame, 14 + packetlen);
     PacketTrace::trace(PacketTrace::SENT, packet, packetlen); 
+    if (o.pcaplog)
+      log_pcap(NULL, (u_char *) packet, packetlen);
     /* No need to close ethsd due to caching */
     free(eth_frame);
     eth_frame = NULL;
@@ -2062,6 +2067,9 @@
    PacketTrace::trace(PacketTrace::RCVD, (u8 *) alignedbuf, *len, rcvdtime);
  else PacketTrace::trace(PacketTrace::RCVD, (u8 *) alignedbuf, *len);
 
+ if (o.pcaplog)
+   log_pcap(&head, (u_char *) alignedbuf, *len);
+
  return alignedbuf;
 }
 
Index: output.h
===================================================================
--- output.h    (revision 6658)
+++ output.h    (working copy)
@@ -124,6 +124,7 @@
 #include "portlist.h"
 #include "nmap.h"
 #include "global_structures.h"
+#include <pcap.h>
 
 /* Prints the familiar Nmap tabular output showing the "interesting"
    ports found on the machine.  It also handles the Machine/Greppable
@@ -169,6 +170,8 @@
    it already exists.  If the file does not exist, it will be created */
 int log_open(int logt, int append, char *filename);
 
+void log_pcap(struct pcap_pkthdr *, u_char *, int);
+
 /* Output the list of ports scanned to the top of machine parseable
    logs (in a comment, unfortunately).  The items in ports should be
    in sequential order for space savings and easier to read output */
Index: output.cc
===================================================================
--- output.cc   (revision 6658)
+++ output.cc   (working copy)
@@ -1080,7 +1080,38 @@
   return 1;
 }
 
+/* Logs packet to pcap savefile.
+ *
+ * You can pass NULL for h: log_pcap will create a pcap_pkthdr based on the
+ * length and current time.  This is important for logging packets that are
+ * being sent.
+ *
+ * pkt must be an IP packet (no ARP), which starts at the header.
+ *
+ * len is the pkt length
+ */
+void log_pcap(struct pcap_pkthdr *h, u_char *pkt, int len)
+{
+       struct pcap_pkthdr th;
 
+       if (!o.pcaplog)
+               return;
+
+       if (!h) {
+               struct timeval tv;
+
+               h = &th;
+
+               gettimeofday(&tv, NULL);
+
+               th.ts = tv;
+               th.caplen = len;
+               th.len = len;
+       }
+
+       pcap_dump((u_char *) o.pcaplog, h, pkt);
+}
+
 /* The items in ports should be
    in sequential order for space savings and easier to read output.  Outputs
    the rangelist to the log stream given (such as LOG_MACHINE or LOG_XML) */
Index: NmapOps.h
===================================================================
--- NmapOps.h   (revision 6658)
+++ NmapOps.h   (working copy)
@@ -102,6 +102,7 @@
 #include "nmap.h"
 #include "global_structures.h"
 #include "output.h"
+#include <pcap.h>
 #include <string>
 
 class NmapOps {
@@ -305,6 +306,8 @@
   int append_output; /* Append to any output files rather than overwrite */
   FILE *logfd[LOG_NUM_FILES];
   FILE *nmap_stdout; /* Nmap standard output */
+  pcap_t *pcaplogfd;
+  pcap_dumper_t *pcaplog;
   int ttl; // Time to live
   int badsum;
   char *datadir;

Attachment: test.pcap
Description:


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

Current thread: