bm.c0000644000000000000000000000623513307745614010336 0ustar rootroot/* Boyer-Moore string search as found on the internet using Google */ #include #include #include #include #include "bm.h" #define MAX(a,b) ((a) < (b) ? (b) : (a)) static void preBmBc(unsigned char *x, int m, int bmBc[]) { int i; for (i = 0; i < BM_ASIZE; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[x[i]] = m - i - 1; } static void suffixes(unsigned char *x, int m, int *suff) { int f, g, i; f = 0; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && x[g] == x[g + m - 1 - f]) --g; suff[i] = f - g; } } } static int preBmGs(unsigned char *x, int m, int bmGs[]) { int i, j, *suff; suff = (int *) calloc(sizeof(int), m); if (suff == NULL) return -1; suffixes(x, m, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= -1; --i) if (i == -1 || suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; free(suff); return 0; } int bm_init(BM *bmp, unsigned char *x, int m, int icase) { int i; memset(bmp, 0, sizeof(bmp)); bmp->icase = icase; bmp->bmGs = (int *) calloc(sizeof(int), m); if (bmp->bmGs == NULL) return -1; bmp->saved_m = m; bmp->saved_x = (unsigned char *) malloc(m); if (bmp->saved_x == NULL) return -2; for (i = 0; i < m; i++) bmp->saved_x[i] = icase ? tolower(x[i]) : x[i]; /* Preprocessing */ if (preBmGs(bmp->saved_x, m, bmp->bmGs) < 0) return -3; preBmBc((unsigned char *) bmp->saved_x, m, bmp->bmBc); return 0; } void bm_destroy(BM *bmp) { if (bmp->bmGs) free(bmp->bmGs); if (bmp->saved_x) free(bmp->saved_x); } /* Search for matches ** ** If mfun is defined, then call this function for each match. ** If mfun returns anything else but 0 abort the search. If the ** returned value is < 0 then return this value, else return the ** number of matches (so far). ** ** If mfun is NULL then stop at first match and return the position */ int bm_search(BM *bmp, unsigned char *y, int n, int (*mfun)(void *buf, int n, int pos)) { int i, j, c; int nm = 0; /* Searching */ j = 0; while (j <= n - bmp->saved_m) { for (i = bmp->saved_m - 1; i >= 0 && bmp->saved_x[i] == (bmp->icase ? tolower(y[i + j]) : y[i + j]); --i) ; if (i < 0) { if (mfun) { ++nm; c = mfun(y, n, j); if (c) return (c < 0 ? c : nm); j += bmp->bmGs[0]; } else return j; } else { unsigned char c = (bmp->icase ? tolower(y[i + j]) : y[i + j]); j += MAX(bmp->bmGs[i], bmp->bmBc[c] - bmp->saved_m + 1 + i); } } return mfun == NULL ? -1 : nm; } #if 0 int main(int argc, char *argv[]) { int pos; bm_setup(argv[1], strlen(argv[1])); pos = bm_search(argv[2], strlen(argv[2])); printf("Match at pos %d\n", pos); exit(0); } #endif bm.h0000644000000000000000000000071413307745614010337 0ustar rootroot#ifndef PNSCAN_BM_H #define PNSCAN_BM_H #define BM_ASIZE 256 /* Allowed character code values */ typedef struct { int xsize; int *bmGs; int bmBc[BM_ASIZE]; unsigned char *saved_x; int saved_m; int icase; } BM; extern int bm_init(BM *bmp, unsigned char *x, int m, int icase); extern int bm_search(BM *bmp, unsigned char *y, int n, int (*mfun)(void *buf, int n, int pos)); extern void bm_destroy(BM *bmp); #endif ChangeLog0000644000000000000000000000141713307745614011343 0ustar rootroot2007-10-22 Peter Eriksson * pnscan.c: Fixed coredump when called without arguments. Thanks to Jose Luis Gonzalez for fixing and Ola Lundqvist for forwarding. 2002-03-27 Peter Eriksson * pnscan.c: Some more error checking in get_service() and when specifying a single port/service as an argument. * Print a descriptive string when reading host information from stdin. 2002-03-27 Henrik Rindlöw * Added Tru64 Unix support 2002-03-24 Ola Lundqvist * pnscan.sgml Added the other options implemented in pnscan.c. 2002-03-22 Peter Eriksson * pnscan.c: Modified the threads startup code to dynamically only start as many threads as is needed. install-sh0000755000000000000000000001273613307745614011603 0ustar rootroot#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$cpprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 ipsort0000755000000000000000000000020413307745614011030 0ustar rootroot#!/bin/sh # # Sort a file using IPv4 addresses in at the beginning of each line exec sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n "$@" ipsort.10000644000000000000000000000213413307745614011170 0ustar rootroot.\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "IPSORT" "1" "25 March 2002" "" "" .SH NAME ipsort \- sort a file using IPv4 addresses at the beginning of each line. .SH SYNOPSIS \fBipsort\fR\fB filename\fR .SH "DESCRIPTION" .PP This manual page documents briefly the \fBipsort\fR command. .PP \fBipsort\fR is a tool that can sort a file using IPv4 addresses at the beginning of each line. It is implemented as a shell script front end to the normal sort command. .SH "SEE ALSO" .PP pnscan (1) and sort (1). .SH "AUTHOR" .PP ipsort was written by Peter Eriksson . .PP Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. ipsort.sgml0000644000000000000000000000641413307745614011777 0ustar rootroot manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Peter"> Eriksson"> March 22, 2002"> 1"> pen@lysator.liu.se"> ipsort"> Debian"> GNU"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2002 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; sort a file using IPv4 addresses at the beginning of each line. &dhpackage; filename DESCRIPTION This manual page documents briefly the &dhpackage; command. &dhpackage; is a tool that can sort a file using IPv4 addresses at the beginning of each line. It is implemented as a shell script front end to the normal sort command. SEE ALSO pnscan (1) and sort (1). AUTHOR &dhpackage; was written by &dhusername; &dhemail;. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.
LICENSE0000644000000000000000000000047113307745614010575 0ustar rootrootThis program is free software; you can redistribute it and/or modify it as you wish - as long as you don't claim that you wrote it. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Makefile0000644000000000000000000000354113307745614011231 0ustar rootroot# Makefile for pnscan DESTDIR=/usr/local BINDIR=$(DESTDIR)/bin MANDIR=$(DESTDIR)/man MAN1DIR=$(MANDIR)/man1 TAR=tar GZIP=gzip MAKE=make INSTALL=./install-sh ## Solaris 8 with Gcc 3.0 GSO_CC=gcc -Wall -g -O -pthreads GSO_LDOPTS= GSO_LIBS= -lnsl -lsocket ## Solaris 8 with Forte C 6.2 SOL_CC=cc -mt -O SOL_LDOPTS= SOL_LIBS= -lpthread -lnsl -lsocket ## Linux 2.4 with Gcc 2.96 LNX_CC=gcc -Wall -g -O LNX_LDOPTS=-Wl,-s LNX_LIBS=-lpthread -lnsl T64_CC=cc -pthread -O T64_LDOPTS= T64_LIBS= -lpthread OBJS = pnscan.o bm.o version.o default: @echo 'Use "make SYSTEM" where SYSTEM may be:' @echo ' lnx (Linux with GCC)' @echo ' gso (Solaris with GCC v3)' @echo ' sol (Solaris with Forte C)' @echo ' t64 (Tru64 Unix with Compaq C)' @exit 1 t64 tru64 osf1 digitalunix: @$(MAKE) all CC="$(T64_CC)" LIBS="$(T64_LIBS)" LDOPTS="$(T64_LDOPTS)" lnx linux: @$(MAKE) all CC="$(LNX_CC)" LIBS="$(LNX_LIBS)" LDOPTS="$(LNX_LDOPTS)" gso: @$(MAKE) all CC="$(GSO_CC)" LIBS="$(GSO_LIBS)" LDOPTS="$(GSO_LDOPTS)" sol solaris: @$(MAKE) all CC="$(SOL_CC)" LIBS="$(SOL_LIBS)" LDOPTS="$(SOL_LDOPTS)" all: pnscan man: pnscan.1 ipsort.1 pnscan.1: pnscan.sgml docbook2man pnscan.sgml ipsort.1: ipsort.sgml docbook2man ipsort.sgml pnscan: $(OBJS) $(CC) $(LDOPTS) -o pnscan $(OBJS) $(LIBS) version: (PACKNAME=`basename \`pwd\`` ; echo 'char version[] = "'`echo $$PACKNAME | cut -d- -f2`'";' >version.c) clean distclean: -rm -f *.o *~ pnscan core manpage.* \#* dist: distclean version (PACKNAME=`basename \`pwd\`` ; cd .. ; $(TAR) cf - $$PACKNAME | $(GZIP) -9 >$$PACKNAME.tar.gz) install: install-bin install-man install-bin: all $(INSTALL) -c -m 755 pnscan $(BINDIR) $(INSTALL) -c -m 755 ipsort $(BINDIR) install-man: man $(INSTALL) -c -m 644 pnscan.1 $(MAN1DIR) $(INSTALL) -c -m 644 ipsort.1 $(MAN1DIR) install-all install-distribution: install pnscan.10000644000000000000000000000561013307745614011134 0ustar rootroot.\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "PNSCAN" "1" "27 March 2002" "" "" .SH NAME pnscan \- multi threaded port scanning tool .SH SYNOPSIS \fBpnscan\fR [ \fBoptions\fR] [ \fB \fR] \fBpnscan\fR [ \fBoptions\fR] [ \fB\fR] .SH "DESCRIPTION" .PP This manual page documents briefly the \fBpnscan\fR command. .PP \fBpnscan\fR is a tool that can be used to survey TCP network services. .PP When used with two command line arguments it will scan the indicated network/hosts and ports. When used without arguments or just one then it will read hostname/IP addresses from stdin and probe those. The single port/service argument is used as a default if no port is indicated on stdin .PP For example, it can be used to survey the installed versions of SSH, FTP, SMTP, Web, IDENT and possibly other services. .PP This program implements a multithreaded TCP port scanner. More information and new relaseses may be found at: http://www.lysator.liu.se/~pen/pnscan .SH "OPTIONS" .TP \fB-h\fR Show summary of options. .TP \fB-v\fR Be verbose. .TP \fB-V\fR Print version. .TP \fB-d\fR Print internal debugging info. .TP \fB-s \fR Lookup and print hostnames. This will slow down the scan considerably. .TP \fB-S\fR Enable shutdown mode. With this enabled pnscan will call shutdown(2) with an argument of 1 in order to half-close the TCP connection after any -w/-W arguments has been transmitted. The default is to wait for the remote party to close its end first (or until enough bytes has been received). .TP \fB-l\fR Line oriented output. This option will cause pnscan to try to locate the beginning of a line when a match (-r/-R) has been found, and only print up to the last byte/character on that line. .TP \fB-w \fR Request string to send. Please note that you must send any needed CR/LF characters as needed by the protocol since the string specified is sent as is (after escape characters has been decoded). .TP \fB-r \fR Response string to look for. .TP \fB-W \fR Hex coded request string to send. .TP \fB-R \fR Hex coded response string to look for. .TP \fB-L \fR Max bytes of response to print. .TP \fB-t \fR Connect/Write/Read timeout. .TP \fB-n \fR Maximum concurrent worker threads to start. .SH "SEE ALSO" .PP nmap (1) and ipsort (1). .SH "AUTHOR" .PP pnscan was written by Peter Eriksson . .PP Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. pnscan.c0000644000000000000000000005154713307745614011230 0ustar rootroot/* ** pnscan.c - Parallell Network Scanner ** ** Copyright (c) 2002 Peter Eriksson ** ** This program is free software; you can redistribute it and/or ** modify it as you wish - as long as you don't claim that you wrote ** it. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bm.h" #define RESPONSE_MAX_SIZE 1024 extern char version[]; unsigned char *wstr = NULL; int wlen = 0; unsigned char *rstr = NULL; int rlen = 0; int debug = 0; int verbose = 0; int stop = 0; int tworkers = 1; /* Currently running worker threads */ int mworkers = 1; /* Peak started concurrent worker threads */ int aworkers = 0; /* Currently active probing worker threads */ int nworkers = 0; /* Max concurrent worker threads */ int timeout = 2000; /* ms */ int pr_sym = 0; int line_f = 0; int use_shutdown = 0; int maxlen = 64; int first_port = 0; int last_port = 0; unsigned long first_ip = 0x00000000; unsigned long last_ip = 0xFFFFFFFF; pthread_mutex_t cur_lock; unsigned long cur_ip; int cur_port; pthread_mutex_t print_lock; int ignore_case = 0; BM bmb; void print_version(FILE *fp) { fprintf(fp, "[PNScan, version %s - %s %s]\n", version, __DATE__, __TIME__); } int get_char_code(unsigned char **cp, int base) { int val = 0; int len = 0; while (len < (base == 16 ? 2 : 3) && ((**cp >= '0' && **cp < '0'+(base > 10 ? 10 : base)) || (base >= 10 && toupper(**cp) >= 'A' && toupper(**cp) < 'A'+base-10))) { val *= base; if (**cp >= '0' && **cp < '0'+(base > 10 ? 10 : base)) val += **cp - '0'; else if (base >= 10 && toupper(**cp) >= 'A' && toupper(**cp) < 'A'+base-10) val += toupper(**cp) - 'A' + 10; ++*cp; ++len; } return val & 0xFF; } int dehex(unsigned char *str) { unsigned char *wp, *rp; int val; rp = wp = str; while (*rp) { while (*rp && isspace(* (unsigned char *) rp)) ++rp; if (*rp == '\0') break; if (!isxdigit(* (unsigned char *) rp)) return -1; val = get_char_code(&rp, 16); *wp++ = val; } *wp = '\0'; return wp - str; } int deslash(unsigned char *str) { unsigned char *wp, *rp; rp = wp = str; while (*rp) { if (*rp != '\\') *wp++ = *rp++; else { switch (*++rp) { case 'n': *wp++ = 10; ++rp; break; case 'r': *wp++ = 13; ++rp; break; case 't': *wp++ = 9; ++rp; break; case 'b': *wp++ = 8; ++rp; break; case 'x': ++rp; *wp++ = get_char_code(&rp, 16); break; case '0': *wp++ = get_char_code(&rp, 8); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *wp++ = get_char_code(&rp, 10); break; default: *wp++ = *rp++; break; } } } *wp = '\0'; return wp-str; } void print_host(FILE *fp, struct in_addr in, int port) { struct hostent *hep = NULL; if (pr_sym) { hep = gethostbyaddr((const char *) &in, sizeof(in), AF_INET); fprintf(fp, "%-15s : %-40s : %5d", inet_ntoa(in), hep ? hep->h_name : "(unknown)", port); } else fprintf(fp, "%-15s : %5d", inet_ntoa(in), port); } int t_write(int fd, unsigned char *buf, int len) { int tw, wl, code; struct pollfd pfd; tw = len; while (tw > 0) { pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; while ((code = poll(&pfd, 1, timeout)) < 0 && errno == EINTR) errno = 0; if (code == 0) { code = -1; errno = ETIMEDOUT; } while ((wl = write(fd, buf, tw)) < 0 && errno == EINTR) ; if (wl < 0) return wl; tw -= wl; buf += wl; } return len; } int t_read(int fd, unsigned char *buf, int size) { int len, code; struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN; pfd.revents = 0; while ((code = poll(&pfd, 1, timeout)) < 0 && errno == EINTR) errno = 0; if (code == 0) { errno = ETIMEDOUT; return -1; } while ((len = read(fd, buf, size)) < 0 && errno == EINTR) ; return len; } int is_text(unsigned char *cp, int slen) { while (slen > 0 && (isprint(*cp) || *cp == '\0' || *cp == '\t' || *cp == '\n' || *cp == '\r')) { --slen; ++cp; } return slen == 0; } int print_output(unsigned char *str, int slen) { unsigned char *cp = str; int len; len = 0; if (str == NULL) { printf("NULL"); return len; } if (slen >= 2 && cp[0] == IAC && cp[1] >= xEOF) { printf("TEL : "); while (len < slen && len < maxlen) { if (*cp == IAC) { ++len; printf(""); switch (*++cp) { case 0: return len; case DONT: printf(""); break; case DO: printf(""); break; case WONT: printf(""); break; case WILL: printf(""); break; case SB: printf(""); break; case GA: printf(""); break; case EL: printf(""); break; case EC: printf(""); break; case AYT: printf(""); break; case AO: printf(""); break; case IP: printf(""); break; case BREAK: printf(""); break; case DM: printf(""); break; case NOP: printf(""); break; case SE: printf(""); break; case EOR: printf(""); break; case ABORT: printf(""); break; case SUSP: printf(""); break; case xEOF: printf(""); break; default: printf("<0x%02X>", *cp); } } else if (isprint(*cp)) putchar(*cp); else { switch (*cp) { case '\n': if (line_f) return len; printf("\\n"); break; case '\r': if (line_f) return len; printf("\\r"); break; case '\t': printf("\\t"); break; case '\0': printf("\\0"); break; default: printf("\\x%02X", *cp); } } ++len; ++cp; } } else if (is_text(str, slen)) { printf("TXT : "); while (len < slen && len < maxlen) { if (isprint(* (unsigned char *) str)) putchar(*str); else switch (*str) { case '\0': printf("\\0"); break; case '\n': if (line_f) return len; printf("\\n"); break; case '\r': if (line_f) return len; printf("\\r"); break; case '\t': printf("\\t"); break; default: printf("\\x%02x", * (unsigned char *) str); } ++len; ++str; } } else { printf("HEX :"); while (len < slen && len < maxlen) { printf(" %02x", * (unsigned char *) str); ++len; ++str; } } return len; } int probe(unsigned long addr, int port) { int fd, code, len; struct sockaddr_in sin; unsigned char buf[RESPONSE_MAX_SIZE]; struct pollfd pfd; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) return -1; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = htonl(addr); code = fcntl(fd, F_GETFL, 0); if (code < 0) { close(fd); return -1; } #ifdef FNDELAY code = fcntl(fd, F_SETFL, code|FNDELAY); #else code = fcntl(fd, F_SETFL, code|O_NONBLOCK); #endif if (code < 0) { close(fd); return -1; } while ((code = connect(fd, (struct sockaddr *) &sin, sizeof(sin))) < 0 && errno == EINTR) errno = 0; if (code < 0 && errno == EINPROGRESS) { pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; while ((code = poll(&pfd, 1, timeout)) < 0 && errno == EINTR) errno = 0; if (code == 0) { code = -1; errno = ETIMEDOUT; } } if (code < 0) { if (verbose) { pthread_mutex_lock(&print_lock); print_host(stderr, sin.sin_addr, port); fprintf(stderr, " : ERR : connect() failed: %s\n", strerror(errno)); pthread_mutex_unlock(&print_lock); } close(fd); return 0; } if (wstr) { code = t_write(fd, wstr, wlen); if (code < 0) { if (verbose) { pthread_mutex_lock(&print_lock); print_host(stderr, sin.sin_addr, port); fprintf(stderr, " : ERR : write() failed: %s\n", strerror(errno)); pthread_mutex_unlock(&print_lock); } close(fd); return 0; } } if (use_shutdown) shutdown(fd, 1); while ((len = t_read(fd, buf, sizeof(buf)-1)) < 0 && errno == EINTR) ; if (len < 0) { if (verbose) { pthread_mutex_lock(&print_lock); print_host(stderr, sin.sin_addr, port); fprintf(stderr, " : ERR : read() failed: %s\n", strerror(errno)); pthread_mutex_unlock(&print_lock); } close(fd); return -1; } buf[len] = '\0'; if (rstr) { int pos; pos = bm_search(&bmb, buf, len, NULL); if (pos >= 0) { if (line_f) while (pos > 0 && !(buf[pos-1] == '\n' || buf[pos-1] == '\r')) --pos; pthread_mutex_lock(&print_lock); print_host(stdout, sin.sin_addr, port); printf(" : "); print_output(buf+pos, len-pos); putchar('\n'); pthread_mutex_unlock(&print_lock); } } else { pthread_mutex_lock(&print_lock); print_host(stdout, sin.sin_addr, port); printf(" : "); print_output(buf, len); putchar('\n'); pthread_mutex_unlock(&print_lock); } close(fd); return 1; } void * r_worker(void *arg) { unsigned long addr; int port; pthread_t tid; pthread_mutex_lock(&cur_lock); while (!stop) { if (cur_ip <= last_ip) { port = cur_port; addr = cur_ip++; } else { if (cur_port >= last_port) { stop = 1; break; } port = ++cur_port; addr = cur_ip = first_ip; } if (aworkers >= tworkers-1 && tworkers < nworkers) { ++tworkers; if (pthread_create(&tid, NULL, r_worker, NULL) != 0) { --tworkers; nworkers = tworkers; } if (tworkers > mworkers) mworkers = tworkers; } ++aworkers; pthread_mutex_unlock(&cur_lock); probe(addr, port); pthread_mutex_lock(&cur_lock); --aworkers; } --tworkers; pthread_mutex_unlock(&cur_lock); fflush(stdout); return NULL; } int get_host(char *str, unsigned long *ip) { struct hostent *hep; unsigned long tip; hep = gethostbyname(str); if (hep && hep->h_addr_list &&hep->h_addr_list[0]) { tip = * (unsigned long *) (hep->h_addr_list[0]); *ip = ntohl(tip); return 1; } return inet_pton(AF_INET, str, ip); } int get_service(char *str, int *pp) { struct servent *sep; char c; sep = getservbyname(str, "tcp"); if (sep) { *pp = ntohs(sep->s_port); return 1; } if (sscanf(str, "%u%c", pp, &c) != 1) return -1; if (*pp < 1 || *pp > 65535) return 0; return 1; } void * f_worker(void *arg) { unsigned long addr; int port, code; char buf[1024]; char *host; char *serv; char *tokp; pthread_t tid; pthread_mutex_lock(&cur_lock); while (!stop) { if (fgets(buf, sizeof(buf), stdin) == NULL) { if (debug) fprintf(stderr, "*** GOT EOF ***\n"); stop = 1; break; } host = strtok_r(buf, " \t\n\r", &tokp); if (host == NULL || host[0] == '#') continue; if (get_host(host, &addr) != 1) { if (verbose) fprintf(stderr, "%s: invalid host\n", host); continue; } serv = strtok_r(NULL, " \t\n\r", &tokp); if (serv == NULL) { if (first_port == 0) { if (verbose) fprintf(stderr, "%s: missing service specification\n", host); continue; } port = first_port; } else { code = get_service(serv, &port); if (code != 1) { if (verbose) fprintf(stderr, "%s: invalid service (code=%d)\n", serv, code); continue; } } if (aworkers >= tworkers-1 && tworkers < nworkers) { ++tworkers; if (pthread_create(&tid, NULL, f_worker, NULL) != 0) { --tworkers; nworkers = tworkers; } if (tworkers > mworkers) mworkers = tworkers; } ++aworkers; pthread_mutex_unlock(&cur_lock); probe(addr, port); pthread_mutex_lock(&cur_lock); --aworkers; } --tworkers; pthread_mutex_unlock(&cur_lock); fflush(stdout); return NULL; } char *argv0 = "pnscan"; void usage(FILE *out) { fprintf(out, "Usage: %s [] [{| } | ]\n", argv0); fputs("\n\ This program implements a multithreaded TCP port scanner.\n\ More information may be found at:\n\ \thttp://www.lysator.liu.se/~pen/pnscan\n\ \n\ Command line options:\n", out); fprintf(out, "\t-h Display this information.\n"); fprintf(out, "\t-V Print version.\n"); fprintf(out, "\t-v Be verbose.\n"); fprintf(out, "\t-d Print debugging info.\n"); fprintf(out, "\t-s Lookup and print hostnames.\n"); fprintf(out, "\t-i Ignore case when scanning responses.\n"); fprintf(out, "\t-S Enable shutdown mode.\n"); fprintf(out, "\t-l Line oriented output.\n"); fprintf(out, "\t-w Request string to send.\n"); fprintf(out, "\t-W Hex coded request string to send.\n"); fprintf(out, "\t-r Response string to look for.\n"); fprintf(out, "\t-R Hex coded response string to look for.\n"); fprintf(out, "\t-L Max bytes to print.\n"); fprintf(out, "\t-t Connect/Write/Read timeout.\n"); fprintf(out, "\t-n Concurrent worker threads limit.\n"); } int get_network(char *str, unsigned long *np) { struct netent *nep; struct in_addr ia; nep = getnetbyname(str); if (nep) { ia = inet_makeaddr(nep->n_net, 0); *np = ntohl(ia.s_addr); return 1; } return inet_pton(AF_INET, str, np); } int get_ip_range(char *str, unsigned long *first_ip, unsigned long *last_ip) { char first[1024], last[1024]; int len; unsigned long ip; unsigned long mask = 0; if (sscanf(str, "%1023[^/ ] / %u", first, &len) == 2) { /* CIDR */ if (get_network(first, &ip) != 1 || len < 0 || len > 32) return -1; ip = ntohl(ip); *first_ip = ip+1; len = 32-len; while (len-- > 0) mask = ((mask << 1)|1); *last_ip = (ip|mask)-1; return 2; } switch (sscanf(str, "%1023[^: ] : %1023s", first, last)) { case 1: if (get_host(first, first_ip) != 1) return -1; *last_ip = *first_ip; return 1; case 2: if (get_host(first, first_ip) != 1) return -1; if (get_host(last, last_ip) != 1) return -1; return 2; } return -1; } int get_port_range(char *str, int *first_port, int *last_port) { char first[256], last[256]; switch (sscanf(str, "%255[^: ] : %255s", first, last)) { case 1: if (strcmp(first, "all") == 0) { *first_port = 1; *last_port = 65535; return 2; } if (get_service(first, first_port) != 1) return -1; *last_port = *first_port; return 1; case 2: if (get_service(first, first_port) != 1) return -1; if (get_service(last, last_port) != 1) return -1; return 2; } return -1; } void e_fun(void) { printf("mworkers = %d, tworkers = %d, aworkers = %d, nworkers = %d\n", mworkers, tworkers, aworkers, nworkers); } int main(int argc, char *argv[]) { int i, j; struct rlimit rlb; char *arg; argv0 = argv[0]; setlocale(LC_CTYPE, ""); first_port = 0; last_port = 0; getrlimit(RLIMIT_NOFILE, &rlb); rlb.rlim_cur = rlb.rlim_max; setrlimit(RLIMIT_NOFILE, &rlb); signal(SIGPIPE, SIG_IGN); nworkers = rlb.rlim_cur - 8; if (nworkers > 1024) nworkers = 1024; pthread_mutex_init(&cur_lock, NULL); pthread_mutex_init(&print_lock, NULL); for (i = 1; i < argc && argv[i][0] == '-'; i++) for (j = 1; j > 0 && argv[i][j]; ++j) switch (argv[i][j]) { case '-': case '\0': ++i; goto EndOptions; case 'V': print_version(stdout); break; case 'd': ++debug; break; case 'i': ignore_case = 1; break; case 'v': ++verbose; break; case 'h': usage(stdout); exit(0); case 'l': ++line_f; break; case 's': ++pr_sym; break; case 'S': ++use_shutdown; break; case 'w': if (argv[i][2]) wstr = (unsigned char *) strdup(argv[i]+2); else if (i+1 < argc) wstr = (unsigned char *) strdup(argv[++i]); else { fprintf(stderr, "%s: Missing required argument for '-w'\n", argv[0]); exit(1); } wlen = deslash(wstr); j = -2; break; case 'W': if (argv[i][2]) wstr = (unsigned char *) strdup(argv[i]+2); else if (i+1 < argc) wstr = (unsigned char *) strdup(argv[++i]); else { fprintf(stderr, "%s: Missing required argument for '-W'\n", argv[0]); exit(1); } wlen = dehex(wstr); j = -2; break; case 'R': if (argv[i][2]) rstr = (unsigned char *) strdup(argv[i]+2); else if (i+1 < argc) rstr = (unsigned char *) strdup(argv[++i]); else { fprintf(stderr, "%s: Missing required argument for '-R\n", argv[0]); exit(1); } rlen = dehex(rstr); j = -2; break; case 'r': if (argv[i][2]) rstr = (unsigned char *) strdup(argv[i]+2); else if (i+1 < argc) rstr = (unsigned char *) strdup(argv[++i]); else { fprintf(stderr, "%s: Missing required argument for '-r'\n", argv[0]); exit(1); } rlen = deslash(rstr); j = -2; break; case 'L': if (argv[i][2]) arg = argv[i]+2; else arg = argv[++i]; if (!arg || sscanf(arg, "%u", &maxlen) != 1) { fprintf(stderr, "%s: Invalid length specification: %s\n", argv[0], arg ? arg : ""); exit(1); } j = -2; break; case 't': if (argv[i][2]) arg = argv[i]+2; else arg = argv[++i]; if (!arg || sscanf(arg, "%u", &timeout) != 1) { fprintf(stderr, "%s: Invalid timeout specification: %s\n", argv[0], arg ? arg : ""); exit(1); } j = -2; break; case 'n': if (argv[i][2]) arg = argv[i]+2; else arg = argv[++i]; if (!arg || sscanf(arg, "%u", &nworkers) != 1) { fprintf(stderr, "%s: Invalid workers specification: %s\n", argv[0], arg ? arg : ""); exit(1); } j = -2; break; default: fprintf(stderr, "%s: unknown command line switch: -%c\n", argv[0], argv[i][j]); exit(1); } EndOptions: if (rstr) { if (bm_init(&bmb, rstr, rlen, ignore_case) < 0) { fprintf(stderr, "%s: Failed search string setup: %s\n", argv[0], rstr); exit(1); } } if (debug) atexit(e_fun); if (i == argc || i+1 == argc) { if (i + 1 == argc) if (get_service(argv[i], &first_port) != 1) { fprintf(stderr, "%s: Invalid port/service: %s\n", argv[0], argv[i]); exit(1); } if (verbose || isatty(0)) { if (!isatty(0)) fprintf(stderr, "[Reading host/address data from stdin]\n"); else fprintf(stderr, "[Waiting for host/address data on stdin]\n"); } f_worker(NULL); pthread_exit(NULL); return 1; /* Not reached */ } if (i + 2 != argc) { fprintf(stderr, "%s: Missing or extra argument(s). Use '-h' for help.\n", argv[0]); exit(1); } if (get_ip_range(argv[i], &first_ip, &last_ip) < 1) { fprintf(stderr, "%s: Invalid IP address range: %s\n", argv[0], argv[i]); exit(1); } if (get_port_range(argv[i+1], &first_port, &last_port) < 1) { fprintf(stderr, "%s: Invalid Port range: %s\n", argv[0], argv[i+1]); exit(1); } cur_ip = first_ip; cur_port = first_port; r_worker(NULL); pthread_exit(NULL); return 1; /* Not reached */ } pnscan.sgml0000644000000000000000000001631513307745614011742 0ustar rootroot manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Peter"> Eriksson"> March 22, 2002"> 1"> pen@lysator.liu.se"> pnscan"> Debian"> GNU"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2002 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; multi threaded port scanning tool &dhpackage; <CIDR | host-range> <port-range> &dhpackage; DESCRIPTION This manual page documents briefly the &dhpackage; command. &dhpackage; is a tool that can be used to survey TCP network services. When used with two command line arguments it will scan the indicated network/hosts and ports. When used without arguments or just one then it will read hostname/IP addresses from stdin and probe those. The single port/service argument is used as a default if no port is indicated on stdin For example, it can be used to survey the installed versions of SSH, FTP, SMTP, Web, IDENT and possibly other services. This program implements a multithreaded TCP port scanner. More information and new relaseses may be found at: http://www.lysator.liu.se/~pen/pnscan OPTIONS Show summary of options. Be verbose. Print version. Print internal debugging info. Lookup and print hostnames. This will slow down the scan considerably. Enable shutdown mode. With this enabled pnscan will call shutdown(2) with an argument of 1 in order to half-close the TCP connection after any -w/-W arguments has been transmitted. The default is to wait for the remote party to close its end first (or until enough bytes has been received). Line oriented output. This option will cause pnscan to try to locate the beginning of a line when a match (-r/-R) has been found, and only print up to the last byte/character on that line. Request string to send. Please note that you must send any needed CR/LF characters as needed by the protocol since the string specified is sent as is (after escape characters has been decoded). Response string to look for. Hex coded request string to send. Hex coded response string to look for. Max bytes of response to print. Connect/Write/Read timeout. Maximum concurrent worker threads to start. SEE ALSO nmap (1) and ipsort (1). AUTHOR &dhpackage; was written by &dhusername; &dhemail;. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.
README0000644000000000000000000001003713307745614010447 0ustar rootrootpnscan - a Parallell Network Scanner Copyright (c) 2002-2016 Peter Eriksson ---------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it as you wish - as long as you don't claim that you wrote it. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ---------------------------------------------------------------------- INTRODUCTION Pnscan is a tool that can be used to survey TCP network services. For example, it can be used to survey the installed versions of SSH, FTP, SMTP, Web, IDENT and possibly other services. The latest version of pnscan can always be downloaded from: ftp://ftp.lysator.liu.se/pub/unix/pnscan There is also a small web page about it at: http://www.lysator.liu.se/~pen/pnscan If you like it then I'd gladly accept a nice bottle of whisky, some free beer or even just a "Thank you!" email :-) INSTALLATION Possibly edit the "Makefile" and the run 'make ' where currently may be: lnx Linux with GCC v2 gso Solaris with GCC v3 sol Solaris with Forte C When it has been built you can install it with "make install-all". It will by default install in /usr/local/bin and /usr/local/man/man1 USAGE Start pnscan with "-h" for online help. pnscan tries to be smart as to how many threads to start - it will dynamically start only as many as is needed to make progress in the scan - up to a maximum either as specified with the "-n" command line option, or 8 minus the maximum number of available file descriptors (pnscan tries to increase it to the max limit automatically) - or any internal limit on the system (Linux normally only allows 256 threads). Host ranges can be specified both as a CIDR - network name or IP address / mask bit length and as a range. When using CIDR notation - the first and last address is ignored (normally used for broadcasts) Some examples: 192.168.0.0/24 192.160.0.1:192.160.0.254 arpanet/8 The CIDR names are looked up in "networks" (/etc/networks or the YP/NIS+/whatever equivalent). The host ranges can also be specified as a range (or a single address) of hostnames or IP addresses: some.where.com:otherplace.where.com 192.168.10.27:192.168.11.194 localhost Service/Port ranges can be specified both via symbolic names looked up in "services" (/etc/services or YP/NIS+/whatever equivalent) or as numbers: ssh:telnet 22:23 113 The strings used with "-w" and "-r" may contain escaped characters. NUL characters are legal (\0) to use. pnscan by default will start printing the output from the first line recevied - *or* from the start of a match with "-r" (or from the first line of the first match if used with the "-l" option). EXAMPLES # Scan network 192.168.0.0/24 for SSH daemons on port 22 pnscan 192.168.0.0/24 22 pnscan 192.168.0.1:192.168.0.254 ssh # Scan hosts 192.168.10.34 ... 98 for IDENT servers, max 8 threads pnscan -n8 -w"VERSION" 192.168.10.34:192.168.10.98 113 # Scan host 127.0.0.1 for WWW servers on all ports pnscan -w"HEAD / HTTP/1.0\r\n\r\n" -r"Server:" 192.168.0.32 1:65525 pnscan -w"HEAD / HTTP/1.0\r\n\r\n" -r"Server:" localhost 1:65525 # Send binary data and expect the binary sequence FF 00 FF on port 145. pnscan -W"05 5A 37" -R"FF 00 FF" 192.168.0.32 145 # Scan for Roxen servers and print the whole Server-line pnscan -l -w"HEAD / HTTP/1.0\r\n\r\n" -r"Roxen" localhost 1:65525 # Scan for pidentd servers and try to locate the version pnscan -w"VERSION" 192.160.0.0/24 113 # Scan network arpanet/24 for daytime servers and sort them IP-numerically pnscan arpanet/10 daytime | ipsort # Read host (&port) lines from stdin and scan the selected hosts for SSH echo '192.160.10.11 ssh' | pnscan -v echo '192.160.10.12' | pnscan 22 WARNING Scanning of networks of which you do not have explicit permission to do probably will be considered abuse of network resources and may cause problems for you. So *please* use this tool with great care. TODO0000644000000000000000000000003213307745614010251 0ustar rootrootIPv6 support? UDP scans? version.c0000644000000000000000000000003113307745614011411 0ustar rootrootchar version[] = "1.11";