用Python做一个安全攻防工具:端口嗅探器(9)

传送门

本系列原创博文传送门:

用Python做一个安全攻防工具:端口嗅探器(1)

用Python做一个安全攻防工具:端口嗅探器(2)

用Python做一个安全攻防工具:端口嗅探器(3)

用Python做一个安全攻防工具:端口嗅探器(4)

用Python做一个安全攻防工具:端口嗅探器(5)

用Python做一个安全攻防工具:端口嗅探器(6)

用Python做一个安全攻防工具:端口嗅探器(7)

用Python做一个安全攻防工具:端口嗅探器(8)

用Python做一个安全攻防工具:端口嗅探器(9)

 

本章目标

本章目标是将工具打包成可执行文件。

暂时选择py2exe模块。

步骤实施

找了一篇示范性的文章,《使用 py2exe 打包 Python 程序》。

第一步是安装py2exe模块:

pip install py2exe --user

这里需要加上 “--user” ,否则会出现权限问题。

第二步,在文件夹下,新建python文件 setup.py :

from distutils.core import setup

setup(console=["PortSearchGUI.py"])  # 入口文件

第三步,将命令行切换到python文件目录下:

C:\Users\admin\PycharmProjects\PortSearch>python setup.py py2exe

出现报错:

error: invalid command 'py2exe'

修改代码:

from distutils.core import setup
import py2exe

setup(console=["PortSearchGUI.py"])  # 入口文件

第二行的代码 “import py2exe”,一开始提示没有被调用,实际上在命令行运行时,会使用到,加上之后,前面的报错没有了。

出现了新的报错:

running py2exe

  9 missing Modules
  ------------------
? AppKit                              imported from pyperclip
? Foundation                          imported from pyperclip
? PyQt4                               imported from pyperclip
? _posixshmem                         imported from multiprocessing.resource_tracker, multiprocessing.shared_memory
? _testinternalcapi                   imported from test.support
? gtk                                 imported from pyperclip
? qtpy                                imported from pyperclip
? readline                            imported from cmd, code, pdb
? resource                            imported from test.support
Building 'dist\PortSearchGUI.exe'.
error: [Errno 2] No such file or directory: 'C:\\Users\\admin\\AppData\\Roaming\\Python\\Python39\\site-packages\\py2exe\\run-py3.9-win-amd64.exe'

先找找缺少 run-py3.9-win-amd64.exe 的原因,据说py2exe只支持 python 3.4及以下。

查了下,有人建议先从缺失的模块开始入手,这些missing Modules理论上讲在代码里是不会调到的,试着修改代码试试:

from distutils.core import setup
import py2exe

setup(console=["PortSearchGUI.py"],  # 入口文件
      options={'py2exe': {'excludes': ['AppKit', 'Foundation', 'PyQt4', '_posixshmem', '_testinternalcapi', 'gtk',
                                       'qtpy', 'readline', 'resource']}},)  # 入口文件

再次运行下看看,报错,提示少了,只剩下一个问题:

running py2exe
Building 'dist\PortSearchGUI.exe'.
error: [Errno 2] No such file or directory: 'C:\\Users\\admin\\AppData\\Roaming\\Python\\Python39\\site-packages\\py2exe\\run-py3.9-win-amd64.exe'

到 C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\py2exe 目录下看一看,发现有个 

run_w-py3.9-win-amd64.exe 文件:

复制一个文件出来,将其命名为: run-py3.9-win-amd64.exe

再次运行:

C:\Users\admin\PycharmProjects\PortSearch>python setup.py py2exe

运行成功:

running py2exe
Building 'dist\PortSearchGUI.exe'.
Building shared code archive 'dist\library.zip'.
Copy c:\python39\python39.dll to dist
Copy C:\Python39\DLLs\unicodedata.pyd to dist\unicodedata.pyd
Copy C:\Python39\DLLs\select.pyd to dist\select.pyd
Copy C:\Python39\DLLs\_bz2.pyd to dist\_bz2.pyd
Copy C:\Python39\DLLs\_lzma.pyd to dist\_lzma.pyd
Copy C:\Python39\DLLs\pyexpat.pyd to dist\pyexpat.pyd
Copy C:\Python39\DLLs\_socket.pyd to dist\_socket.pyd
Copy C:\Python39\DLLs\_hashlib.pyd to dist\_hashlib.pyd
Copy C:\Python39\DLLs\_decimal.pyd to dist\_decimal.pyd
Copy C:\Python39\DLLs\_ssl.pyd to dist\_ssl.pyd
Copy C:\Python39\DLLs\_queue.pyd to dist\_queue.pyd
Copy C:\Python39\DLLs\_elementtree.pyd to dist\_elementtree.pyd
Copy C:\Python39\DLLs\_ctypes.pyd to dist\_ctypes.pyd
Copy C:\Python39\DLLs\_tkinter.pyd to dist\_tkinter.pyd
Copy C:\Python39\DLLs\_testcapi.pyd to dist\_testcapi.pyd
Copy C:\Python39\DLLs\_asyncio.pyd to dist\_asyncio.pyd
Copy C:\Python39\DLLs\_multiprocessing.pyd to dist\_multiprocessing.pyd
Copy C:\Python39\DLLs\_overlapped.pyd to dist\_overlapped.pyd
Copy C:\Python39\lib\site-packages\shiboken2\shiboken2.pyd to dist\shiboken2.shiboken2.pyd
Copy C:\Python39\lib\site-packages\PySide2\QtNetwork.pyd to dist\PySide2.QtNetwork.pyd
Copy C:\Python39\lib\site-packages\PySide2\QtWidgets.pyd to dist\PySide2.QtWidgets.pyd
Copy C:\Python39\lib\site-packages\PySide2\QtCore.pyd to dist\PySide2.QtCore.pyd
Copy C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PyQt5\QtWidgets.pyd to dist\PyQt5.QtWidgets.pyd
Copy DLL C:\Python39\lib\site-packages\PySide2\Qt5Qml.dll to dist\
Copy DLL C:\Python39\DLLs\tcl86t.dll to dist\
Copy DLL C:\Python39\DLLs\libssl-1_1.dll to dist\
Copy DLL C:\Python39\DLLs\libcrypto-1_1.dll to dist\
Copy DLL C:\Python39\lib\site-packages\PySide2\Qt5Core.dll to dist\
Copy DLL C:\Python39\lib\site-packages\PySide2\pyside2.abi3.dll to dist\
Copy DLL C:\Python39\DLLs\tk86t.dll to dist\
Copy DLL C:\Python39\lib\site-packages\PySide2\Qt5Widgets.dll to dist\
Copy DLL C:\Python39\lib\site-packages\PySide2\Qt5Gui.dll to dist\
Copy DLL C:\Python39\DLLs\libffi-7.dll to dist\
Copy DLL C:\Python39\lib\site-packages\PySide2\Qt5Network.dll to dist\
Copy DLL C:\Python39\lib\site-packages\shiboken2\shiboken2.abi3.dll to dist\
Copy ExtensionDLL C:\Python39\python3.dll to dist\

在项目目录下看到新增一个文件夹:

找到入口文件 PortSearchGUI.exe

到项目目录下看一下,双击运行入口文件,出现报错:

打开log文件,发现报错:

Traceback (most recent call last):
  File "PortSearchGUI.py", line 3, in <module>
  File "<frozen zipimport>", line 259, in load_module
  File "<loader>", line 10, in <module>
  File "<loader>", line 8, in __load
ImportError: (could not import module 'PySide2.QtGui') 'C:\\Users\\admin\\PycharmProjects\\PortSearch\\dist\\PySide2.QtWidgets.pyd'

在命令行里输入:python

输入:import PySide2.QtGui

C:\Users\admin\PycharmProjects\PortSearch>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import PySide2.QtGui

发现不报错,试着在 PortSearchGUI.py 中加入一行引入 import PySide2.QtGui,删除dist目录,再试着打包一次。

报错:

This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

查一下问题,根据 信息 ,先进入 C:\Python39\Lib\site-packages\PySide2 ,将 plugins 文件夹下的 platforms 文件夹复制到 PySide2目录下,与 designer.exe 同目录。

再次打包,还是报一样的错误,再将 PySide2文件夹复制到  C:\Users\admin\AppData\Roaming\Python\Python39\site-packages 目录下,再次打包,再次试图运行,报了另外一个错:

查看日志文件,看到报错:

Traceback (most recent call last):
  File "PortSearchGUI.py", line 3, in <module>
ModuleNotFoundError: No module named 'PySide2.QtWidgets'

在PortSearchGUI.py中加入引用 

import PySide2.QtWidgets

再次打包并运行,在日志里又看到:

Traceback (most recent call last):
  File "PortSearchGUI.py", line 3, in <module>
ModuleNotFoundError: No module named 'PySide2.QtWidgets'

修改:

from PySide2 import *

再次打包并运行,在日志里又看到:

Traceback (most recent call last):
  File "PortSearchGUI.py", line 3, in <module>
AttributeError: module 'PySide2' has no attribute 'QtCore'

