操作系统 端口扫描分析

 
操作系统 端口扫描分析

来源:自绿色兵团
端口扫描分析(一)常用的网络相关命令
来源 / 作者: Oliver


  一个端口就是一个潜在的通信通道,也就是一个入侵通道。对目标计算机进行端口扫描,能得到许多有用的信息。进行扫描的方法很多,可以是手工进行扫描,也可以用端口扫描软件进行。
  在手工进行扫描时,需要熟悉各种命令。对命令执行后的输出进行分析。用扫描软件进行扫描时,许多扫描器软件都有分析数据的功能。
  通过端口扫描,可以得到许多有用的信息,从而发现系统的安全漏洞。
  下面首先介绍几个常用网络命令,对端口扫描原理进行介绍,然后提供一个简单的扫描程序。第一节 几个常用网络相关命令
Ping
命令经常用来对 TCP/IP 网络进行诊断。通过目标计算机发送一个数据包,让它将这个数据包反送回来,如果返回的数据包和发送的数据包一致,那就是说你的 PING 命令成功了。通过这样对返回的数据进行分析,就能判断计算机是否开着,或者这个数据包从发送到返回需要多少时间。

一。几个常用网络相关命令
1.Ping
命令的基本格式:
     ping hostname

  其中 hostname 是目标计算机的地址。 Ping 还有许多高级使用,下面就是一个例子。
C:> ping -f hostname
  这条命令给目标机器发送大量的数据,从而使目标计算机忙于回应。在 Windows 95 的计算机上,使用下面的方法:
c:/windows/ping -l 65500 saddam_hussein's.computer.mil
  这样做了之后,目标计算机有可能会挂起来,或从新启动。由于 -l 65510 产生一个巨大的数据包。由于要求返回一个同样的数据包,会使目标计算机反应不过来。
  在 Linux 计算机上,可以编写一个程序来实现上述方法。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
 
/*
* If your kernel doesn't muck with raw packets, #define REALLY_RAW.
* This is probably only Linux.
*/
#ifdef REALLY_RAW
#define FIX(x)
  htons(x)
#else
#define FIX(x)
  (x)
#endif
 
int
main(int argc, char **argv)
{
     int s;
     char buf[1500];
     struct ip *ip = (struct ip *)buf;
     struct icmp *icmp = (struct icmp *)(ip + 1);
     struct hostent *hp;
     struct sockaddr_in dst;
     int offset;
     int on = 1;
 
     bzero(buf, sizeof buf);
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) < 0) {
         perror("socket");
         exit(1);
     }
     if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
         perror("IP_HDRINCL");
         exit(1);
     }
     if (argc != 2) {
         fprintf(stderr, "usage: %s hostname/n", argv[0]);
         exit(1);
     }
     if ((hp = gethostbyname(argv[1])) == NULL) {
         if ((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1) {
             fprintf(stderr, "%s: unknown host/n", argv[1]);
         }
     } else {
         bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
     }

     printf("Sending to %s/n", inet_ntoa(ip->ip_dst));
     ip->ip_v = 4;
     ip->ip_hl = sizeof *ip >> 2;
     ip->ip_tos = 0;
     ip->ip_len = FIX(sizeof buf);
     ip->ip_id = htons(4321);
     ip->ip_off = FIX(0);
     ip->ip_ttl = 255;
     ip->ip_p = 1;
     ip->ip_sum = 0;          /* kernel fills in */
     ip->ip_src.s_addr = 0;       /* kernel fills in */
 
     dst.sin_addr = ip->ip_dst;
     dst.sin_family = AF_INET;
 
     icmp->icmp_type = ICMP_ECHO;
     icmp->icmp_code = 0;
     icmp->icmp_cksum = htons(~(ICMP_ECHO << 8));
         /* the checksum of all 0's is easy to compute */

     for (offset = 0; offset < 65536; offset += (sizeof buf - sizeof *ip)) {
         ip->ip_off = FIX(offset >> 3);
         if (offset < 65120)
             ip->ip_off |= FIX(IP_MF);
         else
             ip->ip_len = FIX(418);   /* make total 65538 */
         if (sendto(s, buf, sizeof buf, 0, (struct sockaddr *)&dst,
                     sizeof dst) < 0) {
             fprintf(stderr, "offset %d: ", offset);
             perror("sendto");
         }
         if (offset == 0) {
             icmp->icmp_type = 0;
             icmp->icmp_code = 0;
             icmp->icmp_cksum = 0;
         }
     }
}

