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:
- [PATCH] New output format (-oP): Pcap savefile Kris Katterjohn (Dec 30)