python实现端口扫描器

设计今下午终于验收了,╰(°▽°)╯
本文主要实现一个带界面的端口扫描器
一篇特别好的博客https://thief.one/2018/05/17/1/

扫描原理

端口扫描方式主要以下几种:tcp全连接、tcp syn、fin、udp扫描

TCP全连接扫描

利用tcp的三次握手,如果能建立连接,则说明端口开放。扫描过程:
如果该端口是开放的,就能完成TCP三次握手。但是这些样会记录发送者的IP地址,所以很容易被发现。本次使用socket实现这种扫描。
python实现端口扫描器

TCP SYN扫描

不建立完整的TCP连接。端口扫描工具生成一个SYN包,如果目标端口开放,则会返回 SYN-ACK 包,扫描端回应一个RST包,然后在握手完成前关闭连接。
关于实现有以下几个设想:

  • 开始本来想使用原生套接字实现,但是出现各种原因
  • 后来又想借助impacket构造包,再用原生套接字发送,但是也存在问题
  • 最后只好使用scapy,确实简单方便不少,最后成功

python实现端口扫描器

FIN扫描

发送FIN包,如果响应RST包,则端口是关闭的

UDP扫描

发送udp包,如果没有响应,可能是开放的

遇到的问题

QT desinger 设计ui界面

参考:
http://code.py40.com/2561.html

QProgressBar使用

如果将进度条的最大最小值设为0,则进度条会变为繁忙状态,参考:
https://blog.csdn.net/liang19890820/article/details/52302879

QT界面运行假死

运用线程,主界面一个线程,处理程序一个线程,中间通过信号传递消息。参考:
https://www.jb51.net/article/176310.htm
https://zhuanlan.zhihu.com/p/62988456
https://www.jianshu.com/p/ed47a8959854
https://blog.csdn.net/djstavav/article/details/88942098

QT界面转换为代码

开始配过pyuic,可以直接转换,但是重装了pycharm后没有了,重新配置后出现问题,所以采用如下命令,将设计好的界面转换为代码:
pyuic5 -o my.py my.ui

socket编程

参考:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017788916649408

原始套接字

参考:
https://blog.csdn.net/u011580175/article/details/80761274
该文说原始套接字在win10不可使用,但是我验证可以使用,只是运行程序时需要管理员权限,但是用原始套接字自己构造包最后有错误,还是不能完成程序,可能是构造包时出现问题,主要是如下报错

WinError 10022 提供了一个无效的参数

python-nmap使用

python-nmap是一个可以在Python程序中使用nmap端口扫描器的Python包。参考:
https://www.cnblogs.com/aylin/p/5996229.html
https://blog.csdn.net/qq_36119192/article/details/83717690

impacket使用

https://blog.csdn.net/CubieLee/article/details/105041275
使用impacket最后能发出包,但是不太对,可能是构造包还是有问题

scapy使用

https://zhuanlan.zhihu.com/p/51002301
https://www.jianshu.com/p/025337816217
导入包时出现如下报错,可能是包中命名与其它有错误,将导入它的语句放在了导入其它包语句的前面就解决了

'module' object is not callable

IPy使用

主要用于分割cidr类型的ip段,参考
https://www.cnblogs.com/cherishry/p/5916935.html

扫描实现

最简单的全连接扫描

import sys
from socket import *

host = sys.argv[1]
portStr = sys.argv[2].split('-')
startPort = int(portStr[0])
endPort = int(portStr[1])

openPort = []
ip = gethostbyname(host)
for port in range(startPort, endPort + 1):
    # 创建套接字,第一个为协议族名,第二个为套接字。TCP套接字的名字SOCK_STREAM,UDP套接字的名字SOCK_DGRAM
    sock = socket(AF_INET, SOCK_STREAM)
    sock.settimeout(10)
    #s.connect()主动初始化TCP服务器连接。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
    #connect_ex()为connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
    result = sock.connect_ex((ip, port))
    if result == 0:
        openPort.append(port)
print("开放的端口有")
for port in openPort:
    print(port)

多线程的全连接扫描

使用多线程加快扫描速度

import sys
import _thread as thread
from socket import *

def scan(port):
    sock = socket(AF_INET, SOCK_STREAM)
    sock.settimeout(10)
    result = sock.connect_ex((ip, port))
    #print输出时候需要加锁,如果不加锁可能会出现多个输出混合在一起的错误状态,而锁需要在程序启动时创建,从而能让新建的线程共享这个锁:
    if result == 0:
        lock.acquire()
        print("开放的端口", port)
        lock.release()
if __name__ == '__main__':
    host = sys.argv[1]
    portStr = sys.argv[2].split('-')
    startPort = int(portStr[0])
    endPort = int(portStr[1])
    ip = gethostbyname(host)
    #创建锁
    lock = thread.allocate_lock()
    for port in range(startPort, endPort + 1):
        #创建线程
        thread.start_new_thread(scan, (port,))

