使用pyqt5来开发图形化工具

admin 2024年9月27日13:42:22评论26 views字数 9493阅读31分38秒阅读模式
本文由掌控安全学院 -

1198950xxx

投稿

 

前言

这里介绍一些PyQt的基本使用,以及一些常用的组件,以及如何使用Qt Designer设计图形化界面。

一篇文章教会小白写图形化界面工具。

1.PyQt介绍与安装

PyQt的开发者是英国的“Riverbank Computing”公司。它提供了GPL(简单的说,以GPL协议发布到网上的素材,你可以使用,也可以更改,但是经过你更改然后再次发布的素材必须也遵守GPL协议,主要要求是必须开源,而且不能删减原作者的声明信息等)与商业协议两种授权方式,因此它可以免费地用于自由软件的开发。
PyQt是Python语言的GUI(Graphical User Interface,简称 GUI,又称图形用户接口)编程解决方案之一
可以用来代替Python内置的Tkinter。其它替代者还有PyGTK、wxPython等,与Qt一样,PyQt是一个自由软件

安装PyQt5

  1. pip install pyqt5 -i https://mirrors.aliyun.com/pypi/simple/

2.PyQt5使用示例

  1. import sys
  2. fromPyQt5.QtWidgetsimportQApplication,QWidget
  3. if __name__ =='__main__':
  4. app =QApplication(sys.argv)
  5. w =QWidget()
  6. # 设置窗口标题
  7. w.setWindowTitle("第一个PyQt")
  8. # 展示窗口
  9. w.show()
  10. # 程序进行循环等待状态
  11. app.exec()

使用pyqt5来开发图形化工具

3.PyQt5组件以及布局

这里的组件和布局比较简单,下面链接介绍比较全面

https://doc.itprojects.cn/0001.zhishi/python.0008.pyqt5rumen/index.html#/README

4.Qt Designer介绍

纯靠代码来编写界面,效率属实是有点底,介绍一个辅助设计图形化的软件 QT Designer。

可以直接拖动组件设计ui界面。

使用pyqt5来开发图形化工具

保存后的文件为ui文件

使用pyqt5来开发图形化工具

若要加载ui文件,则需要导入 uic 模块 , 它位于PyQt5 中

  1. import sys
  2. fromPyQt5.QtWidgetsimportQApplication
  3. fromPyQt5import uic
  4. if __name__ =='__main__':
  5. app =QApplication(sys.argv)
  6. ui = uic.loadUi("./untitled.ui")
  7. # 展示窗口
  8. ui.show()
  9. app.exec()

不过使用.ui去调用就无法和py文件一起打包成exe,这里可以使用pyuic5将ui文件转换成python文件

在cmd中执行

pyuic5 -o .py .ui

pyuic5 -o tishi_ui.py tishi.ui

使用pyqt5来开发图形化工具

调用py文件

  1. fromPyQt5.QtCoreimportQt
  2. from.tishi_ui importUi_Form
  3. fromPyQt5.QtWidgetsimportQWidget
  4. classTiShi(QWidget,Ui_Form):
  5. def __init__(self):
  6. super(TiShi, self).__init__()
  7. self.setupUi(self)# 使用 sjui.Ui_Form 类中的方法初始化 UI
  8. self.setWindowFlags(Qt.WindowCloseButtonHint)

5.Pyqt5项目 Xray-Gui

这项目是通过pyqt5实现的一个Xray的图形界面,方便用户使用。

项目地址: https://github.com/buluorifu/Xray-Gui

构思

使用pyqt5来开发图形化工具

文件夹结构

使用pyqt5来开发图形化工具

效果图

使用pyqt5来开发图形化工具

使用Qt Designer设计界面

1. 打开Qt Designer,并设计好ui界面

使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具

保存好会生成.ui文件

使用pyqt5来开发图形化工具

2. 将ui文件转化为py文件

  1. pyuic5 -o ***.py ***.ui

使用pyqt5来开发图形化工具

