pscan2.c
上传用户:chzhceng
上传日期:2007-01-05
资源大小:5k
文件大小:15k
源码类别:

扫描程序

开发平台:

Unix_Linux

  1. /* http://www.cotse.com  Fear the swimming Elephant! */
  2. /*
  3.  * pscan.c
  4.  *
  5.  *   TCP/UDP/NIS/RPC scanner..
  6.  *     o scans TCP ports and prints the services running
  7.  *     o scans UDP ports and prints the services running (remote hosts only)
  8.  *     o dumps portmappers listing of RPC services
  9.  *     o prints available NIS maps 
  10.  *
  11.  *   UDP port scanning is kinda flakey.. but it works.. with the exception 
  12.  *   of on your own host (netstat -a for christs sake).. anyway.. here 
  13.  *   it is..
  14.  *
  15.  *                  - pluvius@dhp.com
  16.  *
  17.  * tested on SunOS 4.1.3_U1 and Linux 1.1.85
  18.  * Also tested on OSF/1, courtesy of IETF.
  19.  * compile: cc -o pscan -s pscan.c
  20.  *
  21.  * NOTE: when you do a NIS listing.. it MUST be the domain name that
  22.  *       you pass as the remote host.. otherwise this will not work.
  23.  *
  24.  * H* mods: use a normally refused TCP port to determine UDP RTT delay.
  25.  * Much faster, and prevents the target from logging opened connections.
  26.  * May behave oddly if some TCP ports are dropped by a filter, and doesn't
  27.  * work on solaris cuz ICMP is *not* delivered to connected-UDP sockets.
  28.  * See udp_scan.c in Satan for more info, and a solaris version that works
  29.  * but needs root.
  30.  *
  31.  * If only one port arg given, just hit that port and report state.
  32.  *
  33.  * Added settable connect() timeout for tcp scan, with appropriate errors.
  34.  * Useful for determining what TCP ports are being filtered out -- scan a
  35.  * known machine behind a packet filter, and anything that wasn't refused
  36.  * or open is being dropped.  Ping first to get an idea of the right
  37.  * timeout to use; otherwise defaults to 3 sec.
  38.  *
  39.  * -->
  40.  *   connect time outs is broke on linux.. ripped it out. <p.
  41.  *   also yanked the --wait command thingy
  42.  *
  43.  *
  44.  * TODO: fix domainname shit, maybe rip code from satan yp_chk
  45.  *
  46. */
  47. #include <stdio.h>
  48. #include <unistd.h>
  49. #include <netdb.h>
  50. #include <sys/socket.h>
  51. #include <sys/types.h>
  52. #include <netinet/in.h>
  53. #include <rpc/rpc.h>
  54. #include <rpc/xdr.h>
  55. #include <rpc/pmap_prot.h>
  56. #include <rpc/pmap_clnt.h>
  57. #include <rpcsvc/yp_prot.h>
  58. #include <rpcsvc/ypclnt.h>
  59. #include <errno.h>
  60. #include <signal.h>
  61. #include <setjmp.h>
  62. /* xxx: these are sometimes defined by .h files as below for getopt.  I'll
  63.    fix it later... */
  64. extern int errno;
  65. #ifndef BSD4_4
  66. extern char *sys_errlist[];
  67. #endif
  68. #ifndef INADDR_NONE
  69. #define INADDR_NONE 0xffffffff
  70. #endif
  71. #ifdef __GNU_LIBRARY__    /* this is part of the GNU C lib */
  72. #include <getopt.h>
  73. #else
  74. extern int optind;
  75. extern char *optarg;
  76. #endif
  77. #define DEFAULT_LOW_PORT 1
  78. #define DEFAULT_HIGH_PORT 10240
  79. #define RTT_PORT 3 /* for UDP-RTT hack */
  80. #define MAJOR_VERSION 1
  81. #define MINOR_VERSION 4
  82. static char sccsid[] = "@(#) pscan.c 1.4 (pluvius+hobbit) 04/15/95";
  83. typedef enum {
  84.    false,
  85.    true
  86. } my_bool;
  87. my_bool Single = false; /* use booleans for all if-ed vars */
  88. typedef enum {
  89.    s_none,
  90.    s_tcp,
  91.    s_udp,
  92.    s_rpc,
  93.    s_nis
  94. } scan_t;
  95. #ifdef __GNU_LIBRARY__
  96. static struct option long_options[] = {
  97.    {"tcp", 0, 0, 0},
  98.    {"udp", 0, 0, 0},
  99.    {"rpc", 0, 0, 0},
  100.    {"nis", 0, 0, 0},
  101.    {"help", 0, 0, 0},
  102.    {"version", 0, 0, 0},
  103.    {0,0,0,0}
  104. };
  105. #endif
  106. struct {
  107.    char    *alias;
  108.    char    *mapname;
  109.    my_bool  inuse;
  110. } yp_maps[] = {
  111.    {"passwd",    "passwd.byname", false},
  112.    {"group",     "group.byname", false},
  113.    {"networks",  "networks.byaddr", false},
  114.    {"hosts",     "hosts.byaddr", false},
  115.    {"protocols", "protocols.bynumber", false},
  116.    {"services",  "services.byname", false},
  117.    {"aliases",   "mail.aliases", false},
  118.    {"ethers",    "ethers.byname", false},
  119.    {NULL,        NULL, false}
  120. };
  121. scan_t scan_type;
  122. char remote_host[200];
  123. char remote_ip[20];
  124. char remote_domain[128];
  125. int low_port;
  126. int high_port;
  127. void print_version(s)
  128. {
  129.    fprintf(stderr,"%s version %d.%dn",s,MAJOR_VERSION,MINOR_VERSION);
  130.    exit(0);
  131. }
  132. void print_usage(s)
  133. {
  134.    fprintf(stderr,"usage %s: <scan type> <host> [low port] [high port]n",s);
  135.    fprintf(stderr,"where scan type is one of:n");
  136. #ifdef __GNU_LIBRARY__
  137.    fprintf(stderr,"   --tcp, -t       - TCP port scann");
  138.    fprintf(stderr,"   --udp, -u       - UDP port scann");
  139.    fprintf(stderr,"   --rpc, -r       - RPC service listn");
  140.    fprintf(stderr,"   --nis, -n       - NIS map listingn");
  141.    fprintf(stderr,"   --version, -v   - Print version informationn");
  142.    fprintf(stderr,"   --help, -h      - Print usage informationn");
  143. #else
  144.    fprintf(stderr,"   -t              - TCP port scann");
  145.    fprintf(stderr,"   -u              - UDP port scann");
  146.    fprintf(stderr,"   -r              - RPC service listn");
  147.    fprintf(stderr,"   -n              - NIS map listingn");
  148.    fprintf(stderr,"   -v              - Print version informationn");
  149.    fprintf(stderr,"   -h              - Print usage informationn");
  150. #endif
  151.    fprintf(stderr,"n");
  152.    exit(0);
  153. }
  154. /* XXX: document -d after it works, maybe make -u take an arg? */
  155. void get_args(n,v)
  156. int n;
  157. char *v[];
  158. {
  159.  int c;
  160.  int opt_ind;
  161.    memset (remote_domain, 0, 8);
  162.    scan_type = s_none;
  163.    while (true) {
  164. #ifdef __GNU_LIBRARY__
  165.       c = getopt_long(n,v,"turnhvd:",long_options,&opt_ind);
  166. #else
  167.       c = getopt(n,v,"turnhvd:");
  168. #endif
  169.       if (c == -1)
  170.          break;
  171.       switch(c) {
  172. #ifdef __GNU_LIBRARY__
  173.        case 0:
  174.          opt_ind++; /* index's are one less than the scan type */
  175.          if (opt_ind == 5)
  176.             print_usage(v[0]);
  177.          if (opt_ind == 6)
  178.             print_version(v[0]);
  179.          scan_type = opt_ind;
  180.          break;
  181. #endif
  182.        case 't':
  183.          scan_type = s_tcp;
  184.          break;
  185.        case 'u':
  186.          scan_type = s_udp;
  187.          break;
  188.        case 'r':
  189.          scan_type = s_rpc;
  190.          break;
  191.        case 'n':
  192.          scan_type = s_nis;
  193.          break;
  194.        case 'd':
  195.  strcpy (remote_domain, optarg);
  196.  break;
  197.        case 'v':
  198.          print_version(v[0]);
  199.          break;
  200.        case 'h':
  201.        case '?':
  202.          print_usage(v[0]);
  203.          break;
  204.       }
  205.    }
  206.    low_port = DEFAULT_LOW_PORT;
  207.    high_port = DEFAULT_HIGH_PORT;
  208.    for (opt_ind = 0;optind < n;optind++) {
  209.       switch(opt_ind++) {
  210.        case 0: /* remote host */
  211.          strncpy(remote_host,v[optind],199);
  212.          break;
  213.        case 1: /* low port */
  214.          low_port = atoi(v[optind]);
  215.  Single = true;
  216.          break;
  217.        case 2: /* high port */
  218.          high_port = atoi(v[optind]);
  219.  Single = false;
  220.          break;
  221.       }
  222.    }
  223.    if (Single)
  224. high_port = low_port;
  225.    if ((opt_ind == 0) || (scan_type == s_none)) {
  226.       fprintf(stderr,"error: you must specify a scan type and a hostn");
  227.       print_usage(v[0]);
  228.    }
  229. }
  230. void check_args()
  231. {
  232.  struct hostent *host;
  233.    host = gethostbyname(remote_host);
  234.    if (host == NULL) {
  235. #if 0
  236. /* this sscanf and related code crashes on sunos, beats the shit out of me why.
  237.    In any case, punt -- just check the arg's validity with inet_addr and copy
  238.    it directly. */
  239.     unsigned char a,b,c,d,n;
  240.     char addr[5];
  241.       /* hmm.. perhaps it was a dotted quad entered.. */
  242.       n = sscanf(remote_host,"%u.%u.%u.%u",&a,&b,&c,&d);
  243.       if (n != 4) {
  244.          fprintf(stderr,"error: host '%s' not foundn",remote_host);
  245.          exit(1);
  246.       }
  247.       addr[0] = a;
  248.       addr[1] = b;
  249.       addr[2] = c;
  250.       addr[3] = d;
  251.       host = gethostbyaddr(addr,4,AF_INET);
  252. #endif /* 0 */
  253. /* ... we'll do it this way instead. */
  254.       unsigned long n;
  255.       n = inet_addr(remote_host);
  256.       if (n == INADDR_NONE) {
  257.          fprintf(stderr,"error: host '%s' not foundn",remote_host);
  258.          exit(1);
  259.       }
  260.       strcpy (remote_ip, remote_host);
  261.       host = gethostbyaddr(remote_ip,4,AF_INET);
  262.       if (host == NULL) {
  263.          fprintf(stderr,"error: host '%s' not foundn",remote_host);
  264.          exit(1);
  265.       }
  266.    } else {  /* gethostbyname */
  267.       sprintf(remote_ip,"%u.%u.%u.%u",
  268.               (unsigned char) host->h_addr_list[0][0],
  269.               (unsigned char) host->h_addr_list[0][1],
  270.               (unsigned char) host->h_addr_list[0][2],
  271.               (unsigned char) host->h_addr_list[0][3]);
  272.    }
  273. }
  274. void print_args()
  275. {
  276.  static char *opt_table[] = {
  277.     "tcp","udp","rpc","nis"
  278.  };
  279.   if (!Single) {
  280.    fprintf(stdout,"scanning host %s's %s ports ",remote_host,
  281.           opt_table[scan_type-1]);
  282.    if (scan_type < 3) {
  283.       fprintf(stdout,"%d through %d",low_port,high_port);
  284.    }
  285.    fprintf(stdout,"n");
  286.   } /* single */
  287. }
  288. void ping_host() 
  289. {
  290.  int s,slen;
  291.  struct sockaddr_in addr;
  292.  char out_string[100];
  293. /* What p. didn't explain here is that this is a simple way of delaying for
  294.    the expected RTT of the link, i.e. enough time for UDP out, ICMP back,
  295.    causing the next UDP write to error out.  Turns out that trying to connect
  296.    to a normally refused port is faster, although occasionally misses one. _H*/
  297.    /* send some stuff and wait for it to come back... ping for us */
  298.    /* non-root folks                                              */
  299.    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  300.    addr.sin_family = AF_INET;
  301.    addr.sin_addr.s_addr = inet_addr(remote_ip);
  302.    addr.sin_port = htons(RTT_PORT);
  303.    /* timeout code didn't work on linux.. scrap it. <p. */
  304.    connect(s, (struct sockaddr*) &addr, sizeof(addr));
  305.    close(s);
  306. }
  307. int scan()
  308. {
  309.  int soc;
  310.  struct sockaddr_in addr;
  311.  struct servent *serv;
  312.  int port,rc,addr_len,opt;
  313.    if (scan_type >= 3) /* this proc only does tcp and udp */
  314.       return;
  315.    errno = 0;
  316.    for (port = low_port;port <= high_port;port++) {
  317.       if (scan_type == s_tcp) {
  318.          soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  319.       } else if (scan_type == s_udp) {
  320.          soc = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  321.       } else 
  322.          return;
  323.       if (soc < 0) {
  324.          fprintf(stderr,"error: socket() failedn");
  325.          return;
  326.       }
  327.       /* this makes scan drop to a crawl on linux... */
  328.       /*rc = setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));*/
  329.       addr.sin_family = AF_INET;
  330.       addr.sin_addr.s_addr = inet_addr(remote_ip);
  331.       addr.sin_port = htons(port);
  332.       addr_len = sizeof(addr);
  333.       rc = connect(soc, (struct sockaddr*) &addr, addr_len);
  334.       if (scan_type == s_udp) {
  335.        char out_text[100];
  336.          strncpy(out_text,"k0ad kidz uv th3 WeRlD UN1t3n",99); 
  337.          rc = write(soc,out_text,strlen(out_text));
  338.          ping_host(); /* wait for icmp's */
  339.          rc = write(soc,out_text,strlen(out_text));
  340.       }
  341.       close(soc);
  342. /* for tcp, if anything other than refused, we want to know about it.  Always
  343.    print status for a single-port run. */
  344.       if (!Single)
  345.         if ((rc < 0) && (scan_type == s_tcp) && (errno == ECONNREFUSED))
  346.   continue;
  347.       if ((rc < 0) && (scan_type == s_udp))
  348. continue;
  349.       if (scan_type == s_tcp)
  350.          serv = getservbyport(htons(port),"tcp");
  351.       else if (scan_type == s_udp) {
  352.          serv = getservbyport(htons(port),"udp");
  353.  rc = 0; /* fake out below msg */
  354.       }
  355.       else 
  356.          return;
  357.       fprintf(stdout,"port %d (%s) %sn", port,
  358. (serv == NULL)?"UNKNOWN": serv->s_name,
  359. (rc == 0) ? "open" : sys_errlist[errno]);
  360.       fflush (stdout);
  361.    }
  362. }
  363. int callback_proc(is,ik,ikl,iv,ivl,id)
  364. int is;
  365. char *ik;
  366. int ikl;
  367. char *iv;
  368. int ivl;
  369. char *id;
  370. {
  371.    if (is != YP_TRUE)
  372.       return is;
  373.    return 0;
  374. }
  375. void nis_dump()
  376. {
  377.  int i,rc;
  378.  char *domainname;
  379.  char *map;
  380.  struct ypall_callback callback;
  381.    if (remote_domain[0])
  382. domainname = &remote_domain[0];
  383.    else
  384. domainname = &remote_host[0];
  385.    for (i = 0;yp_maps[i].mapname != NULL;i++) {
  386.       callback.foreach = callback_proc;
  387.       callback.data = NULL;
  388.       map = yp_maps[i].mapname;
  389.       rc = yp_all(domainname,map,&callback);
  390.       switch(rc) {
  391.        case 0:
  392.          printf("%-10.10s is availablen",yp_maps[i].alias);
  393.          break;
  394.        case YPERR_YPBIND:
  395.          fprintf(stderr,"error: server is not running ypbindn");
  396.          exit(1);
  397.          break;
  398.        default:
  399.          fprintf(stderr,"error: %s in domain %sn",
  400. yperr_string(rc), domainname);
  401.          exit(1);
  402.       }
  403.    }
  404. }
  405. /* this routine basically ripped from rpcinfo -p */
  406. void rpc_scan()
  407. {
  408. struct sockaddr_in server_addr;
  409. register struct hostent *hp;
  410. struct pmaplist *head = NULL;
  411. int socket = RPC_ANYSOCK;
  412. struct timeval minutetimeout;
  413. register CLIENT *client;
  414. struct rpcent *rpc;
  415. minutetimeout.tv_sec = 60;
  416. minutetimeout.tv_usec = 0;
  417.         server_addr.sin_addr.s_addr = inet_addr(remote_ip);
  418. server_addr.sin_family = AF_INET;
  419. server_addr.sin_port = htons(111);
  420. if ((client = clnttcp_create(&server_addr, PMAPPROG,
  421.     PMAPVERS, &socket, 50, 500)) == NULL) {
  422. clnt_pcreateerror("rpcinfo: can't contact portmapper");
  423. exit(1);
  424. }
  425. if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
  426.     xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
  427. fprintf(stderr, "rpcinfo: can't contact portmapper: ");
  428. clnt_perror(client, "rpcinfo");
  429. exit(1);
  430. }
  431. if (head == NULL) {
  432. printf("No remote programs registered.n");
  433. } else {
  434. printf("   program vers proto   portn");
  435. for (; head != NULL; head = head->pml_next) {
  436. printf("%10ld%5ld",
  437.     head->pml_map.pm_prog,
  438.     head->pml_map.pm_vers);
  439. if (head->pml_map.pm_prot == IPPROTO_UDP)
  440. printf("%6s",  "udp");
  441. else if (head->pml_map.pm_prot == IPPROTO_TCP)
  442. printf("%6s", "tcp");
  443. else
  444. printf("%6ld",  head->pml_map.pm_prot);
  445. printf("%7ld",  head->pml_map.pm_port);
  446. rpc = getrpcbynumber(head->pml_map.pm_prog);
  447. if (rpc)
  448. printf("  %sn", rpc->r_name);
  449. else
  450. printf("n");
  451. }
  452. }
  453. }
  454. int main(argc,argv)
  455. int argc;
  456. char *argv[];
  457. {
  458.    get_args(argc,argv);
  459.    check_args();
  460.    print_args();
  461.    /* this will only do tcp and udp, otherwise returns without doing anything */
  462.    switch (scan_type) {
  463.     case s_tcp:
  464.       scan();
  465.       break;
  466.     case s_udp:
  467.       scan();
  468.       break;
  469.     case s_rpc:
  470.       rpc_scan();
  471.       break;
  472.     case s_nis:
  473.       nis_dump();
  474.       break;
  475.    }
  476.    return 0;
  477. }