📄 output.cc
字号:
fatal("Failed to open %s output file %s for writing", logtypes[i], filename); } return 1;}/* 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) */static void output_rangelist_given_ports(int logt, unsigned short *ports, int numports) {int i, previous_port = -2, range_start = -2, port;char outpbuf[128]; for(i=0; i <= numports; i++) { port = (i < numports)? ports[i] : 0xABCDE; if (port != previous_port + 1) { outpbuf[0] = '\0'; if (range_start != previous_port && range_start != -2) sprintf(outpbuf, "-%hu", previous_port); if (port != 0xABCDE) { if (range_start != -2) strcat(outpbuf, ","); sprintf(outpbuf + strlen(outpbuf), "%hu", port); } if (*outpbuf) log_write(logt, "%s", outpbuf); range_start = port; } previous_port = port; }}/* 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 */void output_ports_to_machine_parseable_output(struct scan_lists *ports, int tcpscan, int udpscan, int protscan) { int tcpportsscanned = ports->tcp_count; int udpportsscanned = ports->udp_count; int protsscanned = ports->prot_count; log_write(LOG_MACHINE, "# Ports scanned: TCP(%d;", tcpportsscanned); if (tcpportsscanned) output_rangelist_given_ports(LOG_MACHINE, ports->tcp_ports, tcpportsscanned); log_write(LOG_MACHINE, ") UDP(%d;", udpportsscanned); if (udpportsscanned) output_rangelist_given_ports(LOG_MACHINE, ports->udp_ports, udpportsscanned); log_write(LOG_MACHINE, ") PROTOCOLS(%d;", protsscanned); if (protsscanned) output_rangelist_given_ports(LOG_MACHINE, ports->prots, protsscanned); log_write(LOG_MACHINE, ")\n"); log_flush_all();}/* Simple helper function for output_xml_scaninfo_records */static void doscaninfo(char *type, char *proto, unsigned short *ports, int numports) { log_write(LOG_XML, "<scaninfo type=\"%s\" protocol=\"%s\" numservices=\"%d\" services=\"", type, proto, numports); output_rangelist_given_ports(LOG_XML, ports, numports); log_write(LOG_XML, "\" />\n");}/* Similar to output_ports_to_machine_parseable_output, this function outputs the XML version, which is scaninfo records of each scan requested and the ports which it will scan for */void output_xml_scaninfo_records(struct scan_lists *scanlist) { if (o.synscan) doscaninfo("syn", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.ackscan) doscaninfo("ack", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.bouncescan) doscaninfo("bounce", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.connectscan) doscaninfo("connect", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.nullscan) doscaninfo("null", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.xmasscan) doscaninfo("xmas", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.windowscan) doscaninfo("window", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.maimonscan) doscaninfo("maimon", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.finscan) doscaninfo("fin", "tcp", scanlist->tcp_ports, scanlist->tcp_count); if (o.udpscan) doscaninfo("udp", "udp", scanlist->udp_ports, scanlist->udp_count); if (o.ipprotscan) doscaninfo("ipproto", "ip", scanlist->prots, scanlist->prot_count); log_flush_all();}/* Prints the MAC address (if discovered) to XML output */static void print_MAC_XML_Info(Target *currenths) { const u8 *mac = currenths->MACAddress(); char macascii[32]; char vendorstr[128]; char *xml_mac = NULL; if (mac) { const char *macvendor = MACPrefix2Corp(mac); Snprintf(macascii, sizeof(macascii), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); if (macvendor) { xml_mac = xml_convert(macvendor); Snprintf(vendorstr, sizeof(vendorstr), " vendor=\"%s\"", xml_mac); free(xml_mac); } else vendorstr[0] = '\0'; log_write(LOG_XML, "<address addr=\"%s\" addrtype=\"mac\"%s />\n", macascii, vendorstr); }}/* Helper function to write the status and address/hostname info of a host into the XML log */static void write_xml_initial_hostinfo(Target *currenths, const char *status) { log_write(LOG_XML,"<status state=\"%s\" reason=\"%s\"/>\n", status, reason_str(currenths->reason.reason_id, SINGULAR)); log_write(LOG_XML,"<address addr=\"%s\" addrtype=\"%s\" />\n", currenths->targetipstr(), (o.af() == AF_INET)? "ipv4" : "ipv6"); print_MAC_XML_Info(currenths); if (*currenths->HostName()) { log_write(LOG_XML, "<hostnames><hostname name=\"%s\" type=\"PTR\" /></hostnames>\n", currenths->HostName()); } else /* If machine is up, put blank hostname so front ends know that no name resolution is forthcoming */ if (strcmp(status, "up") == 0) log_write(LOG_XML, "<hostnames />\n"); log_flush_all();}/* Writes host status info to the log streams (including STDOUT). An example is "Host: 10.11.12.13 (foo.bar.example.com)\tStatus: Up\n" to machine log. resolve_all should be passed nonzero if the user asked for all hosts (even down ones) to be resolved */void write_host_status(Target *currenths, int resolve_all) { char hostname[1200]; char reasonbuf[512]; if (o.listscan) { /* write "unknown" to stdout, machine, and xml */ log_write(LOG_PLAIN, "Host %s not scanned\n", currenths->NameIP(hostname, sizeof(hostname))); log_write(LOG_MACHINE, "Host: %s (%s)\tStatus: Unknown\n", currenths->targetipstr(), currenths->HostName()); write_xml_initial_hostinfo(currenths, "unknown"); } else if (currenths->wierd_responses) { /* SMURF ADDRESS */ /* Write xml "down" or "up" based on flags and the smurf info */ write_xml_initial_hostinfo(currenths, (currenths->flags & HOST_UP)? "up" : "down"); log_write(LOG_XML, "<smurf responses=\"%d\" />\n", currenths->wierd_responses); log_write(LOG_MACHINE,"Host: %s (%s)\tStatus: Smurf (%d responses)\n", currenths->targetipstr(), currenths->HostName(), currenths->wierd_responses); if (o.pingscan) log_write(LOG_PLAIN,"Host %s seems to be a subnet broadcast address (returned %d extra pings).%s\n", currenths->NameIP(hostname, sizeof(hostname)), currenths->wierd_responses, (currenths->flags & HOST_UP)? " Note -- the actual IP also responded." : ""); else { log_write(LOG_PLAIN,"Host %s seems to be a subnet broadcast address (returned %d extra pings). %s.\n", currenths->NameIP(hostname, sizeof(hostname)), currenths->wierd_responses, (currenths->flags & HOST_UP)? " Still scanning it due to ping response from its own IP" : "Skipping host"); } } else if (o.pingscan) { if(o.reason && currenths->flags & HOST_UP) Snprintf(reasonbuf, 512, "%s.\n", target_reason_str(currenths)); else Snprintf(reasonbuf, 512, ".\n"); write_xml_initial_hostinfo(currenths, (currenths->flags & HOST_UP)? "up" : "down"); if (currenths->flags & HOST_UP) { log_write(LOG_PLAIN,"Host %s appears to be up%s", currenths->NameIP(hostname, sizeof(hostname)), reasonbuf); log_write(LOG_MACHINE,"Host: %s (%s)\tStatus: Up\n", currenths->targetipstr(), currenths->HostName()); } else if (o.verbose || resolve_all) { if (resolve_all) log_write(LOG_PLAIN,"Host %s appears to be down.\n", currenths->NameIP(hostname, sizeof(hostname))); else log_write(LOG_STDOUT,"Host %s appears to be down.\n", currenths->NameIP(hostname, sizeof(hostname))); log_write(LOG_MACHINE, "Host: %s (%s)\tStatus: Down\n", currenths->targetipstr(), currenths->HostName()); } } else { /* Normal case (non ping/list scan or smurf address) */ write_xml_initial_hostinfo(currenths, (currenths->flags & HOST_UP)? "up" : "down"); if (o.verbose) { if (currenths->flags & HOST_UP) { log_write(LOG_STDOUT, "Host %s appears to be up ... good.\n", currenths->NameIP(hostname, sizeof(hostname))); } else { if (resolve_all) { log_write(LOG_PLAIN,"Host %s appears to be down, skipping it.\n", currenths->NameIP(hostname, sizeof(hostname))); } else { log_write(LOG_STDOUT,"Host %s appears to be down, skipping it.\n", currenths->NameIP(hostname, sizeof(hostname))); } log_write(LOG_MACHINE, "Host: %s (%s)\tStatus: Down\n", currenths->targetipstr(), currenths->HostName()); } } }}/* Returns -1 if adding the entry is not possible because it would overflow. Otherwise it returns the new number of entries. Note that only unique entries are added. Also note that *numentries is incremented if the candidate is added. arrsize is the number of char * members that fit into arr */static int addtochararrayifnew(char *arr[], int *numentries, int arrsize, char *candidate) { int i; // First lets see if the member already exists for(i=0; i < *numentries; i++) { if (strcmp(arr[i], candidate) == 0) return *numentries; } // Not already there... do we have room for a new one? if (*numentries >= arrsize ) return -1; // OK, not already there and we have room, so we'll add it. arr[*numentries] = candidate; (*numentries)++; return *numentries;}/* guess is true if we should print guesses */#define MAX_OS_CLASSMEMBERS 8static void printosclassificationoutput(const struct OS_Classification_Results *OSR, bool guess) { int classno, i, familyno; int overflow = 0; /* Whether we have too many devices to list */ char *types[MAX_OS_CLASSMEMBERS]; char fullfamily[MAX_OS_CLASSMEMBERS][128]; // "[vendor] [os family]" double familyaccuracy[MAX_OS_CLASSMEMBERS]; // highest accuracy for this fullfamily char familygenerations[MAX_OS_CLASSMEMBERS][48]; // example: "4.X|5.X|6.X" int numtypes = 0, numfamilies=0; char tmpbuf[1024]; for(i=0; i < MAX_OS_CLASSMEMBERS; i++) { familygenerations[i][0] = '\0'; familyaccuracy[i] = 0.0; } if (OSR->overall_results == OSSCAN_SUCCESS) { /* Print the OS Classification results to XML output */ for (classno=0; classno < OSR->OSC_num_matches; classno++) { // Because the OS_Generation filed is optional if (OSR->OSC[classno]->OS_Generation) { Snprintf(tmpbuf, sizeof(tmpbuf), " osgen=\"%s\"", OSR->OSC[classno]->OS_Generation); } else tmpbuf[0] = '\0'; { char *xml_type, *xml_vendor, *xml_class; xml_type = xml_convert(OSR->OSC[classno]->Device_Type); xml_vendor = xml_convert(OSR->OSC[classno]->OS_Vendor); xml_class = xml_convert(OSR->OSC[classno]->OS_Family); log_write(LOG_XML, "<osclass type=\"%s\" vendor=\"%s\" osfamily=\"%s\"%s accuracy=\"%d\" />\n", xml_type, xml_vendor, xml_class, tmpbuf, (int) (OSR->OSC_Accuracy[classno] * 100)); free(xml_type); free(xml_vendor); free(xml_class); } } // Now to create the fodder for normal output for (classno=0; classno < OSR->OSC_num_matches; classno++) { /* We have processed enough if any of the following are true */ if (!guess && OSR->OSC_Accuracy[classno] < 1.0 || OSR->OSC_Accuracy[classno] <= OSR->OSC_Accuracy[0] - 0.1 || OSR->OSC_Accuracy[classno] < 1.0 && classno > 9) break; if (addtochararrayifnew(types, &numtypes, MAX_OS_CLASSMEMBERS, OSR->OSC[classno]->Device_Type) == -1) overflow = 1; // If family and vendor names are the same, no point being redundant if (strcmp(OSR->OSC[classno]->OS_Vendor, OSR->OSC[classno]->OS_Family) == 0) Strncpy(tmpbuf, OSR->OSC[classno]->OS_Family, sizeof(tmpbuf)); else Snprintf(tmpbuf, sizeof(tmpbuf), "%s %s", OSR->OSC[classno]->OS_Vendor, OSR->OSC[classno]->OS_Family); // Let's see if it is already in the array for(familyno = 0; familyno < numfamilies; familyno++) { if (strcmp(fullfamily[familyno], tmpbuf) == 0) { // got a match ... do we need to add the generation? if (OSR->OSC[classno]->OS_Generation && !strstr(familygenerations[familyno], OSR->OSC[classno]->OS_Generation)) { int flen = strlen(familygenerations[familyno]); // We add it, preceded by | if something is already there if (flen + 2 + strlen(OSR->OSC[classno]->OS_Generation) >= sizeof(familygenerations[familyno])) fatal("buffer 0verfl0w of familygenerations"); if (*familygenerations[familyno]) strcat(familygenerations[familyno], "|"); strncat(familygenerations[familyno], OSR->OSC[classno]->OS_Generation, sizeof(familygenerations[familyno]) - flen - 1); } break; } } if (familyno == numfamilies) { // Looks like the new family is not in the list yet. Do we have room to add it? if (numfamilies >= MAX_OS_CLASSMEMBERS) { overflow = 1; break; } // Have space, time to add... Strncpy(fullfamily[numfamilies], tmpbuf, 128); if (OSR->OSC[classno]->OS_Generation) Strncpy(familygenerations[numfamilies], OSR->OSC[classno]->OS_Generation, 48); familyaccuracy[numfamilies] = OSR->OSC_Accuracy[classno]; numfamilies++; } } if (!overflow && numfamilies >= 1) { log_write(LOG_PLAIN, "Device type: "); for(classno=0; classno < numtypes; classno++) log_write(LOG_PLAIN, "%s%s", types[classno], (classno < numtypes - 1)? "|" : ""); log_write(LOG_PLAIN, "\nRunning%s: ", (familyaccuracy[0] < 1.0)? " (JUST GUESSING) " : ""); for(familyno = 0; familyno < numfamilies; familyno++) { if (familyno > 0) log_write(LOG_PLAIN, ", "); log_write(LOG_PLAIN, "%s", fullfamily[familyno]); if (*familygenerations[familyno]) log_write(LOG_PLAIN, " %s", familygenerations[familyno]); if (familyaccuracy[familyno] < 1.0) log_write(LOG_PLAIN, " (%d%%)", (int) (familyaccuracy[familyno] * 100)); } log_write(LOG_PLAIN, "\n"); } } log_flush_all(); return;}/* Prints the MAC address if one was found for the target (generally this means that the target is directly connected on an ethernet network. This only prints to human output -- XML is handled by a separate call ( print_MAC_XML_Info ) because it needs to be printed in a certain place to conform to DTD. */void printmacinfo(Target *currenths) { const u8 *mac = currenths->MACAddress(); char macascii[32]; if (mac) { const char *macvendor = MACPrefix2Corp(mac); Snprintf(macascii, sizeof(macascii), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); log_write(LOG_PLAIN, "MAC Address: %s (%s)\n", macascii, macvendor? macvendor : "Unknown"); }}/* Prints the formatted OS Scan output to stdout, logfiles, etc (but only if an OS Scan was performed).*/void printosscanoutput(Target *currenths) { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -