天天看點

端口掃描分析

端口掃描分析(一)常用的網絡相關指令

  一個端口就是一個潛在的通信通道,也就是一個入侵通道。對目标計算機進行端口掃描,能得到許多有用的資訊。進行掃描的方法很多,可以是手工進行掃描,也可以用端口掃描軟體進行。

  在手工進行掃描時,需要熟悉各種指令。對指令執行後的輸出進行分析。用掃描軟體進行掃描時,許多掃描器軟體都有分析資料的功能。

  通過端口掃描,可以得到許多有用的資訊,進而發現系統的安全漏洞。

  下面首先介紹幾個常用網絡指令,對端口掃描原理進行介紹,然後提供一個簡單的掃描程式。第一節 幾個常用網絡相關指令

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");

    if (argc != 2) {

        fprintf(stderr, "usage: %s hostname\n", argv[0]);

    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.

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 <errno.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");

  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 "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++;

        case ’s’:

            single++;

        case ‘x’:

            hex++;

    if(classB == 0 && classC == 0 && single == 0) {

        fprintf(stderr, "usage: %s [-b||-c||-s] [-x] xxx.xxx[.xxx[.xxx]]\n", argv[0]);

    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)

            fmt = "%x.%x.%x";

            sscanf(argv[3], fmt, &a0, &a1, &a2);

            fmt = "%d.%d.%d";

            sscanf(argv[2], fmt, &a0, &a1, &a2);

    else if(single)

            fmt = "%x.%x.%x.%x";

            sscanf(argv[3], fmt, &a0, &a1, &a2, &a3);

            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++;

            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[3] = (unsigned char)a3;

        if(a3>255||a3<0)

            bad_a

繼續閱讀