##端口掃描
這一章將會演示如何通過Python的網絡連接來開發一個基礎的端口掃描器,我們的設計思路是使用socket一遍又一遍的去連接ip與端口的組合的新值,為了方面我們能夠快速的完成它,首先需要介紹一點新的概念,for循環:
```
>>>
>>> for port in range(1000,1024):
... print "[+] The port is: "+str(port)
...
[+] The port is: 1000
[+] The port is: 1001
[+] The port is: 1002
[+] The port is: 1003
[+] The port is: 1004
[+] The port is: 1005
[+] The port is: 1006
[+] The port is: 1007
[+] The port is: 1008
[+] The port is: 1009
[+] The port is: 1010
[+] The port is: 1011
[+] The port is: 1012
[+] The port is: 1013
[+] The port is: 1014
[+] The port is: 1015
[+] The port is: 1016
[+] The port is: 1017
[+] The port is: 1018
[+] The port is: 1019
[+] The port is: 1020
[+] The port is: 1021
[+] The port is: 1022
[+] The port is: 1023
```
注意上面那段代碼在循環體內的縮進,通常情況下是空兩格或一個tab鍵,但這都沒有關系,只要你的整個代碼一直就可以了。我么所寫的那個簡短的端口掃描器的核心代碼會寫在上面代碼中的輸出塊部分,然后建立一個socket連接。下面的代碼就演示了如何使用內建的socket模塊去建立一個socket連接:
```
>>>
>>> import socket
>>>
>>> s = socket.socket()
>>> s.connect(('127.0.0.1s', 22))
>>> s.send('Primal Security \n')
17
>>> banner = s.recv(1024)
>>> print banner
OpenSSH
```
上面這個例子:我們先import這socket模塊并且調用connect()函數去連接指定的IP地址與端口。它就會建立一個TCP連接(SYN/SYN-ACK/ACK)并且我們再通過send()函數給服務器發送一個真實的數據,然后使用recv()打印出響應的內容。現在教大家如何容錯socket,對于不能打開的連接:
```
>>>
>>> s.connect(('127.0.0.1', 23))
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 1, in connect
socket.error: (111, 'Connection refused')
```
對于上面的錯誤有若干中處理方式,這里我們使用最簡單的一種方式:使用"try/except"循環來處理錯誤:
```
>>>
>>> try:
... s.connect(('127.0.0.1', 23))
... except: pass
...
>>>
```
現在就不會出現錯誤了,一行很簡單的代碼就讓你的程序能夠繼續工作下去^_^。現在讓我們使用之前學到的知識,使用for循環來寫一個簡單的端口掃描器:
```
>>>
>>> for port in range(20,25):
... try:
... print "[+] Attempting to connect to 127.0.0.1:"+str(port)
... s.connect(('127.0.0.1', port))
... s.send('Primal Security \n')
... banner = s.recv(1024)
... if banner:
... print "[+] Port "+str(port)+" open: "+banner
... s.close()
... except: pass
...
17
[+] Attempting to connect to 127.0.0.1:20
[+] Attempting to connect to 127.0.0.1:21
[+] Attempting to connect to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Attempting to connect to 127.0.0.1:23
[+] Attempting to connect to 127.0.0.1:24
[+] Attempting to connect to 127.0.0.1:25
```
上面我們演示了使用"try/except"循環來處理當socket連接的時候遇到端口關閉的錯誤,同時上面還演示了如何使用"if"語句打印出可以連接成功的端口。下面我們將創建一個我們掃描指定端口的掃描器,這里的端口號,我們使用數組來存儲,然后遍歷這一個數組:
```
>>>
>>> ports = [22, 445, 80, 443, 3389]
>>> for port in ports:
... print port
...
22
445
80
443
3389
>>>
```
如果我們想一次性掃描多臺主機,可以使用一個for循環嵌套。最外層的是主機的ip,然后里面的for循環是端口。下面有一個基礎的例子,展示了如何通過循環嵌套來構建一個簡單的掃描器:
```
>>>
>>> hosts = ['127.0.0.1', '192.168.1.5', '10.0.0.1']
>>>
>>> ports = [22, 445, 80, 443, 3389]
>>>
>>> for host in hosts:
... for port in ports:
... try:
... print "[+] Connecting to "+host+":"+str(port)
... s.connect((host, port))
... s.send('Primal Security \n')
... banner = s.recv(1024)
... if banner:
... print "[+] Port "+str(port)+" open: "+banner
... s.close()
... except:pass
...
[+] Connecting to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Connecting to 127.0.0.1:445
[+] Connecting to 127.0.0.1:80
[+] Connecting to 127.0.0.1:443
[+] Connecting to 127.0.0.1:3389
[+] Connecting to 192.168.1.5:22
[+] Connecting to 192.168.1.5:445
[+] Connecting to 192.168.1.5:80
[+] Connecting to 192.168.1.5:443
[+] Connecting to 192.168.1.5:3389
[+] Connecting to 10.0.0.1:22
[+] Connecting to 10.0.0.1:445
[+] Connecting to 10.0.0.1:80
[+] Connecting to 10.0.0.1:443
[+] Connecting to 10.0.0.1:3389
```
正如你所看到的結果,它把hosts數組里面的所有值都遍歷了一次ports數組,等hosts[0]掃描完成之后再掃描hosts[1]依次類推。在這個例子里面你也可以修改里面的代碼,只讓它顯示出可以打開的端口。
在這最后,你會發現還是Nmap最好用,但是我們將在后面的文章里面繼續完善這個實例,大家可以花點時間去學習一些socket模塊其他的功能函數,大家可以使用"dir(socket)"來了解更多,當然還有'help()'.