找不到问题,试着运行了下 PortSearchGUI.py,发现报错:

Traceback (most recent call last):
  File "C:\Users\admin\PycharmProjects\PortSearch\PortSearchGUI.py", line 3, in <module>
    from PySide2.QtWidgets import QApplication, QLineEdit, QLabel, QPlainTextEdit, QPushButton, QWidget  # 引入模块
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PySide2\__init__.py", line 107, in <module>
    _setupQtDirectories()
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PySide2\__init__.py", line 54, in _setupQtDirectories
    for dir in _additional_dll_directories(pyside_package_dir):
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PySide2\__init__.py", line 26, in _additional_dll_directories
    raise ImportError(shiboken2 + ' does not exist')
ImportError: C:\Users\admin\AppData\Roaming\Python\Python39\shiboken2\libshiboken does not exist

安装 shiboken2,发现安装在c盘根目录下,跟之前的操作一样,复制一份到 C:\Users\admin\AppData\Roaming\Python\Python39\site-packages 

再运行试试,能跑起来了,再打包试试,又报这个错:

在个人环境变量里新建:

QT_PLUGINS_PATH    C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PySide2\plugins

QT_PLATFORMS_PATH    C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\PySide2\plugins\platforms

再次打包,运行,终于出来了:

泪流满面……

精简不必要的代码,最后PortSearchGUI.py代码如下:

 

# coding=utf-8

from PySide2 import QtGui
from PySide2.QtWidgets import QApplication, QLineEdit, QLabel, QPlainTextEdit, QPushButton, QWidget  # 引入模块
from PySide2.QtWidgets import QMessageBox
from PySide2.QtWidgets import QGroupBox, QVBoxLayout, QHBoxLayout  # 布局容器
from PySide2.QtCore import Slot  # 插槽模块
from PortSearch import PortSearch
import PortText
import threading
import pyperclip
import time
import sys