带界面的端口扫描器

支持对一个ip或者一个ip段的一个端口或者端口范围进行全连接、syn、nmap扫描。
并且采用多线程提高扫描速度,可以设置扫描间隔进一步提高隐蔽性,最后可以将扫描结果保存为文件。

界面设计

python实现端口扫描器

自动转换的代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'my.ui'
#
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_widget(object):
    def setupUi(self, widget):
        widget.setObjectName("widget")
        widget.resize(936, 745)
        widget.setMinimumSize(QtCore.QSize(936, 745))
        widget.setMaximumSize(QtCore.QSize(936, 745))
        self.gridLayout = QtWidgets.QGridLayout(widget)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.label_6 = QtWidgets.QLabel(widget)
        self.label_6.setObjectName("label_6")
        self.horizontalLayout_4.addWidget(self.label_6)
        self.progressBar = QtWidgets.QProgressBar(widget)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.horizontalLayout_4.addWidget(self.progressBar)
        self.gridLayout.addLayout(self.horizontalLayout_4, 1, 0, 1, 1)
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.scrollArea = QtWidgets.QScrollArea(widget)
        self.scrollArea.setMinimumSize(QtCore.QSize(700, 0))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 698, 687))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
        self.verticalLayout.setObjectName("verticalLayout")
        self.textBrowser = QtWidgets.QTextBrowser(self.scrollAreaWidgetContents)
        self.textBrowser.setObjectName("textBrowser")
        self.verticalLayout.addWidget(self.textBrowser)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout_2.addWidget(self.scrollArea, 0, 1, 1, 1)
        self.gridLayout_3 = QtWidgets.QGridLayout()
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.gridLayout_4 = QtWidgets.QGridLayout()
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.lineEdit_2 = QtWidgets.QLineEdit(widget)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout.addWidget(self.lineEdit_2)
        self.gridLayout_4.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.label_3 = QtWidgets.QLabel(widget)
        self.label_3.setMaximumSize(QtCore.QSize(100, 16777215))
        self.label_3.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.label_3.setObjectName("label_3")
        self.horizontalLayout_3.addWidget(self.label_3)
        self.comboBox = QtWidgets.QComboBox(widget)
        self.comboBox.setMinimumSize(QtCore.QSize(50, 0))
        self.comboBox.setMaximumSize(QtCore.QSize(1000, 16777215))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.horizontalLayout_3.addWidget(self.comboBox)
        self.gridLayout_4.addLayout(self.horizontalLayout_3, 4, 0, 1, 1)
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.label_4 = QtWidgets.QLabel(widget)
        self.label_4.setMaximumSize(QtCore.QSize(100, 16777215))
        self.label_4.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.label_4.setObjectName("label_4")
        self.horizontalLayout_5.addWidget(self.label_4)
        self.lineEdit_4 = QtWidgets.QLineEdit(widget)
        self.lineEdit_4.setMaximumSize(QtCore.QSize(50, 16777215))
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.horizontalLayout_5.addWidget(self.lineEdit_4)
        self.label_5 = QtWidgets.QLabel(widget)
        self.label_5.setMaximumSize(QtCore.QSize(100, 16777215))
        self.label_5.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.label_5.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.label_5.setObjectName("label_5")
        self.horizontalLayout_5.addWidget(self.label_5)
        self.lineEdit_3 = QtWidgets.QLineEdit(widget)
        self.lineEdit_3.setMaximumSize(QtCore.QSize(50, 16777215))
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.horizontalLayout_5.addWidget(self.lineEdit_3)
        self.gridLayout_4.addLayout(self.horizontalLayout_5, 6, 0, 1, 1)
        self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_8.setObjectName("horizontalLayout_8")
        self.gridLayout_4.addLayout(self.horizontalLayout_8, 9, 0, 1, 1)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.label_2 = QtWidgets.QLabel(widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        self.label_2.setMinimumSize(QtCore.QSize(10, 10))
        self.label_2.setMaximumSize(QtCore.QSize(60, 100))
        self.label_2.setLineWidth(-1)
        self.label_2.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout_2.addWidget(self.label_2)
        self.lineEdit = QtWidgets.QLineEdit(widget)
        self.lineEdit.setEnabled(True)
        self.lineEdit.setMinimumSize(QtCore.QSize(162, 24))
        self.lineEdit.setMaximumSize(QtCore.QSize(162, 24))
        self.lineEdit.setInputMask("")
        self.lineEdit.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout_2.addWidget(self.lineEdit)
        self.gridLayout_4.addLayout(self.horizontalLayout_2, 2, 0, 1, 1)
        self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_9.setObjectName("horizontalLayout_9")
        self.pushButton_3 = QtWidgets.QPushButton(widget)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout_9.addWidget(self.pushButton_3)
        self.pushButton = QtWidgets.QPushButton(widget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout_9.addWidget(self.pushButton)
        self.gridLayout_4.addLayout(self.horizontalLayout_9, 8, 0, 1, 1)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem, 3, 0, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem1, 1, 0, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem2, 5, 0, 1, 1)
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem3, 7, 0, 1, 1)
        self.gridLayout_3.addLayout(self.gridLayout_4, 0, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout_3, 0, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)

        self.retranslateUi(widget)
        QtCore.QMetaObject.connectSlotsByName(widget)

    def retranslateUi(self, widget):
        _translate = QtCore.QCoreApplication.translate
        widget.setWindowTitle(_translate("widget", "端口扫描工具"))
        self.label_6.setText(_translate("widget", "进度"))
        self.textBrowser.setHtml(_translate("widget",
                                            "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                            "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                            "p, li { white-space: pre-wrap; }\n"
                                            "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\';\"><br /></p>\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\'; font-size:20pt;\"><br /></p>\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\'; font-size:20pt;\"><br /></p>\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\'; font-size:20pt;\"><br /></p>\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\'; font-size:20pt;\"><br /></p>\n"
                                            "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\'; font-size:20pt;\"><br /></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:20pt;\">端口扫描工具</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:20pt;\">             by 启林</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">支持全连接扫描和syn扫描,集成nmap工具</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">扫描目标可以为单个ip或者host/掩码的ip网段的形式</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">端口可以为单个端口或者以“-”连接的端口范围</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">延迟选项为每次扫描新建连接的间隔时间</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">timeout只针对syn扫描,为其等待响应的等待时间</span></p>\n"
                                            "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-size:14pt;\">扫描结果可保存为result.txt文档</span></p></body></html>"))
        self.label.setText(_translate("widget", "目标"))
        self.label_3.setText(_translate("widget", "扫描方式"))
        self.comboBox.setItemText(0, _translate("widget", "full"))
        self.comboBox.setItemText(1, _translate("widget", "syn"))
        self.comboBox.setItemText(2, _translate("widget", "nmap"))
        self.label_4.setText(_translate("widget", "延迟"))
        self.label_5.setText(_translate("widget", "timeout"))
        self.label_2.setText(_translate("widget", "端口"))
        self.lineEdit.setText(_translate("widget", "1-65535"))
        self.pushButton_3.setText(_translate("widget", "保存"))
        self.pushButton.setText(_translate("widget", "开始"))