2.Tracert
命令用来跟踪一个消息从一台计算机到另一台计算机所走的路径,比方说从你的计算机走到浙江信息超市。在 DOS 窗口下,命令如下:
C:/WINDOWS>tracert 202.96.102.4

Tracing route to 202.96.102.4 over a maximum of 30 hops

  1    84 ms    82 ms    95 ms   202.96.101.57
  2   100 ms   100 ms    95 ms   0fa1.1-rtr1-a-hz1.zj.CN.NET [202.96.101.33]
  3    95 ms    90 ms   100 ms   202.101.165.1
  4    90 ms    90 ms    90 ms   202.107.197.98
  5    95 ms    90 ms    99 ms   202.96.102.4
  6    90 ms    95 ms   100 ms   202.96.102.4

Trace complete.

  上面的这些输出代表什么意思?左边的数字是该路由通过的计算机数目。 "150 ms" 是指向那台计算机发送消息的往返时间,单位是微秒。由于每条消息每次的来回的时间不一样, tracert 将显示来回时间三次。 "*" 表示来回时间太长, tracert 将这个时间 忘掉了 。在时间信息到来后,计算机的名字信息也到了。开始是一种便于人们阅读的格式, 接着是数字格式。

C:/WINDOWS>tracert
  152.163.199.56

Tracing route to dns-aol.ANS.NET [198.83.210.28]over a maximum of 30 hops:

  1   124 ms   106 ms   105 ms   202.96.101.57
  2    95 ms    95 ms    90 ms   0fa1.1-rtr1-a-hz1.zj.CN.NET [202.96.101.33]
  3   100 ms    90 ms   100 ms   202.101.165.1
  4    90 ms    95 ms    95 ms   202.97.18.241
  5   105 ms   105 ms   100 ms   202.97.18.93
  6   100 ms    99 ms   100 ms   202.97.10.37
  7   135 ms    98 ms   100 ms   202.97.9.78
  8   760 ms   725 ms   768 ms   gip-ftworth-4-serial8-3.gip.net [204.59.178.53]
  9   730 ms   750 ms   715 ms   gip-ftworth-4-serial8-3.gip.net [204.59.178.53]
10
  750 ms   785 ms   772 ms   144.232.11.9
11
  740 ms   800 ms   735 ms   sl-bb11-pen-2-0.sprintlink.NET [144.232.8.158]
12
  790 ms   800 ms   735 ms   sl-nap2-pen-4-0-0.sprintlink.net [144.232.5.66]
13
  770 ms   800 ms   800 ms   p219.t3.ans.net [192.157.69.13]
14
  775 ms   820 ms   780 ms   h14-1.t60-6.Reston.t3.ANS.NET [140.223.17.18]
15
  780 ms   800 ms   800 ms   h11-1.t60-2.Reston.t3.ANS.NET [140.223.25.34]
16
  790 ms   795 ms   800 ms   h14-1.t104-0.Atlanta.t3.ANS.NET [140.223.65.18]
17
   *    h14-1.t104-0.Atlanta.t3.ANS.NET [140.223.65.18]   reports: Destination host unreachable.

Trace complete.

3.rusers
finger
  这两个都是 Unix 命令。通过这两个命令,你能收集到目标计算机上的有关用户的消息。
使用 rusers 命令,产生的结果如下示意:
gajake
    snark.wizard.com:ttyp1   Nov 13 15:42   7:30 (remote)
root
     snark.wizard.com:ttyp2   Nov 13 14:57   7:21 (remote)
robo
     snark.wizard.com:ttyp3   Nov 15 01:04   01 (remote)
angel111
   snark.wizard.com:ttyp4   Nov14 23:09     (remote)
pippen
    snark.wizard.com:ttyp6 Nov 14 15:05      (remote)
root
     snark.wizard.com:ttyp5 Nov 13 16:03    7:52 (remote)
