pscan.c
上传用户:jxr_002
上传日期:2007-01-05
资源大小:12k
文件大小:14k
- /*
- * pscan.c
- *
- * TCP/UDP/NIS/RPC scanner..
- * o scans TCP ports and prints the services running
- * o scans UDP ports and prints the services running (remote hosts only)
- * o dumps portmappers listing of RPC services
- * o prints available NIS maps
- *
- * UDP port scanning is kinda flakey.. but it works.. with the exception
- * of on your own host (netstat -a for christs sake).. anyway.. here
- * it is..
- *
- * - pluvius@dhp.com
- *
- * tested on SunOS 4.1.3_U1 and Linux 1.1.85
- * Also tested on OSF/1, courtesy of IETF.
- * compile: cc -o pscan -s pscan.c
- *
- * NOTE: when you do a NIS listing.. it MUST be the domain name that
- * you pass as the remote host.. otherwise this will not work.
- *
- * H* mods: use a normally refused TCP port to determine UDP RTT delay.
- * Much faster, and prevents the target from logging opened connections.
- * May behave oddly if some TCP ports are dropped by a filter, and doesn't
- * work on solaris cuz ICMP is *not* delivered to connected-UDP sockets.
- * See udp_scan.c in Satan for more info, and a solaris version that works
- * but needs root.
- *
- * If only one port arg given, just hit that port and report state.
- *
- * Added settable connect() timeout for tcp scan, with appropriate errors.
- * Useful for determining what TCP ports are being filtered out -- scan a
- * known machine behind a packet filter, and anything that wasn't refused
- * or open is being dropped. Ping first to get an idea of the right
- * timeout to use; otherwise defaults to 3 sec.
- *
- * -->
- * connect time outs is broke on linux.. ripped it out. <p.
- * also yanked the --wait command thingy
- *
- *
- * TODO: fix domainname shit, maybe rip code from satan yp_chk
- *
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <rpc/rpc.h>
- #include <rpc/xdr.h>
- #include <rpc/pmap_prot.h>
- #include <rpc/pmap_clnt.h>
- #include <rpcsvc/yp_prot.h>
- #include <rpcsvc/ypclnt.h>
- #include <errno.h>
- #include <signal.h>
- #include <setjmp.h>
- /* xxx: these are sometimes defined by .h files as below for getopt. I'll
- fix it later... */
- extern int errno;
- #ifndef BSD4_4
- extern char *sys_errlist[];
- #endif
- #ifndef INADDR_NONE
- #define INADDR_NONE 0xffffffff
- #endif
- #ifdef __GNU_LIBRARY__ /* this is part of the GNU C lib */
- #include <getopt.h>
- #else
- extern int optind;
- extern char *optarg;
- #endif
- #define DEFAULT_LOW_PORT 1
- #define DEFAULT_HIGH_PORT 10240
- #define RTT_PORT 3 /* for UDP-RTT hack */
- #define MAJOR_VERSION 1
- #define MINOR_VERSION 4
- static char sccsid[] = "@(#) pscan.c 1.4 (pluvius+hobbit) 04/15/95";
- typedef enum {
- false,
- true
- } my_bool;
- my_bool Single = false; /* use booleans for all if-ed vars */
- typedef enum {
- s_none,
- s_tcp,
- s_udp,
- s_rpc,
- s_nis
- } scan_t;
- #ifdef __GNU_LIBRARY__
- static struct option long_options[] = {
- {"tcp", 0, 0, 0},
- {"udp", 0, 0, 0},
- {"rpc", 0, 0, 0},
- {"nis", 0, 0, 0},
- {"help", 0, 0, 0},
- {"version", 0, 0, 0},
- {0,0,0,0}
- };
- #endif
- struct {
- char *alias;
- char *mapname;
- my_bool inuse;
- } yp_maps[] = {
- {"passwd", "passwd.byname", false},
- {"group", "group.byname", false},
- {"networks", "networks.byaddr", false},
- {"hosts", "hosts.byaddr", false},
- {"protocols", "protocols.bynumber", false},
- {"services", "services.byname", false},
- {"aliases", "mail.aliases", false},
- {"ethers", "ethers.byname", false},
- {NULL, NULL, false}
- };
- scan_t scan_type;
- char remote_host[200];
- char remote_ip[20];
- char remote_domain[128];
- int low_port;
- int high_port;
- void print_version(s)
- {
- fprintf(stderr,"%s version %d.%dn",s,MAJOR_VERSION,MINOR_VERSION);
- exit(0);
- }
- void print_usage(s)
- {
- fprintf(stderr,"usage %s: <scan type> <host> [low port] [high port]n",s);
- fprintf(stderr,"where scan type is one of:n");
- #ifdef __GNU_LIBRARY__
- fprintf(stderr," --tcp, -t - TCP port scann");
- fprintf(stderr," --udp, -u - UDP port scann");
- fprintf(stderr," --rpc, -r - RPC service listn");
- fprintf(stderr," --nis, -n - NIS map listingn");
- fprintf(stderr," --version, -v - Print version informationn");
- fprintf(stderr," --help, -h - Print usage informationn");
- #else
- fprintf(stderr," -t - TCP port scann");
- fprintf(stderr," -u - UDP port scann");
- fprintf(stderr," -r - RPC service listn");
- fprintf(stderr," -n - NIS map listingn");
- fprintf(stderr," -v - Print version informationn");
- fprintf(stderr," -h - Print usage informationn");
- #endif
- fprintf(stderr,"n");
- exit(0);
- }
- /* XXX: document -d after it works, maybe make -u take an arg? */
- void get_args(n,v)
- int n;
- char *v[];
- {
- int c;
- int opt_ind;
- memset (remote_domain, 0, 8);
- scan_type = s_none;
- while (true) {
- #ifdef __GNU_LIBRARY__
- c = getopt_long(n,v,"turnhvd:",long_options,&opt_ind);
- #else
- c = getopt(n,v,"turnhvd:");
- #endif
- if (c == -1)
- break;
- switch(c) {
- #ifdef __GNU_LIBRARY__
- case 0:
- opt_ind++; /* index's are one less than the scan type */
- if (opt_ind == 5)
- print_usage(v[0]);
- if (opt_ind == 6)
- print_version(v[0]);
- scan_type = opt_ind;
- break;
- #endif
- case 't':
- scan_type = s_tcp;
- break;
- case 'u':
- scan_type = s_udp;
- break;
- case 'r':
- scan_type = s_rpc;
- break;
- case 'n':
- scan_type = s_nis;
- break;
- case 'd':
- strcpy (remote_domain, optarg);
- break;
- case 'v':
- print_version(v[0]);
- break;
- case 'h':
- case '?':
- print_usage(v[0]);
- break;
- }
- }
- low_port = DEFAULT_LOW_PORT;
- high_port = DEFAULT_HIGH_PORT;
- for (opt_ind = 0;optind < n;optind++) {
- switch(opt_ind++) {
- case 0: /* remote host */
- strncpy(remote_host,v[optind],199);
- break;
- case 1: /* low port */
- low_port = atoi(v[optind]);
- Single = true;
- break;
- case 2: /* high port */
- high_port = atoi(v[optind]);
- Single = false;
- break;
- }
- }
- if (Single)
- high_port = low_port;
- if ((opt_ind == 0) || (scan_type == s_none)) {
- fprintf(stderr,"error: you must specify a scan type and a hostn");
- print_usage(v[0]);
- }
- }
- void check_args()
- {
- struct hostent *host;
- host = gethostbyname(remote_host);
- if (host == NULL) {
- #if 0
- /* this sscanf and related code crashes on sunos, beats the shit out of me why.
- In any case, punt -- just check the arg's validity with inet_addr and copy
- it directly. */
- unsigned char a,b,c,d,n;
- char addr[5];
- /* hmm.. perhaps it was a dotted quad entered.. */
- n = sscanf(remote_host,"%u.%u.%u.%u",&a,&b,&c,&d);
- if (n != 4) {
- fprintf(stderr,"error: host '%s' not foundn",remote_host);
- exit(1);
- }
- addr[0] = a;
- addr[1] = b;
- addr[2] = c;
- addr[3] = d;
- host = gethostbyaddr(addr,4,AF_INET);
- #endif /* 0 */
- /* ... we'll do it this way instead. */
- unsigned long n;
- n = inet_addr(remote_host);
- if (n == INADDR_NONE) {
- fprintf(stderr,"error: host '%s' not foundn",remote_host);
- exit(1);
- }
- strcpy (remote_ip, remote_host);
- host = gethostbyaddr(remote_ip,4,AF_INET);
- if (host == NULL) {
- fprintf(stderr,"error: host '%s' not foundn",remote_host);
- exit(1);
- }
- } else { /* gethostbyname */
- sprintf(remote_ip,"%u.%u.%u.%u",
- (unsigned char) host->h_addr_list[0][0],
- (unsigned char) host->h_addr_list[0][1],
- (unsigned char) host->h_addr_list[0][2],
- (unsigned char) host->h_addr_list[0][3]);
- }
- }
- void print_args()
- {
- static char *opt_table[] = {
- "tcp","udp","rpc","nis"
- };
- if (!Single) {
- fprintf(stdout,"scanning host %s's %s ports ",remote_host,
- opt_table[scan_type-1]);
- if (scan_type < 3) {
- fprintf(stdout,"%d through %d",low_port,high_port);
- }
- fprintf(stdout,"n");
- } /* single */
- }
- void ping_host()
- {
- int s,slen;
- struct sockaddr_in addr;
- char out_string[100];
- /* What p. didn't explain here is that this is a simple way of delaying for
- the expected RTT of the link, i.e. enough time for UDP out, ICMP back,
- causing the next UDP write to error out. Turns out that trying to connect
- to a normally refused port is faster, although occasionally misses one. _H*/
- /* send some stuff and wait for it to come back... ping for us */
- /* non-root folks */
- s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(remote_ip);
- addr.sin_port = htons(RTT_PORT);
- /* timeout code didn't work on linux.. scrap it. <p. */
- connect(s, (struct sockaddr*) &addr, sizeof(addr));
- close(s);
- }
- int scan()
- {
- int soc;
- struct sockaddr_in addr;
- struct servent *serv;
- int port,rc,addr_len,opt;
- if (scan_type >= 3) /* this proc only does tcp and udp */
- return;
- errno = 0;
- for (port = low_port;port <= high_port;port++) {
- if (scan_type == s_tcp) {
- soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- } else if (scan_type == s_udp) {
- soc = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
- } else
- return;
- if (soc < 0) {
- fprintf(stderr,"error: socket() failedn");
- return;
- }
- /* this makes scan drop to a crawl on linux... */
- /*rc = setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));*/
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(remote_ip);
- addr.sin_port = htons(port);
- addr_len = sizeof(addr);
- rc = connect(soc, (struct sockaddr*) &addr, addr_len);
- if (scan_type == s_udp) {
- char out_text[100];
- strncpy(out_text,"k0ad kidz uv th3 WeRlD UN1t3n",99);
- rc = write(soc,out_text,strlen(out_text));
- ping_host(); /* wait for icmp's */
- rc = write(soc,out_text,strlen(out_text));
- }
- close(soc);
- /* for tcp, if anything other than refused, we want to know about it. Always
- print status for a single-port run. */
- if (!Single)
- if ((rc < 0) && (scan_type == s_tcp) && (errno == ECONNREFUSED))
- continue;
- if ((rc < 0) && (scan_type == s_udp))
- continue;
- if (scan_type == s_tcp)
- serv = getservbyport(htons(port),"tcp");
- else if (scan_type == s_udp) {
- serv = getservbyport(htons(port),"udp");
- rc = 0; /* fake out below msg */
- }
- else
- return;
- fprintf(stdout,"port %d (%s) %sn", port,
- (serv == NULL)?"UNKNOWN": serv->s_name,
- (rc == 0) ? "open" : sys_errlist[errno]);
- fflush (stdout);
- }
- }
- int callback_proc(is,ik,ikl,iv,ivl,id)
- int is;
- char *ik;
- int ikl;
- char *iv;
- int ivl;
- char *id;
- {
- if (is != YP_TRUE)
- return is;
- return 0;
- }
- void nis_dump()
- {
- int i,rc;
- char *domainname;
- char *map;
- struct ypall_callback callback;
- if (remote_domain[0])
- domainname = &remote_domain[0];
- else
- domainname = &remote_host[0];
- for (i = 0;yp_maps[i].mapname != NULL;i++) {
- callback.foreach = callback_proc;
- callback.data = NULL;
- map = yp_maps[i].mapname;
- rc = yp_all(domainname,map,&callback);
- switch(rc) {
- case 0:
- printf("%-10.10s is availablen",yp_maps[i].alias);
- break;
- case YPERR_YPBIND:
- fprintf(stderr,"error: server is not running ypbindn");
- exit(1);
- break;
- default:
- fprintf(stderr,"error: %s in domain %sn",
- yperr_string(rc), domainname);
- exit(1);
- }
- }
- }
- /* this routine basically ripped from rpcinfo -p */
- void rpc_scan()
- {
- struct sockaddr_in server_addr;
- register struct hostent *hp;
- struct pmaplist *head = NULL;
- int socket = RPC_ANYSOCK;
- struct timeval minutetimeout;
- register CLIENT *client;
- struct rpcent *rpc;
-
- minutetimeout.tv_sec = 60;
- minutetimeout.tv_usec = 0;
- server_addr.sin_addr.s_addr = inet_addr(remote_ip);
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(111);
- if ((client = clnttcp_create(&server_addr, PMAPPROG,
- PMAPVERS, &socket, 50, 500)) == NULL) {
- clnt_pcreateerror("rpcinfo: can't contact portmapper");
- exit(1);
- }
- if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
- xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
- fprintf(stderr, "rpcinfo: can't contact portmapper: ");
- clnt_perror(client, "rpcinfo");
- exit(1);
- }
- if (head == NULL) {
- printf("No remote programs registered.n");
- } else {
- printf(" program vers proto portn");
- for (; head != NULL; head = head->pml_next) {
- printf("%10ld%5ld",
- head->pml_map.pm_prog,
- head->pml_map.pm_vers);
- if (head->pml_map.pm_prot == IPPROTO_UDP)
- printf("%6s", "udp");
- else if (head->pml_map.pm_prot == IPPROTO_TCP)
- printf("%6s", "tcp");
- else
- printf("%6ld", head->pml_map.pm_prot);
- printf("%7ld", head->pml_map.pm_port);
- rpc = getrpcbynumber(head->pml_map.pm_prog);
- if (rpc)
- printf(" %sn", rpc->r_name);
- else
- printf("n");
- }
- }
- }
- int main(argc,argv)
- int argc;
- char *argv[];
- {
- get_args(argc,argv);
- check_args();
- print_args();
- /* this will only do tcp and udp, otherwise returns without doing anything */
- switch (scan_type) {
- case s_tcp:
- scan();
- break;
- case s_udp:
- scan();
- break;
- case s_rpc:
- rpc_scan();
- break;
- case s_nis:
- nis_dump();
- break;
- }
- return 0;
- }