处理程序

from my import Ui_widget
from PyQt5 import QtWidgets
from scapy.all import *
from socket import *
import nmap
import threading
import sys
from PyQt5.QtCore import *
import IPy
import time


class RunThread(QThread):
    # 用于工作线程与界面线程传递信息
    _signal = pyqtSignal(str, int)
    _signal2 = pyqtSignal(str)

    def __init__(self, host, startPort, endPort, mode, delay, timeout):
        super(RunThread, self).__init__()
        self.host = host
        self.startPort = startPort
        self.endPort = endPort
        self.mode = mode
        self.delay = delay
        self.timeout = timeout

    def run(self):
        # 全连接扫描
        if (self.mode == 'full'):
            # 将ip段分为单个ip的列表,如果是单个ip则为单个ip的列表
            ipList = IPy.IP(self.host)
            # 遍历每个ip
            for ip in ipList:
                # 遍历每个端口
                for port in range(self.startPort, self.endPort + 1):
                    # 对于延迟设置判断,如果没有设置,不管
                    if self.delay != '':
                        time.sleep(eval(self.delay))
                    # 新建线程
                    t = threading.Thread(target=self.fullScan, args=(port, str(ip)))
                    t.start()
        # nmap扫描
        elif (self.mode == 'nmap'):
            self.nmap(self.host, self.startPort, self.endPort)
        # syn扫描
        elif (self.mode == 'syn'):
            ipList = IPy.IP(self.host)
            for ip in ipList:
                for port in range(self.startPort, self.endPort + 1):
                    if self.delay != '':
                        time.sleep(eval(self.delay))
                    t = threading.Thread(target=self.synScan, args=(port, str(ip)))
                    t.start()
        else:
            return 0

    # 全连接扫描函数
    def fullScan(self, port, ip):
        # 建立套接字
        sock = socket(AF_INET, SOCK_STREAM)
        sock.settimeout(10)
        # 建立连接
        result = sock.connect_ex((ip, port))
        # 传递信号
        if result == 0:
            self._signal.emit(ip + ' ' + str(port), 0)
        else:
            self._signal.emit('unknow', 0)

    # syn扫描
    def synScan(self, dPort, desIP):
        # 设置原地址和端口
        srcIP = '192.168.1.13'
        sPort = 4444
        # 使用scapy构造数据包
        ipLayer = IP(src=srcIP, dst=desIP)
        # 设置为syn包
        tcpLayer = TCP(sport=sPort, dport=dPort, flags="S")
        packet = ipLayer / tcpLayer
        # 对于timeout设置判断,如果没有设置,默认为1
        if self.timeout != '':
            time = eval(self.timeout)
        else:
            time = 1
        # 使用sr发送数据包,通过ans得到响应
        ans, unans = sr(packet, timeout=time)
        if ans:
            # 判断响应包是否为syn、ack包
            if (ans[0][1].getlayer(TCP).flags == 'SA'):
                self._signal.emit(desIP + ' ' + str(dPort), 0)
                # 之后构造rset包,中断连接
                ipLayer = IP(src=srcIP, dst=desIP)
                tcpLayer = TCP(sport=sPort, dport=dPort, flags="R")
                packet = ipLayer / tcpLayer
                send(packet)
            else:
                self._signal.emit('unknow', 0)
        else:
            self._signal.emit('unknow', 0)
        return 0

    # 使用nmap扫描
    def nmap(self, host, startPort, endPort):
        port = str(startPort) + '-' + str(endPort)
        nm = nmap.PortScanner()
        self._signal.emit('s', 1)
        # 扫描
        nm.scan(host, port)
        # 显示扫描的具体命令
        self._signal.emit(nm.command_line(), 1)
        # 分解显示扫描结果
        for i in nm.all_hosts():
            self._signal2.emit(i)
            for protocal in nm[i].all_protocols():
                for p in nm[i][protocal].keys():
                    result = str(p) + "  " + nm[i][protocal][p]['state'] + "  " + nm[i][protocal][p]['product'] + "  " + \
                             nm[i][protocal][p]['version']
                    self._signal.emit(result, 1)
        self._signal.emit('e', 1)


