Nmap Announce mailing list archives
Nmap stub v1
From: "rain.forest.puppy" <rfpuppy () iname com>
Date: Tue, 29 Dec 1998 21:57:45 -0600
Hello all, I was thinking about the whole "nmap's only a scanner/make it an exploit scanner" issue, and think I may have come up with a good solution. Personally, I stradle the fence...while I think nmap should be left alone to do only scanning, it does provide good info to use right then and there to check for exploits. So, I whipped up the nmap stub. It's simple. It will read in human-readable output from nmap (for reasons I'll get to), reconstruct a simple port list, and then run whatever code you want. So, basically, you get all the same info (list of TCP & UDP ports, IP, hostname & OS name when available). I like this approach, as I can first see what nmap spits out, edit it to my heart's content, and then feed it to the stub. That way you can also paste together outputs from multiple machines into one big text file, and then run the stub on that. The reason why I did the human output rather than the machine output is because I found it easier to parse. :) Also because I tend to forget to specify an output file (but I can always look at the session log to catch the output). If someone wants to code the parser for the machine output, let me know. I personally plan to include support for nlog's db format next (and then you can just run nlog's machine to nlog db converter on it, then feed the nlog db into the stub). I've only tested this code on Intel RedHat 5.2. If it doesn't work on other platforms, sorry. If you can make it work on other platforms, even better. And if you can improve my lousy coding ('bucket-load-o-sscanfs'), great. Also, I don't currently have a place to stick the newest versions of the stub for public download. Anyone want to volunteer approx. 10K of space on a FTP/web server? :) Lastly, I'm going to play around porting Ajax's vulnerability database to use the stub...if anyone's interested. Cheers, .rain.forest.puppy rfpuppy () iname com ------ begin sloppy code -------- /*************************************************************** nmap stub / v1.0 This file reads in nmap (v2.x human) output, puts it into port and host structures, and then can call whatever routines you want (per host) to check for exploits, etc. If you have any suggestions, fixes, etc, let me know rfpuppy () iname com .rain.forest.puppy. ---------------------------------------------------------------- global information the stub provides: ----In INDEX mode:---- int tcp_ports[65535] int udp_ports[65535] These two structures contain the port information (that actual state of the port). Initially set to 0 (port not found), changed to 1 (open). So, to check if port 80 (http) is open: if(tcp_ports[80]){ //port is open..// } ---In LIST mode:---- struct portnode{ unsigned int port; unsigned int state;} portnode tcp_ports[2048] portnode udp_ports[2048] Use in conjunction with tpnum/upnum (total number of ports). Example: for(int x=0; x < tpnum; x++){ // do something with tcp_ports[x] // } Perl equivalent: foreach $found_port (@port_list) { // do whatever // } ----In all modes:---- char name[1024] char ip[1024] char os[1024] unsigned int tpnum unsigned int upnum int return_value Resolved name of host (NULL string if not known), IP address in string format, and OS guess (if available...NULL string if not known). Tpnum is the number of tcp ports in list; upnum is the number of udp ports in list. Return_value is what's given when the program exits. ---------------------------------------------------------------- Todo: read in actual state and adjust port value (tcp_ports[x] in INDEX, tcp_ports[x].state in LIST). Figure 1 for open, 2 for filtered, 3 for firewalled, etc. ****************************************************************/ #include <stdio.h> /* define INDEX for index of ports, undefine INDEX for list of ports */ #define INDEX /* define STATIC_FILE to specify a specific file to always open. Undefine it to take it from ARGV */ #undef STATIC_FILE /* V---- remove the const if you want to change the debug value inline */ const int debug=0; /* set to 1 just to see what's going on */ #ifdef STATIC_FILE #define STATIC_FILE_NAME "nmap.out" #endif #ifdef INDEX int tcp_ports[65535]; int udp_ports[65535]; #define MAX 65535 #else struct portnode { unsigned int port; unsigned int state; } portnode; struct portnode tcp_ports[2048]; struct portnode udp_ports[2048]; #define MAX 2048 #endif char name[1024]; char ip[1024], os[1024]; unsigned int tpnum=0; unsigned int upnum=0; int return_value=0; int y; void yourfunc(void){ /*********************************************************** Insert your function/code here to be called per host ***********************************************************/ /* this is example code */ #ifdef INDEX /* demo of how to access index of ports */ printf("Checking %s, ip: %s", name, ip); if (os[0] != '\0') printf(" OS: %s\n", os); else printf("\n"); printf("Found %i TCP ports, %i UDP ports\n", tpnum, upnum); if (tcp_ports[80]) printf("Seem to be running a web server\n"); if (tcp_ports[21]) printf("Seem to be running a ftp server\n"); if (tcp_ports[23]) printf("Seem to be running telnetd\n"); printf("\n"); #else /* demo of how to access list of ports */ printf("Checking %s, ip: %s", name, ip); if (os[0] != NULL) printf(" OS: %s\n", os); else printf("\n"); printf("Found %i TCP ports, %i UDP ports\n", tpnum, upnum); printf("Open TCP ports:"); for (y = 0; y < tpnum; y++) printf(" %i", tcp_ports[y].port); printf("\n\n"); #endif /* end of example code */ /** End of your code/function *****************************/ } FILE *fp; char line[1024], copy[1024]; char s1[1024], s2[1024], s3[1024]; int c,tp; unsigned int x, gothost=0; int main(int argc, char *argv[]){ char filename[256]; /* shameless plug. ;-) */ printf("Nmap stub by .rain.forest.puppy. rfpuppy () iname com\n"); for (x = 0; x < MAX; x++) #ifdef INDEX tcp_ports[x] = udp_ports[x] = 0; #else tcp_ports[x].state=tcp_ports[x].port=udp_ports[x].state=udp_ports[x].port=0; #endif #ifdef STATIC_FILE filename=STATIC_FILE_NAME; #else if (argc < 2){ printf("You need to specify the nmap input file on the commandline\n"); return -1;} strncpy(filename,argv[1],255); #endif /*********************************************************** If you're going to process commandline switches, here's a good place to do it. If you do commandline switches, I suggest you define STATIC_FILE, and then make a switch to specify the filename. Put the input file name into 'filename'. By defining STATIC_FILE, you'll have a default filename (defined in STATIC_FILE_NAME) ***********************************************************/ /* your getopts code */ /**********************************************************/ if ((fp=fopen(filename,"r")) == NULL){ perror("fopen"); return -1;} fgets(line,sizeof(line)-1,fp); do { /* main decoding loop */ if(c = sscanf(line,"Interesting ports on %1023s (%1023[^)]):",s1,s2)){ if(gothost){ /* we run function on first host when we start the record for the second host */ yourfunc(); for (x=0; x < MAX; x++) #ifdef INDEX tcp_ports[x]=udp_ports[x]=0; #else tcp_ports[x].state=tcp_ports[x].port=udp_ports[x].state=udp_ports[x].port=0; #endif strcpy(name,"\0"); /* no need to clear ip, as it */ strcpy(os,"\0"); /* will be overwritten below */ tpnum = upnum = 0; } gothost = 1; if (c == 2){ strncpy(name, s1, 1024); strncpy(ip, s2, 1024); } else sscanf(s1, "(%1024[^)])", ip); if (debug) printf("Setting hostname: %s ip: %s\n", s1, s2); fgets(line,sizeof(line)-1,fp); } if(!strcmp(line,"Port State Protocol Service\n")){ if (debug) printf("Adding ports:"); fgets(line, sizeof(line)-1,fp); while(strcmp(line, "\n")){ sscanf(line,"%i%20[ ]%20[^ ]%30[ ]%20[^ ]%1024s",&tp,s1,s2,s1,s3,s1); if (debug) printf(" %i/%s (%s)",tp,s3,s2); if(!strncmp(s3,"tcp",1023)) { #ifdef INDEX tcp_ports[tp]=1; #else tcp_ports[tpnum].port=tp; tcp_ports[tpnum].state=1; #endif tpnum++; } else { #ifdef INDEX udp_ports[tp]=1; #else udp_ports[tpnum].port=tp; udp_ports[tpnum].state=1; #endif upnum++;} fgets(line, sizeof(line)-1, fp);} if (debug) printf("\nAdded %i TCP ports, %i UDP ports\n",tpnum,upnum); fgets(line, sizeof(line) - 1, fp);} if(sscanf(line,"Remote operating system guess: %1024[^\n]", s1)){ strncpy(os, s1, 1024); if (debug) printf("OS: %s\n", s1); } } while(fgets(line, sizeof(line) - 1, fp)); if (gothost) yourfunc(); /* catch the last host */ fclose(fp); /*********************************************************** Do any cleanup you need to here ***********************************************************/ return return_value;}
Current thread:
- Nmap stub v1 rain.forest.puppy (Dec 29)