欢迎光临!
若无相欠,怎会相见

Python学习之端口扫描器(2)

接着学习,把上次的端口扫描器添加点儿功能,可以在命令行指定扫描目标。不过,我先把单线程代码贴出来。

单线程代码

照着书一步一步来,同时添加了一些自己的理解,代码中的字符串,我一般使用的都是Unicode编码。

import optparse
import socket


def connScan(targetHost, targetPort):
    try:
        connSkt = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        connSkt.connect((targetHost, targetPort))
        connSkt.send('hello\r\n')
        results = connSkt.recv(100)  #.decode('unicode')此处接受服务器返回的信息
        print(u'[+]%d/tcp 开启' % targetPort)
        print(u'[+]' + str(results))
        connSkt.close()
    except:
        print(u'[-]%d/tcp 关闭' % targetPort)


def portScan(targetHost, targetPorts):
    try:
        targetIP = socket.gethostbyname(targetHost)
    except:
        print(u"[-] 不能识别 '%s' : 未知主机" % targetHost)
        return
    try:
        targetName = socket.gethostbyaddr(targetIP)
        print(u'\n[+]扫描:' + targetName[0])
    except:
        print(u'\n[+]扫描:' + targetIP)
    socket.setdefaulttimeout(1)
    for targetPort in targetPorts:
        print(u'扫描端口: ' + str(targetPort))
        connScan(targetHost, int(targetPort))


def main():
    parser = optparse.OptionParser(u'使用方法 python scanhost.py -H <目标主机> -p <目标端口>')
    parser.add_option('-H', dest='targetHost',type='string',help=u'指定目标主机')
    parser.add_option('-p', dest='targetPort',type='int', help=u'指定目标端口')
    (options, args) = parser.parse_args()
    targetHost = options.targetHost
    targetPort = options.targetPort
    args.append(targetPort)  #此行代码不可缺,否则第一个端口无法测试
    if (targetHost == None)|(targetPort == None):
        print(u'[-] 你必须指定一个主机和端口!')
        # print(parser.usage)
        exit(0)
    portScan(targetHost, args)


if __name__ == '__main__':
    main()

我对上面的代码进行了测试,也是同书上一样测试的是qq.com,结果如下

E:\Projects\Python\20171114>python scanhost.py -H www.qq.com -p 21 22 23 443 80 445

[+]扫描:180.163.26.39
扫描端口: 22
[-]22/tcp 关闭
扫描端口: 23
[-]23/tcp 关闭
扫描端口: 443
[-]443/tcp 关闭
扫描端口: 80
[+]80/tcp 开启
[+]HTTP/1.1 400 Bad Request
Server: squid/3.5.24
Date: Sat, 18 Nov 2017 08:57:28 GMT
Content-Type: t
扫描端口: 445
[-]445/tcp 关闭
扫描端口: 21
[-]21/tcp 关闭

其实,我还对百度测试过,不过有一个返回时乱码,结果如下:

E:\Projects\Python\20171114>python scanhost.py -H www.baidu.com -p 21 22 23 443 80 445

[+]扫描:115.239.211.112
扫描端口: 22
[-]22/tcp 关闭
扫描端口: 23
[-]23/tcp 关闭
扫描端口: 443
[+]443/tcp 开启
[+]╚╔ ╗╗ #此处我也不知道是什么
扫描端口: 80
[-]80/tcp 关闭
扫描端口: 445
[-]445/tcp 关闭
扫描端口: 21
[-]21/tcp 关闭

不过,单线程的会比较慢,当测试较多的目标时。那就需要进行多线程扫描了。

多线程

多线程能在扫描速度上帮助很多,可惜,如果多个线程同时输出的话,就会导致顺序很乱。书中的解决方案是:

为了让函数完整正确的输出信息,我们就使用信号量。一个简单的信号
量为我们提供了一个锁来阻止其他线程进入。注意在打印输出之前,我们抢占
一个锁使用 screenLock.acquire()来加锁。如果锁打开,信号量将允许线程继
续运行然后打印输出,如果锁定,我们将要等到控制信号量的进程释放锁。利
用信号量,我们可以保证在任何个定的时间只有一个线程在打印屏幕输出。