gajake
    snark.wizard.com:ttyp7 Nov 14 20:20    2:59 (remote)
dafr
     snark.wizard.com:ttyp15Nov   3 20:09    4:55 (remote)
dafr
     snark.wizard.com:ttyp1 Nov 14 06:12   19:12 (remote)
dafr
     snark.wizard.com:ttyp19Nov 14 06:12   19:02 (remote)

  最左边的是通过远程登录的用户名。还包括上次登录时间,使用的 SHELL 类型等等信息。
  使用 finger 可以产生类似下面的结果:
user S00
  PPP ppp-122-pm1.wiza   Thu Nov 14 21:29:30 - still logged in
user S15
  PPP ppp-119-pm1.wiza   Thu Nov 14 22:16:35 - still logged in
user S04
  PPP ppp-121-pm1.wiza   Fri Nov 15 00:03:22 - still logged in
user S03
  PPP ppp-112-pm1.wiza   Thu Nov 14 22:20:23 - still logged in
user S26
  PPP ppp-124-pm1.wiza   Fri Nov 15 01:26:49 - still logged in
user S25
  PPP ppp-102-pm1.wiza   Thu Nov 14 23:18:00 - still logged in
user S17
  PPP ppp-115-pm1.wiza   Thu Nov 14 07:45:00 - still logged in
user S-1
  0.0.0 .0       Sat Aug 10 15:50:03 - still logged in
user S23
  PPP ppp-103-pm1.wiza   Fri Nov 15 00:13:53 - still logged in
user S12
  PPP ppp-111-pm1.wiza   Wed Nov 13 16:58:12 - still logged in
  这个命令能显示用户的状态。该命令是建立在客户 / 服务模型之上的。用户通过客户端软件向服务器请求信息,然后解释这些信息,提供给用户。在服务器上一般运行一个叫做 fingerd 的程序,根据服务器的机器的配置,能向客户提供某些信息。如果考虑到保护这些个人信息的话,有可能许多服务器不提供这个服务,或者只提供一些无关的信息。

4.host
命令
   host 是一个 Unix 命令,它的功能和标准的 nslookup 查询一样。唯一的区别是 host 命令比较容易理解。 host 命令的危险性相当大,下面举个使用实例,演示一次对 bu.edu host 查询。
host -l -v -t any bu.edu
  这个命令的执行结果所得到的信息十分多,包括操作系统,机器和网络的很多数据。先看一下基本信息:
Found 1 addresses for BU.EDU
Found 1 addresses for RS0.INTERNIC.NET
Found 1 addresses for SOFTWARE.BU.EDU
Found 5 addresses for RS.INTERNIC.NET
Found 1 addresses for NSEGC.BU.EDU
Trying 128.197.27.7
bu.edu
   86400 IN    SOA    BU.EDU HOSTMASTER.BU.EDU(
       961112121    ;serial (version)
       900    ;refresh period
       900    ;retry refresh this often
       604800    ;expiration period
       86400    ;minimum TTL
       )
bu.edu
   86400 IN    NS    SOFTWARE.BU.EDU
bu.edu
   86400 IN    NS    RS.INTERNIC.NET
bu.edu
   86400 IN    NS    NSEGC.BU.EDU
bu.edu
   86400 IN    A    128.197.27.7

  这些本身并没有危险,只是一些机器和它们的 DNS 服务器。这些信息可以用 WHOIS 或在注册域名的站点中检索到。但看看下面几行信息:
bu.edu
   86400 IN    HINFO    SUN-SPARCSTATION-10/41    UNIX
PPP-77-25.bu.edu
   86400 IN    A    128.197.7.237
PPP-77-25.bu.edu
   86400 IN    HINFO    PPP-HOST    PPP-SW
PPP-77-26.bu.edu
   86400 IN    A    128.197.7.238
PPP-77-26.bu.edu
   86400 IN    HINFO    PPP-HOST    PPP-SW
ODIE.bu.edu
   86400 IN    A    128.197.10.52
ODIE.bu.edu
   86400 IN    MX    10 CS.BU.EDU
ODIE.bu.edu
   86400 IN    HINFO    DEC-ALPHA-3000/300LX    OSF1

