python编写一个端口扫描器

编写一个端口扫描器

  • 任何一个靠谱的网络攻击,都是起步于侦察。所以攻击服务器,也就是检查服务的漏洞。我使用的两种方式无非是web注入和端口扫描。所以先编写一个端口扫描器
  • 端口扫描是基于TCP的,一共分为三个步骤,分别编写三个方法:
    • 处理数据,也就是处理用户输入数据的,此处我们定义为main函数,用来获取主机名和端口
    • 将主机名转换为对应的IPv4互联网地址,采socket.gethostbyname(hostname),获取到IP,然后调用处理端口扫描的函数.定义为portScan(tgtHost,tgtPorts)
    • 端口扫描,也是就TCP的全连接,对目标地址和端口进行连接。最后为了确定该端口上运行的什么服务,我们还会发送垃圾信息,并读取返回的Banner.函数定义为connScan(tgtHost,tgtPort)

实现端口扫描器

  1. main函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    def main():
    parser = optparse.OptionParser("usage: %prog" + \
    "-H <tgtHost host> -P <tgtPort>" ,version="%prog 1.0")
    ''' 添加命令行参 '''
    parser.add_option('-H',dest='Host',type='string',help='specify target host')
    parser.add_option('-P',dest='Port',type='string',\
    help='specify target port[s] separated by command')
    (options ,args) = parser.parse_args()
    tgtHost = options.Host
    tgtPorts = str(options.Port).split(",")
    if (tgtHost == None) or (tgtPorts[0] == None):
    print '[-] You must specify a target host and port[s]'
    exit(0)
    portScan(tgtHost,tgtPorts)
    </code></pre>
    2. portScan(tgtHost,tgtPorts)
    <pre><code>
    def portScan(tgtHost,tgtPorts):
    try:
    tgtIP = gethostbyname(tgtHost)
    except:
    print "[-] cannot resolve '%s':Unknown host" %(tgtHost)
    try:
    tgtName = gethostbyaddr(tgtIP)
    print '\n[+] Scan Reselts for:' + tgtName[0]
    except:
    print '\n[+] Scan Results for: '+ tgtIP
    setdefaulttimeout(1)
    for tgtPort in tgtPorts:
    connScan(tgtHost,tgtPort)
    </code></pre>
    3. connScan(tgtHost, tgtPort)
    <pre><code>
    def connScan(tgtHost, tgtPort):
    try:
    connSkt = socket(AF_INET,SOCK_STREAM)
    connSkt.connect((tgtHost,tgtPort))
    connSkt.send('Hello\r\n')
    results = connSkt.recv(100)
    lock.acquire()
    print "[+]%d/TCP open" %(tgtPort)
    print "[+] "+str(results)
    except:
    lock.acquire()
    print "[-]%d/TCP closed" %(tgtPort)
    finally:
    lock.release()
    connSkt.close()
  2. 使用
    运行后如下结果

    python portscanner.py -H localhost -P 21,22
    [+] Scan Reselts for:localhost
    [+]22/TCP open
    [+] SSH-2.0-OpenSSH_6.4
    [+]21/TCP open
    [+] 220 (vsFTPd 3.0.2)

优化

  1. 线程优化
    采用多线程扫描
    1
    2
    3
    for tgtPort in tgtPorts:
    t=threading.Thread(target=connScan,args=(tgtIP,int(tgtPort)))
    t.start()

这让扫描速度有了很大改进,但又是一个缺点,多个线程同时打印输出,可能出现乱码和失序。我们需要一个信号量来控制,这样代码就会变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import threading
import multiprocessing
lock = multiprocessing.Semaphore(value=1) #锁
def connScan(tgtHost, tgtPort):
try:
connSkt = socket(AF_INET,SOCK_STREAM)
connSkt.connect((tgtHost,tgtPort))
connSkt.send('Hello\r\n')
results = connSkt.recv(100)
lock.acquire()
print "[+]%d/TCP open" %(tgtPort)
print "[+] "+str(results)
except:
lock.acquire()
print "[-]%d/TCP closed" %(tgtPort)
finally:
lock.release()
connSkt.close()
def portScan(tgtHost,tgtPorts):
try:
tgtIP = gethostbyname(tgtHost)
except:
print "[-] cannot resolve '%s':Unknown host" %(tgtHost)
try:
tgtName = gethostbyaddr(tgtIP)
print '\n[+] Scan Reselts for:' + tgtName[0]
except:
print '\n[+] Scan Results for: '+ tgtIP
setdefaulttimeout(1)
for tgtPort in tgtPorts:
#print 'Scanning port ' + tgtPort
t=threading.Thread(target=connScan,args=(tgtIP,int(tgtPort)))
t.start()

完整代码请参考portscanner.py

  1. 使用nmap端口扫描代码
    2.1 下载Python-Nmap
    pip install Python-Nmap
    2.2 实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import nmap
    import optparse
    from socket import *
    import os,sys
    def nmapScan(tgtHost,tgtPort):
    nmScan = nmap.PortScanner()
    nmScan.scan(tgtHost,tgtPort)
    status = nmScan[tgtHost]['tcp'][int(tgtPort)]['state']
    print '[!] %s tcp/%s %s' %(tgtHost,tgtPort,status)

详细代码查看nmapport.py