class PortSearchGUI(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.resize(600, 480)    # 主窗体尺寸
        self.setWindowTitle('端口嗅探器 v1.0')  # 窗体名称

        self.ip_line_edit = QLineEdit()  # 修改父类
        self.ip_line_edit.setPlaceholderText('输入ip或者网址')
        self.ip_line_edit.setMinimumSize(180, 22)

        self.thread_label = QLabel('并发数:')
        self.thread_line_edit = QLineEdit()  # 修改父类
        self.thread_line_edit.setText('300')
        self.thread_line_edit.setMinimumSize(40, 22)

        self.port_label = QLabel('端口范围:')
        self.port_line_edit1 = QLineEdit()  # 修改父类
        self.port_line_edit1.setText('0')
        self.port_label2 = QLabel('~')
        self.port_line_edit2 = QLineEdit()  # 修改父类
        self.port_line_edit2.setText('65535')

        self.report_box_edit = QPlainTextEdit()  # 修改父类
        self.report_box_edit.setReadOnly(True)

        self.start_btn = QPushButton()  # 修改父类
        self.start_btn.setText('启动')
        self.start_btn.clicked.connect(self.collect_data)  # 建立连接

        self.copy_all_btn = QPushButton()  # 修改父类
        self.copy_all_btn.setText('复制全文')
        self.copy_all_btn.clicked.connect(self.copy_all)  # 建立连接

        self.copy_ori_btn = QPushButton()  # 修改父类
        self.copy_ori_btn.setText('复制原文')
        self.copy_ori_btn.clicked.connect(self.copy)  # 建立连接

        self.clear_btn = QPushButton()  # 修改父类
        self.clear_btn.setText('清空')
        self.clear_btn.clicked.connect(self.clear)  # 建立连接

        self.first_group_box = QGroupBox()  # 第一个分组框组控件
        self.first_group_box.setTitle('参数设置')
        self.second_group_box = QGroupBox()  # 第二个分组框组控件
        self.second_group_box.setTitle('端口开放情况')

        self.first_h_layout = QHBoxLayout()  # 第一个横向布局容器,属于第一个分组框控件
        self.second_h_layout = QHBoxLayout()  # 第二个横向布局容器,属于第一个分组框控件
        self.third_h_layout = QHBoxLayout()  # 第三个横向布局容器,属于第一个分组框控件

        self.first_v_layout = QVBoxLayout()  # 第一个纵向布局容器,属于第二个横向布局容器
        self.second_v_layout = QVBoxLayout()  # 第二个纵向布局容器,属于第二个横向布局容器

        self.first_h_layout.addWidget(self.ip_line_edit)
        self.first_h_layout.addWidget(self.thread_label)
        self.first_h_layout.addWidget(self.thread_line_edit)
        self.first_h_layout.addWidget(self.port_label)
        self.first_h_layout.addWidget(self.port_line_edit1)
        self.first_h_layout.addWidget(self.port_label2)
        self.first_h_layout.addWidget(self.port_line_edit2)
        self.first_h_layout.addWidget(self.start_btn)
        self.first_group_box.setLayout(self.first_h_layout)

        self.first_v_layout.addWidget(self.report_box_edit)

        self.second_v_layout.addWidget(self.copy_all_btn)
        self.second_v_layout.addWidget(self.copy_ori_btn)
        self.second_v_layout.addWidget(self.clear_btn)

        self.second_h_layout.addItem(self.first_v_layout)
        self.second_h_layout.addItem(self.second_v_layout)

        self.second_group_box.setLayout(self.second_h_layout)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.first_group_box)
        self.layout.addWidget(self.second_group_box)
        self.setLayout(self.layout)

        self.MESSAGE = (
            'ip或者网址不得为空',
            '并发数不得小于1',
            '开始端口号不得小于0',
            '结束端口号需要大于开始端口号',
            '原文复制成功',
            '全文复制成功'
        )

        self.G_LIST = ['', '']

        self.ip = ''
        self.thread_line = 0
        self.port_start = 0
        self.port_end = 0

    def show_tip(self, message):  # 遇到问题,则丢到这里,抛到界面上
        tip = QMessageBox(self)
        tip.setWindowTitle('提示')
        tip.setText(message)
        tip.show()

        # 函数B 负责调用逻辑
    def logic(self):
        search = PortSearch(ip=self.ip, thread_line=self.thread_line, port_start=self.port_start, port_end=self.port_end)
        result = search.run()
        string = ''
        string1 = ''
        str_len = len(result)
        self.report_box_edit.setPlainText('')
        if str_len > 0:  # 处理返回数据,输出到编辑框内
            for ele in result:
                string = string + '端口:' + str(ele[1]) + '  ,状态:开启,  输出信息:' + str(ele[3]) + "\n"
                time.sleep(1)
                if ele[3] == b'':  # 如果没有端口说明,则输出参考端口服务说明
                    string1 = string1 + '端口:' + str(ele[1]) + ',状态:开启,输出信息:无' + ',参考端口服务说明:' + \
                              PortText.port_text(ele[1]) + "\n"
                else:
                    string1 = string1 + '端口:' + str(ele[1]) + ',状态:开启,输出信息:' + str(ele[3]) + "\n"
        else:
            string1 = '所有端口均未开启'
        self.G_LIST[0] = string  # 保存原文结果
        self.G_LIST[1] = string1  # 保存全文结果
        self.report_box_edit.setPlainText(string1)
        self.start_btn.setEnabled(True)
        self.setWindowTitle('端口嗅探器 v1.0')

    @Slot()
    def collect_data(self):
        self.ip = self.ip_line_edit.text()
        self.thread_line = int(self.thread_line_edit.text())
        self.port_start = int(self.port_line_edit1.text())
        self.port_end = int(self.port_line_edit2.text())
        if not self.ip:
            self.show_tip(self.MESSAGE[0])
            return
        if self.thread_line < 1:
            self.show_tip(self.MESSAGE[1])
            return
        if self.port_start < 0:
            self.show_tip(self.MESSAGE[2])
            return
        if self.port_end <= self.port_start:
            self.show_tip(self.MESSAGE[3])
            return
        thread = threading.Thread(target=self.logic)
        thread.start()  # 异步调用,避免工具卡死
        self.start_btn.setEnabled(False)  # 限制按钮,避免重复调用
        self.setWindowTitle('端口嗅探器 v1.0  ----  执行中')

    @Slot()
    def copy(self):
        pyperclip.copy(self.G_LIST[0])
        self.show_tip(self.MESSAGE[4])

    @Slot()
    def copy_all(self):
        pyperclip.copy(self.G_LIST[1])
        self.show_tip(self.MESSAGE[5])

    @Slot()
    def clear(self):
        self.report_box_edit.setPlainText('')


app = QApplication(sys.argv)     # 创建app

window = PortSearchGUI()    # 创建主窗体
window.show()    # 显示窗体

app.exec_()    # 启动app
sys.exit()

结语

这个系列就写到这里了。

ps: 20210220 今天在其他同事的电脑上试了下,报 计算机中丢失 api-ms-win-core-path-l1-1-0.dll 的报错,查了下原因,需要在该电脑上安装 Visual C++ Redistributable for Visual Studio 2015。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值