–摘自《python绝技:运用python成为顶级黑客》

可惜我看的不是很懂,郁闷!

多线程代码

在我的学习过程中,我的代码虽然与原书差不多,可是,我都是一个字符一个字符慢慢输入PyCharm,不是直接粘贴代码,然后调试运行的,这样也是一个学习过程。

# -*- coding: utf-8 -*-
# @Time    : 2017/11/18 16:31
# @Author  : Liangz
# @Site    : www.liangz.org
# @File    : ScanHostPlus.py
# @Software: PyCharm


import socket
import optparse
import threading


screenLock = threading.Semaphore(value=1)
def connScan(targetHost, targetPort):
    try:
        connSkt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        connSkt.connect((targetHost, targetPort))
        connSkt.send('hello\r\n')
        results = connSkt.recv(100)
        screenLock.acquire()
        print(u'[+]%d /tcp 开启' % targetPort)
        print(u'[+]' +str(results))
    except:
        screenLock.acquire()
        print(u'[-]%d /tcp 关闭' % targetPort)
    finally:
        screenLock.release()
        connSkt.close()


def portScan(targetHost, targetPorts):
    try:
        targetIP = socket.gethostbyname(targetHost)
    except:
        print u"[-] 无法解决 '%s' : 未知主机" % targetHost
        return
    try:
        targetName = socket.gethostbyaddr(targetIP)
        print(u'\n[+] 扫描 : ' + targetName)
    except:
        print(u'\n[+] 扫描 :' + targetIP)
    socket.setdefaulttimeout(1)
    for targetPort in targetPorts:
        print(u'扫描端口 :' + str(targetPort))
        t = threading.Thread(target=connScan,args=(targetHost, int(targetPort)) )
        t.start()


def main():
    parser = optparse.OptionParser(u'使用方法:python ScanHostPlus.py -H <target host> -p <target port>')
    parser.add_option('-H', dest='targetHost', type='string', help=u'指定目标主机')
    parser.add_option('-p', dest='targetPort', type='int', help=u'指定目标端口')
    (options, args) = parser.parse_args()
    targetHost = options.targetHost
    targetPort = options.targetPort
    args.append(targetPort)
    if (targetHost == None)|(targetPort ==None):
        print(u'[-] 你必须指定目标主机和目标端口!')
        exit(0)
    portScan(targetHost, args)

if __name__ == '__main__':
    main()

分别以百度和腾讯测试:

E:\Projects\Python\20171114>python scanhostplus.py -H www.baidu.com -p 21 22 23 443 80 445

[+] 扫描 :115.239.210.27
扫描端口 :22
扫描端口 :23
扫描端口 :443
扫描端口 :80
扫描端口 :445
扫描端口 :21
[+]443 /tcp 开启
[+]╚╔ ╗╗
[-]22 /tcp 关闭
[-]23 /tcp 关闭
[-]445 /tcp 关闭
[-]21 /tcp 关闭
[-]80 /tcp 关闭
E:\Projects\Python\20171114>python scanhostplus.py -H www.qq.com -p 21 22 23 443 80 445

[+] 扫描 :180.163.26.39
扫描端口 :22
扫描端口 :23
扫描端口 :443
扫描端口 :80
扫描端口 :445
扫描端口 :21
[+]80 /tcp 开启
[+]HTTP/1.1 400 Bad Request
Server: squid/3.5.24
Date: Sat, 18 Nov 2017 09:43:01 GMT
Content-Type: t
[-]23 /tcp 关闭
[-]22 /tcp 关闭
[-]443 /tcp 关闭
[-]445 /tcp 关闭
[-]21 /tcp 关闭

如有错误,敬请指出!

赞(0) 打赏
转载请注明:飘零博客 » Python学习之端口扫描器(2)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

欢迎光临