3.调用py文件打开界面

  1. import sys
  2. fromPyQt5.QtGuiimportQIcon
  3. from configuration.box1 import BOX1
  4. from configuration.box2 import BOX2
  5. from configuration.box3 import BOX3
  6. from configuration.homepage importUi_Form
  7. fromPyQt5.QtWidgetsimportQWidget,QApplication,QStackedLayout
  8. classMyWindow(QWidget,Ui_Form):
  9. def __init__(self):
  10. super(MyWindow, self).__init__()
  11. self.setupUi(self)# 使用 sjui.Ui_Form 类中的方法初始化 UI
  12. self.init_ui()
  13. self.sub_window =None# 存储子窗口对象的属性
  14. def init_ui(self):
  15. self.qsl =QStackedLayout(self.groupBox_2)
  16. self.box1 = BOX1()
  17. self.box2 = BOX2()
  18. self.box3 = BOX3()
  19. self.qsl.addWidget(self.box1)
  20. self.qsl.addWidget(self.box2)
  21. self.qsl.addWidget(self.box3)
  22. # 给按钮添加事件(即点击后要调用的函数)
  23. self.pushButton.clicked.connect(self.btn_press1_clicked)
  24. self.pushButton_2.clicked.connect(self.btn_press2_clicked)
  25. self.pushButton_3.clicked.connect(self.btn_press3_clicked)
  26. # 设置按钮1的初始样式
  27. self.pushButton.setStyleSheet("background-color: #CAE1FF;")
  28. def btn_press1_clicked(self):
  29. self.qsl.setCurrentIndex(0)
  30. self.pushButton.setStyleSheet("background-color: #CAE1FF;")
  31. self.pushButton_2.setStyleSheet("")# 恢复按钮2的默认样式
  32. self.pushButton_3.setStyleSheet("")# 恢复按钮3的默认样式
  33. def btn_press2_clicked(self):
  34. self.qsl.setCurrentIndex(1)
  35. self.pushButton.setStyleSheet("")# 恢复按钮1的默认样式
  36. self.pushButton_2.setStyleSheet("background-color: #CAE1FF;")
  37. self.pushButton_3.setStyleSheet("")# 恢复按钮3的默认样式
  38. def btn_press3_clicked(self):
  39. self.qsl.setCurrentIndex(2)
  40. self.pushButton.setStyleSheet("")# 恢复按钮1的默认样式
  41. self.pushButton_2.setStyleSheet("")# 恢复按钮2的默认样式
  42. self.pushButton_3.setStyleSheet("background-color: #CAE1FF;")
  43. def closeEvent(self, event):
  44. # 关闭其他窗口的代码
  45. for widget inQApplication.topLevelWidgets():
  46. if isinstance(widget,QWidget)and widget != self:
  47. widget.close()
  48. event.accept()
  49. if __name__ =='__main__':
  50. app =QApplication(sys.argv)
  51. w =MyWindow()
  52. icon =QIcon('./img/扫描.png')#添加图标
  53. w.setWindowIcon(icon)
  54. w.show()
  55. sys.exit(app.exec_())

我们在box1、box2、box3各把ui里面的代码导入即可,以box1举例

  1. fromPyQt5.QtWidgetsimportQWidget
  2. from.box1_ui importUi_Form
  3. class BOX1(QWidget,Ui_Form):
  4. def __init__(self):
  5. super(QWidget, self).__init__()
  6. self.setupUi(self)# 使用 sjui.Ui_Form 类中的方法初始化 UI
  7. self.init_ui()

4.功能调用介绍

self.init_ui()创建对象时自动调用

init_ui()里面主要为按钮连接的方法

使用pyqt5来开发图形化工具

读取文件功能,获取文件路径

  1. fileName, fileType =QtWidgets.QFileDialog.getOpenFileName(None,"选取文件", os.getcwd(),"All Files(*.exe);")
  2. self.lineEdit.setText(fileName)

使用pyqt5来开发图形化工具

创建子进程,这里不创建子进程会把整个程序阻塞

  1. # 创建子进程
  2. def process_creation(self):
  3. self.process =QProcess()
  4. self.process.setProcessChannelMode(QProcess.MergedChannels)
  5. self.process.readyReadStandardOutput.connect(self.handle_output)
  6. self.process.finished.connect(self.handle_finished)
  7. self.process.start(self.lineEdit.text())
  8. # 命令输出
  9. def handle_output(self):
  10. try:
  11. data = self.process.readAll().data().decode('utf-8').rstrip()
  12. # 将命令行输出至文本框
  13. self.textEdit.append(data)
  14. except:
  15. data = self.process.readAll().data().decode('latin-1').rstrip()
  16. # 将命令行输出至文本框
  17. self.textEdit.append(data)