从这里,我们马上就发现一台 EDC Alpha 运行的是 OSF1 操作系统。在看看:
STRAUSS.bu.edu
   86400 IN    HINFO    PC-PENTIUM    DOS/WINDOWS
BURULLUS.bu.edu
   86400 IN    HINFO    SUN-3/50    UNIX (Ouch)
GEORGETOWN.bu.edu
   86400 IN    HINFO    MACINTOSH    MAC-OS
CHEEZWIZ.bu.edu
   86400 IN    HINFO    SGI-INDIGO-2    UNIX
POLLUX.bu.edu
   86400 IN    HINFO    SUN-4/20-SPARCSTATION-SLC    UNIX
SFA109-PC201.bu.edu
   86400 IN    HINFO    PC    MS-DOS/WINDOWS
UH-PC002-CT.bu.edu
   86400 IN    HINFO    PC-CLONE    MS-DOS
SOFTWARE.bu.edu
   86400 IN    HINFO    SUN-SPARCSTATION-10/30    UNIX
CABMAC.bu.edu
   86400 IN    HINFO    MACINTOSH    MAC-OS
VIDUAL.bu.edu
   86400 IN    HINFO    SGI-INDY    IRIX
KIOSK-GB.bu.edu
   86400 IN    HINFO    GATORBOX    GATORWARE
CLARINET.bu.edu
   86400 IN    HINFO    VISUAL-X-19-TURBO    X-SERVER
DUNCAN.bu.edu
   86400 IN    HINFO    DEC-ALPHA-3000/400    OSF1
MILHOUSE.bu.edu
   86400 IN    HINFO    VAXSTATION-II/GPX    UNIX
PSY81-PC150.bu.edu
   86400 IN    HINFO    PC    WINDOWS-95
BUPHYC.bu.edu
   86400 IN    HINFO    VAX-4000/300    OpenVMS

  可见,任何人都能通过在命令行里键入一个命令,就能收集到一个域里的所有计算机的重要信息。而且只化了 3 秒时间。
  我们利用上述有用的网络命令,可以收集到许多有用的信息,比方一个域里的名字服务器的地址,一台计算机上的用户名,一台服务器上正在运行什么服务,这个服务是哪个软件提供的,计算机上运行的是什么操作系统。
  如果你知道目标计算机上运行的操作系统和服务应用程序后,就能利用已经发现的他们的漏洞来进行攻击。如果目标计算机的网络管理员没有对这些漏洞及时修补的话,入侵者能轻而易举的闯入该系统,获得管理员权限,并留下后门。
  如果入侵者得到目标计算机上的用户名后,能使用口令破解软件,多次试图登录目标计算机。经过尝试后,就有可能进入目标计算机。得到了用户名,就等于得到了一半的进入权限,剩下的只是使用软件进行攻击而已。



            端口扫描分析(二)端口扫描途径

               来源 / 作者: Oliver


二。 端口扫描途径
什么是扫描器
  扫描器是一种自动检测远程或本地主机安全性弱点的程序,通过使用扫描器你可一不留痕迹的发现远程服务器的各种 TCP 端口的分配及提供的服务和它们的软件版本!这就能让我们间接的或直观的了解到远程主机所存在的安全问题。

工作原理
  扫描器通过选用远程 TCP/IP 不同的端口的服务,并记录目标给予的回答,通过这种方法,可以搜集到很多关于目标主机的各种有用的信息(比如:是否能用匿名登陆!是否有可写的 FTP 目录,是否能用 TELNET HTTPD 是用 ROOT 还是 nobady 在跑!)

扫描器能干什么?
  扫描器并不是一个直接的攻击网络漏洞的程序,它仅仅能帮助我们发现目标机的某些内在的弱点。一个好的扫描器能对它得到的数据进行分析,帮助我们查找目标主机的漏洞。但它不会提供进入一个系统的详细步骤。
  扫描器应该有三项功能:发现一个主机或网络的能力;一旦发现一台主机,有发现什么服务正运行在这台主机上的能力;通过测试这些服务,发现漏洞的能力。
  编写扫描器程序必须要很多 TCP/IP 程序编写和 C, Perl 和或 SHELL 语言的知识。需要一些 Socket 编程的背景,一种在开发客户 / 服务应用程序的方法。开发一个扫描器是一个雄心勃勃的项目,通常能使程序员感到很满意。
  下面对常用的端口扫描技术做一个介绍。
