简易端口扫描器

只是一次简单的课程设计,通过Python实现端口扫描器的功能,附加ping扫描以及简单的banner获取,支持导出扫描结果。

程序运行实例

  • 打印装逼信息:
  • 扫描实例:52116869149
  • 具体用法程序中有说明

程序说明

程序中默认扫描一些常见的端口、支持用户设置端口、支持多端口扫描、支持多IP扫描、支持网段存活主机发现、支持导出。

  1. 通过发送ping包,根据返回包的TTL值判断主机是否存活,关键代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def run(self):
    try:
    cmd = ["ping", "-{op}".format(op=self.get_os()),
    "1", self.ip_pre]
    output = os.popen(" ".join(cmd)).readlines()

    except:
    return False
    if lock.acquire():
    flag = False
    for line in list(output):
    if not line:
    continue
    if str(line).upper().find("TTL") >=0:
    flag = True
    break
    if flag:
    print "[+] IP: %s is OK " % self.ip_pre
    ip_str.append(self.ip_pre)
    lock.release()
    return True
  2. 通过socket建立tcp全连接来判断端口开放信息以及banner信息的抓取,关键代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def Ping(self, Port):
    global OpenPort, lock, Timeout
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.settimeout(Timeout)
    address = (self.IP, Port)
    try:
    sock.connect(address)
    ready = select.select([sock],[],[],1)
    except:
    return False
    if lock.acquire():
    OpenPort.append(str(Port))
    ScanIP_list.append(self.IP)
    if ready[0]:
    print "IP:%s Port:%d Open " % (self.IP, Port) +sock.recv(4096)
    sock.close()
    else:
    print "IP:%s Port:%d Open " % (self.IP, Port) + "Unknow!\n"
    sock.close()
    lock.release()
    return True
  3. 通过队列来判断扫描目标的端口列表是否为空,通过判空来控制在端口扫描的时候不会漏扫,还有就是在多IP端口扫描的时候避免出现误扫IP的状况,关键代码如下:

    1
    2
    3
    4
    def run(self):
    while not self.SingleQueue.empty():
    p = self.SingleQueue.get()
    self.Ping(p)
  4. 调用cmd模块来进行交互,用户通过这个模块来设置线程(在中程序中控制在1-5000,可以修改)、设置连接超时时间、设置端口、进行端口扫描、ping扫描等。关键代码如下:(贴出设置端口、单IP扫描、ping扫描的代码,具体代码请看源码)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def do_port(self, argv):
    global PortList
    PortList = []
    ListTmp = argv.split(' ')
    for port in ListTmp:
    if port.find("..") < 0:
    if not port.isdigit():
    print "Input error!"
    return False
    PortList.append(int(port))
    else:
    RangeLst = port.split("..")
    if not (RangeLst[0].isdigit() and RangeLst[1].isdigit()):
    raise ValueError
    exit()
    for i in range(int(RangeLst[0]), int(RangeLst[1])):
    PortList.append(i)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def do_scan(self, argv):
    print "Start Time %s" % time.ctime() + '\n'
    global nThread, PortList, strIP, ScanIP_list, OpenPort
    del ScanIP_list[:]
    del OpenPort[:]
    ThreadList = []
    try:
    strIP = socket.gethostbyname(str(argv))
    except:
    print "Input error!"
    return False
    SingleQueue = GetQueue(PortList)
    if PortList != None:
    for i in range(0, nThread):
    t = ScanThreadSingle(strIP, SingleQueue)
    ThreadList.append(t)
    for t in ThreadList:
    t.start()
    for t in ThreadList:
    t.join()
    print '\n' + "End Time %s" % time.ctime()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def do_ping(self, argv):
    global commandargs
    ThreadList = []
    print "Start Time %s" % time.ctime() + '\n'
    commandargs = str(argv)
    print "[+] Input is %s " % commandargs + '\n'
    args = "".join(commandargs)
    ip_prefix = '.'.join(args.split('.')[:-1])
    for i in range(1,255):
    ip = '%s.%s' % (ip_prefix,i)
    s = PING(ip)
    ThreadList.append(s)
    for s in ThreadList:
    s.start()
    for s in ThreadList:
    s.join()
    print '\n' + "End Time %s" % time.ctime()
  5. 这些就是整个程序中核心的几个模块,具体代码请看源码。

总结

此次设计参考了P牛早期的一个设计以及Python线程锁的处理方法。实现的功能比较单一,还可以添加SYN半连接扫描、UDP扫描、僵尸扫描等功能;但是由于Windows底层的原因,利用Python在Windows上构造数据包有些困难;在linux上可以通过scapy进行原始数据包的构造与发送,通过网络流量中的一些特征来判断。一些扫描脚本可以看四层发现中的一些脚本。