class myWin(QtWidgets.QWidget, Ui_widget):

    def __init__(self):
        super(myWin, self).__init__()
        self.setupUi(self)
        # 两个函数的点击函数
        self.pushButton.clicked.connect(self.button)
        self.pushButton_3.clicked.connect(self.button3)

    # 取得界面输入的值
    def get(self):
        host = self.lineEdit_2.text()
        port = self.lineEdit.text()
        mode = self.comboBox.currentText()
        delay = self.lineEdit_4.text()
        timeout = self.lineEdit_3.text()
        return host, port, mode, delay, timeout

    # 开始按钮点击函数
    def button(self):
        host, port, mode, delay, timeout = self.get()
        port = port.split('-')
        startPort = int(port[0])
        # 判断是对单个端口,还是端口范围扫描
        if (len(port) == 2):
            endPort = int(port[1])
        else:
            endPort = int(port[0])
        # 设置界面进度条的最大值
        max = (endPort - startPort + 1) * len(IPy.IP(host))
        self.textBrowser.clear()
        self.progressBar.setMaximum(max)
        self.progressBar.setValue(0)
        self.thread = RunThread(host, startPort, endPort, mode, delay, timeout)
        self.thread._signal.connect(self.call_backlog)
        self.thread._signal2.connect(self.call_backlog2)
        self.thread.start()

    # 保存点击按钮
    def button3(self):
        result = str(self.textBrowser.toPlainText())
        with open(r'C:\Users\Desktop\result.txt', 'w') as f:
            f.write(result)

    # 信号处理函数2
    def call_backlog2(self, msg):
        self.textBrowser.append(str(msg))

    # 信号处理函数1
    def call_backlog(self, msg, flag):
        # 通过flag值判断,0为syn与full,1为nmap
        if (flag == 0):
            if (msg == 'unknow'):
                # 进度条更新
                self.progressBar.setValue(self.progressBar.value() + 1)
            else:
                self.textBrowser.append(str(msg))
                self.progressBar.setValue(self.progressBar.value() + 1)
        elif (flag == 1):
            # 开始扫描,进度条设置为忙状态
            if (msg == 's'):
                self.progressBar.setMaximum(0)
                self.progressBar.setMinimum(0)
            # 扫描结束,设置为100%
            elif (msg == 'e'):
                self.progressBar.setMaximum(1)
                self.progressBar.setValue(1)
            else:
                self.textBrowser.append(str(msg))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Widget = myWin()
    Widget.show()
    sys.exit(app.exec_())

运行结果

对192.168.1.0/24网段的1-100端口全连接扫描
python实现端口扫描器
通过抓取流量可以进一步验证过程
python实现端口扫描器
对192.168.1.58网段的1-100端口syn扫描
python实现端口扫描器
抓取的流量
对21端口的扫描过程
python实现端口扫描器
对192.168.1.58网段的1-100端口调用nmap扫描
python实现端口扫描器

上一篇:QT使用右键菜单QMenu


下一篇:学习使用PySide2制作一个简单的计算器