TCP connect()
扫描
  这是最基本的 TCP 扫描。操作系统提供的 connect() 系统调用,用来与每一个感兴趣的目标计算机的端口进行连接。如果端口处于侦听状态,那么 connect() 就能成功。否则,这个端口是不能用的,即没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度。如果对每个目标端口以线性的方式,使用单独的 connect() 调用,那么将会花费相当长的时间,你可以通过同时打开多个套接字,从而加速扫描。使用非阻塞 I/O 允许你设置一个低的时间用尽周期,同时观察多个套接字。但这种方法的缺点是很容易被发觉,并且被过滤掉。目标计算机的 logs 文件会显示一连串的连接和连接是出错的服务消息,并且能很快的使它关闭。

TCP SYN
扫描
  这种技术通常认为是 半开放 扫描,这是因为扫描程序不必要打开一个完全的 TCP 连接。扫描程序发送的是一个 SYN 数据包,好象准备打开一个实际的连接并等待反应一样(参考 TCP 的三次握手建立一个 TCP 连接的过程)。一个 SYN|ACK 的返回信息表示端口处于侦听状态。一个 RST 返回,表示端口没有处于侦听态。如果收到一个 SYN|ACK ,则扫描程序必须再发送一个 RST 信号,来关闭这个连接过程。这种扫描技术的优点在于一般不会在目标计算机上留下记录。但这种方法的一个缺点是,必须要有 root 权限才能建立自己的 SYN 数据包。

TCP FIN
扫描
  有的时候有可能 SYN 扫描都不够秘密。一些防火墙和包过滤器会对一些指定的端口进行监视,有的程序能检测到这些扫描。相反, FIN 数据包可能会没有任何麻烦的通过。这种扫描方法的思想是关闭的端口会用适当的 RST 来回复 FIN 数据包。另一方面,打开的端口会忽略对 FIN 数据包的回复。这种方法和系统的实现有一定的关系。有的系统不管端口是否打开,都回复 RST ,这样,这种扫描方法就不适用了。并且这种方法在区分 Unix NT 时,是十分有用的。

IP
段扫描
  这种不能算是新方法,只是其它技术的变化。它并不是直接发送 TCP 探测数据包,是将数据包分成两个较小的 IP 段。这样就将一个 TCP 头分成好几个数据包,从而过滤器就很难探测到。但必须小心。一些程序在处理这些小数据包时会有些麻烦。

TCP
反向 ident 扫描
   ident 协议允许 (rfc1413) 看到通过 TCP 连接的任何进程的拥有者的用户名,即使这个连接不是由这个进程开始的。因此你能,举个例子,连接到 http 端口,然后用 identd 来发现服务器是否正在以 root 权限运行。这种方法只能在和目标端口建立了一个完整的 TCP 连接后才能看到。