这里可以对输出的文本进行优化一下颜色,不然是全黑色字体和xray原本输出的颜色不符

通过正则匹配,对不同字段进行不同颜色的输出

  1. # 命令输出
  2. def handle_output(self):
  3. try:
  4. data = self.process.readAll().data().decode('utf-8').strip()
  5. lines = data.split('n')
  6. for line in lines:
  7. if"[INFO]"in line:
  8. line = line.replace("[INFO]", f'<span style="color: blue;">[INFO]</span>')
  9. elif"[Vuln: dirscan]"in line:
  10. line = line.replace("[Vuln: dirscan]", f'<span style="color: red;">[Vuln: dirscan]</span>')
  11. elif line.startswith('t'):
  12. line = f'<span style="color: purple;">&nbsp;&nbsp;&nbsp;&nbsp;{line}</span>'
  13. elif re.match(r'^[u4e00-u9fff]', line):
  14. line = f'<span style="color: red;">{line}</span>'
  15. elif"requestSent"in line:
  16. line = f'<span style="color: #FFBF00;">{line}</span>'
  17. elif"All pending"in line:
  18. line = f'<span style="color: #00FF7F;">{line}</span>'
  19. self.textEdit.append(line)
  20. except:
  21. data = self.process.readAll().data().decode('latin-1').strip()
  22. lines = data.split('n')
  23. for line in lines:
  24. if"[INFO]"in line:
  25. line = line.replace("[INFO]", f'<span style="color: blue;">[INFO]</span>')
  26. elif"[Vuln: dirscan]"in line:
  27. line = line.replace("[Vuln: dirscan]", f'<span style="color: red;">[Vuln: dirscan]</span>')
  28. elif line.startswith('t'):
  29. line = f'<span style="color: purple;">&nbsp;&nbsp;&nbsp;&nbsp;{line}</span>'
  30. elif re.match(r'^[u4e00-u9fff]', line):
  31. line = f'<span style="color: red;">{line}</span>'
  32. elif"requestSent"in line:
  33. line = f'<span style="color: #FFBF00;">{line}</span>'
  34. elif"All pending"in line:
  35. line = f'<span style="color: #00FF7F;">{line}</span>'
  36. self.textEdit.append(line)

使用pyqt5来开发图形化工具

修改配置文件主要在于修改config.yaml文件,这里用import ruamel.yaml这个库。

  1. # 确认修改基础配置
  2. def basics_save(self):
  3. if os.path.exists('file_address.yaml'):
  4. with open('config.yaml','r', encoding='utf-8')as file:
  5. yaml = ruamel.yaml.YAML()
  6. config = yaml.load(file)
  7. config['parallel']= int(self.spinBox.text())
  8. config['http']['dial_timeout']= int(self.spinBox_2.text())
  9. config['http']['max_redirect']= int(self.spinBox_3.text())
  10. config['http']['max_qps']= int(self.spinBox_4.text())
  11. with open('config.yaml','w', encoding='utf-8')as file:
  12. yaml.dump(config, file)
  13. self.open_tishiwindow(None,None)
  14. else:
  15. text ='未配置xray文件'
  16. img ='./img/失败.png'
  17. self.open_tishiwindow(text, img)

然后通过子进程去输出命令行,并调用handle_output方法输出到文本

这里通过获取界面的选项来拼接命令行

