在本教程中,我们将演示如何通过构建基本端口扫描程序与Python建立网络连接。我们将要做的是基于ip / port组合反复建立网络套接字连接。为了实现这一目标,我们将引入一个新概念,即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
请注意,在上面的代码片段中,for循环的主体是缩进的。通常人们用2个空格或用制表符缩进,只要你在整个剧本中保持一致就没关系。要制作简单的端口扫描程序,我们将使用创建套接字连接的代码片段替换print语句。下面的代码显示了如何使用内置套接字模块建立套接字连接:
>>>
>>> import socket
>>>
>>> s = socket.socket()
>>> s.connect(('127.0.0.1', 22))
>>> s.send('Primal Security n')
17
>>> banner = s.recv(1024)
>>> print banner
OpenSSH
上面我们导入套接字模块并调用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 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循环。这将涉及将循环通过主机的外层for循环和将循环通过端口的内部for循环。下面是如何利用嵌套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数组中的每个端口,然后继续前进到下一个主机。对于最终端口扫描程序,您可能希望将print语句修改为仅打印已打开的端口。
在一天结束时,您会发现Nmap仍然是端口扫描的更好选择,但我们将在后面的文章中构建这些概念,以完成一些更实际的用例。花一些时间来探索插座模块“dir(socket)”中可用的各种功能。