FTP
返回攻击
   FTP 协议的一个有趣的特点是它支持代理( proxy FTP 连接。即入侵者可以从自己的计算机 a.com 和目标主机 target.com FTP server-PI( 协议解释器 ) 连接,建立一个控制通信连接。然后,请求这个 server-PI 激活一个有效的 server-DTP( 数据传输进程 ) 来给 Internet 上任何地方发送文件。对于一个 User-DTP ,这是个推测 , 尽管 RFC 明确地定义请求一个服务器发送文件到另一个服务器是可以的。但现在这个方法好象不行了。这个协议的缺点是 能用来发送不能跟踪的邮件和新闻,给许多服务器造成打击,用尽磁盘,企图越过防火墙
  我们利用这个的目的是从一个代理的 FTP 服务器来扫描 TCP 端口。这样,你能在一个防火墙后面连接到一个 FTP 服务器,然后扫描端口(这些原来有可能被阻塞)。如果 FTP 服务器允许从一个目录读写数据,你就能发送任意的数据到发现的打开的端口。
  对于端口扫描,这个技术是使用 PORT 命令来表示被动的 User DTP 正在目标计算机上的某个端口侦听。然后入侵者试图用 LIST 命令列出当前目录,结果通过 Server-DTP 发送出去。如果目标主机正在某个端口侦听,传输就会成功(产生一个 150 226 的回应)。否则,会出现 "425 Can't build data connection: Connection refused." 。然后,使用另一个 PORT 命令,尝试目标计算机上的下一个端口。这种方法的优点很明显,难以跟踪,能穿过防火墙。主要缺点是速度很慢,有的 FTP 服务器最终能得到一些线索,关闭代理功能。

这种方法能成功的情景:
220 xxxxxxx.com FTP server (Version wu-2.4(3) Wed Dec 14 ...) ready.
220 xxx.xxx.xxx.edu FTP server ready.
220 xx.Telcom.xxxx.EDU FTP server (Version wu-2.4(3) Tue Jun 11 ...) ready.
220 lem FTP server (SunOS 4.1) ready.
220 xxx.xxx.es FTP server (Version wu-2.4(11) Sat Apr 27 ...) ready.
220 elios FTP server (SunOS 4.1) ready

这种方法不能成功的情景:
220 wcarchive.cdrom.com FTP server (Version DG-2.0.39 Sun May 4 ...) ready.
220 xxx.xx.xxxxx.EDU Version wu-2.4.2-academ[BETA-12](1) Fri Feb 7
220 ftp Microsoft FTP Service (Version 3.0).
220 xxx FTP server (Version wu-2.4.2-academ[BETA-11](1) Tue Sep 3 ...) ready.
220 xxx.unc.edu FTP server (Version wu-2.4.2-academ[BETA-13](6) ...) ready.

UDP ICMP
端口不能到达扫描
  这种方法与上面几种方法的不同之处在于使用的是 UDP 协议。由于这个协议很简单,所以扫描变得相对比较困难。这是由于打开的端口对扫描探测并不发送一个确认,关闭的端口也并不需要发送一个错误数据包。幸运的是,许多主机在你向一个未打开的 UDP 端口发送一个数据包时,会返回一个 ICMP_PORT_UNREACH 错误。这样你就能发现哪个端口是关闭的。 UDP ICMP 错误都不保证能到达,因此这种扫描器必须还实现在一个包看上去是丢失的时候能重新传输。这种扫描方法是很慢的,因为 RFC ICMP 错误消息的产生速率做了规定。同样,这种扫描方法需要具有 root 权限。

UDP recvfrom()
write() 扫描
  当非 root 用户不能直接读到端口不能到达错误时, Linux 能间接地在它们到达时通知用户。比如,对一个关闭的端口的第二个 write() 调用将失败。在非阻塞的 UDP 套接字上调用 recvfrom() 时,如果 ICMP 出错还没有到达时回返回 EAGAIN- 重试。如果 ICMP 到达时,返回 ECONNREFUSED- 连接被拒绝。这就是用来查看端口是否打开的技术。


ICMP echo
扫描
  这并不是真正意义上的扫描。但有时通过 ping ,在判断在一个网络上主机是否开机时非常有用。

          端口扫描分析(三)一个简单的扫描程序

              来源 / 作者: Oliver


  下面是一个端口扫描器的源程序,功能相当的简单,一个典型的 TCP connect() 扫描。没有对返回的数据进行分析。
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>

int main(int argc, char **argv)
{
  int probeport = 0;
  struct hostent *host;
  int err, i, net;
  struct sockaddr_in sa;

  if (argc != 2) {
   printf(" 用法 : %s hostname/n", argv[0]);
   exit(1);
  }

  for (i = 1; i < 1024; i++) { // 这里有点不是很好,可以将主机地址放在循环外
   strncpy((char *)&sa, "", sizeof sa);
   sa.sin_family = AF_INET;
   if (isdigit(*argv[1]))
    sa.sin_addr.s_addr = inet_addr(argv[1]);
   else if ((host = gethostbyname(argv[1])) != 0)
    strncpy((char *)&sa.sin_addr, (char *)host->h_addr, sizeof sa.sin_addr);
   else {
    herror(argv[1]);
    exit(2);
   }
   sa.sin_port = htons(i);
   net = socket(AF_INET, SOCK_STREAM, 0);
   if (net < 0) {
    perror("/nsocket");
    exit(2);
   }
   err = connect(net, (struct sockaddr *) &sa, sizeof sa);
   if (err < 0) {
    printf("%s %-5d %s/r", argv[1], i, strerror(errno));
    fflush(stdout);
   } else {
    printf("%s %-5d accepted.                 /n", argv[1], i);
    if (shutdown(net, 2) < 0) {
   perror("/nshutdown");
   exit(2);
    }
   }
   close(net);
  }
  printf("                                  /r");
  fflush(stdout);
  return (0);
}
下面这个又是一个端口器:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "netdb.h"
struct hostent *gethostbyaddr();
void bad_addr();
main(argc, argv)
     int    argc;
     char    *argv[];
{
     char        addr[4];
     int        i, j,
             a0, a1, a2, a3,
             c,
             classB, classC, single, hex;
     char        *fmt = "%d.%d.%d";
     char        **ptr;
     struct hostent   *host;
     extern char    *optarg;
     classB = classC = single = hex = 0;
     while((c = getopt(argc,argv,"bcsx")) != EOF) {
         switch(c) {
         case 'b':
             classB++;
             break;
         case 'c':
             classC++;
             break;
         case 's':
             single++;
             break;
         case 'x':
             hex++;
             break;
         }
     }
     if(classB == 0 && classC == 0 && single == 0) {
         fprintf(stderr, "usage: %s [-b||-c||-s] [-x] xxx.xxx[.xxx[.xxx]]/n", argv[0]);
         exit(1);
     }
     if(classB)
         if(hex) {
             fmt = "%x.%x";
             sscanf(argv[3], fmt, &a0, &a1);
         } else {
             fmt = "%d.%d";
             sscanf(argv[2], fmt, &a0, &a1);
         }
     else if(classC)
         if(hex) {
             fmt = "%x.%x.%x";
             sscanf(argv[3], fmt, &a0, &a1, &a2);
         } else {
             fmt = "%d.%d.%d";
             sscanf(argv[2], fmt, &a0, &a1, &a2);
         }
     else if(single)
         if(hex) {
             fmt = "%x.%x.%x.%x";
             sscanf(argv[3], fmt, &a0, &a1, &a2, &a3);
         } else {
             fmt = "%d.%d.%d.%d";
             sscanf(argv[2], fmt, &a0, &a1, &a2, &a3);
         }
     sscanf(argv[1], fmt, &a0, &a1, &a2);
     addr[0] = (unsigned char)a0;
     addr[1] = (unsigned char)a1;
     if(a0>255||a0<0)
         bad_addr(a0);
     if(a1>255||a1<0)
         bad_addr(a1);
     if(classB) {
         if(hex)
             printf("Converting address from hex. (%x.%x)/n", a0, a1);
         printf("Scanning Class B network %d.%d.../n", a0, a1);
         while(j!=256) {
             a2=j;
             addr[2] = (unsigned char)a2;
jmpC:
         if(classC)
             if(hex)
                 printf("Converting address from hex. (%x.%x.%x)/n", a0, a1, a2);
             printf("Scanning Class C network %d.%d.%d.../n", a0, a1, a2);
         while(i!=256) {
             a3=i;
             addr[3] = (unsigned char)a3;
jmpS:
             if ((host = gethostbyaddr(addr, 4, AF_INET)) != NULL) {
                 printf("%d.%d.%d.%d => %s/n", a0, a1, a2, a3, host->h_name);
                 ptr = host->h_aliases;
                 while (*ptr != NULL) {
                     printf("%d.%d.%d.%d => %s (alias)/n", a0, a1, a2, a3, *ptr);
                     ptr++;
                 }
             }
             if(single)
                 exit(0);
             i++;
         }
         if(classC)
             exit(0);
         j++;
         }
     } else if(classC) {
         addr[2] = (unsigned char)a2;
         if(a2>255||a2<0)
             bad_addr(a2);
         goto jmpC;
     } else if(single) {
         addr[2] = (unsigned char)a2;
         addr[3] = (unsigned char)a3;
         if(a2>255||a2<0)
             bad_addr(a2);
         if(a3>255||a3<0)
             bad_a
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值