然后config界面和rad界面同理

  1. def initiative_scan(self):
  2. if os.path.exists('file_address.yaml'):
  3. self.textEdit.clear()
  4. self.process_kill()
  5. ifnot hasattr(self,'is_first_click'):
  6. if self.lineEdit_2.text()==""or self.lineEdit_2.text()=="默认则随机命名":
  7. self.dict['name']= str(int(time.time()))
  8. else:
  9. self.dict['name']= self.lineEdit_2.text()
  10. # 第一次按下按钮
  11. self.is_first_click =True
  12. self.process_kill()
  13. with open('file_address.yaml','r', encoding='utf-8')as file:
  14. yaml = ruamel.yaml.YAML()
  15. config = yaml.load(file)
  16. self.args = config['xray_address']
  17. if self.radioButton_5.isChecked():
  18. self.args = self.args +' --log-level debug'
  19. if self.radioButton_6.isChecked():
  20. self.args = self.args +' --log-level info'
  21. if self.radioButton_7.isChecked():
  22. self.args = self.args +' --log-level warn'
  23. if self.radioButton_8.isChecked():
  24. self.args = self.args +' --log-level error'
  25. if self.radioButton_9.isChecked():
  26. self.args = self.args +' --log-level fatal'
  27. self.args = self.args +' webscan'
  28. if self.radioButton_11.isChecked():
  29. self.args = self.args +' --level medium'
  30. if self.radioButton_12.isChecked():
  31. self.args = self.args +' --level high'
  32. if self.radioButton_13.isChecked():
  33. self.args = self.args +' --level critical'
  34. if self.dict['url']:
  35. self.args = self.args +' --url '+ self.dict['url']
  36. if self.dict['request']:
  37. self.args = self.args +' --raw-request '+ self.dict['request']
  38. if self.dict['url_list']:
  39. self.args = self.args +' --url-file '+ self.dict['url_list']
  40. if self.radioButton.isChecked():
  41. self.args = self.args +' --html-output '+ self.dict['name']+'.html'
  42. self.dict['name_all']= os.path.dirname(config['xray_address'])+'/'+ self.dict['name']+'.html'
  43. if self.radioButton_2.isChecked():
  44. self.args = self.args +' --json-output '+ self.dict['name']+'.txt'
  45. self.dict['name_all']= os.path.dirname(config['xray_address'])+'/'+ self.dict['name']+'.txt'
  46. self.pushButton_3.setText("关闭主动扫描")
  47. self.process_creation()
  48. self.process.start(self.args)
  49. else:
  50. # 第二次按下按钮
  51. del self.is_first_click # 删除标记
  52. self.pushButton_3.setText("开启主动扫描")
  53. self.textEdit.clear()
  54. self.process_kill()
  55. else:
  56. text ='未配置xray文件'
  57. img ='./img/失败.png'
  58. self.open_tishiwindow(text, img)

被动代理效果,红色即是扫出的漏洞

使用pyqt5来开发图形化工具

打开输出文件

  1. # 查看扫描结果
  2. def file_look(self):
  3. try:
  4. if self.dict['name_all']:
  5. os.startfile(self.dict['name_all'])
  6. else:
  7. text ='没有输出文件'
  8. img ='./img/失败.png'
  9. self.open_tishiwindow(text, img)
  10. except:
  11. text ='没有输出文件'
  12. img ='./img/失败.png'
  13. self.open_tishiwindow(text, img)

使用pyqt5来开发图形化工具

加解密界面主要通过self.textEdit.textChanged.connect(self.encrypt_txt)去对输入的文本进行处理

这里可以创建一个线程,去执行加密操作,避免阻塞界面

  1. def start_encrypt_txt(self):
  2. t = threading.Thread(target=self.encrypt_txt)
  3. t.daemon =True
  4. t.start()

md5的界面主要通过字典匹配,如果匹配不到,就返回无法解密

  1. found_match =False# 标记是否找到匹配的解密结果
  2. with open('./dict/top1w-md5.txt','r', encoding='utf-8')as fp:
  3. for line in fp:
  4. if str_txt == line.strip():
  5. # 如果找到了匹配的MD5哈希值,我们可以从原始文件中获取相应的单词
  6. with open("./dict/top1w.txt",'r', encoding='utf-8')as wp:
  7. for word_line in wp:
  8. words = word_line.split()
  9. for word in words:
  10. if hashlib.md5(word.encode('utf-8')).hexdigest()== str_txt:
  11. found_match =True
  12. self.textEdit_6.setText(word)
  13. break
  14. if found_match:
  15. break
  16. ifnot found_match:
  17. self.textEdit_6.setText('无法解密')

5.把python打包成exe文件

  1. 安装pyinstaller

首先我们要先安装Pyinstaller,直接在cmd使用pip命令

  1. pip install pyinstaller

2、执行命令,从程序开始的地方打包,生成exe文件

末尾出现Building EXE from EXE-00.toc completed successfully.代表打包成功

打包后在当前路径dist目录下面生成exe文件

  1. Pyinstaller-F -w -i 扫描.ico ui.py

使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具
使用pyqt5来开发图形化工具

一个图形化工具就写完了

结尾

感谢大家的观看,求个Star!https://github.com/buluorifu/Xray-Gui

原文始发于微信公众号(掌控安全EDU):使用pyqt5来开发图形化工具

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月27日13:42:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   使用pyqt5来开发图形化工具https://cn-sec.com/archives/3214319.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息