沙箱分析报告:https://s.threatbook.com/report/ ... 03_enx64_office2016
介意的同学,建议自己保存代码,部署依赖包,自行打包,使用pyinstaller打包即可
打包命令如下:(需提前安装下文依赖包,并将三个文件,按照指定文件名保存在一个目录下):
[Shell] 纯文本查看 复制代码pyinstaller -F -w --hidden-import=PyQt6 --hidden-import=qrcode --hidden-import=clipboard --hidden-import=psutil --hidden-import=http.server --hidden-import=socketserver --hidden-import=socket --hidden-import=ipaddress --hidden-import=requests --hidden-import=PIL --hidden-import=json --hidden-import=time --add-data "Ui_mian.py;." --add-data "server.py;." mian.py
众所周知,python可以启动一个临时http服务器传输文件,本工具就使用了这个原理,制作了UI,进行文件传输。使用方法为:
1.启动程序,默认监听80端口,传输文件目录默认在桌面,在脚本所在目录会生成config.ini文件,内部记录了桌面路径。如果想改成别的路径,可以手动修改后重启程序。
2.电脑与手机在同一局域网下。
3.选择自己电脑的IP,二维码会对应改变,同时将连接复制到电脑剪切板
4.可以将剪切板连接用微信发到手机打卡,也可以手机扫描二维码打开网站。
6.点击下载即可。
依赖版本:
[Shell] 纯文本查看 复制代码pyqt6==6.2.3
qrcode==7.3.1
Pillow==9.5.0
clipboard
psutil==5.9.7
requests
本脚本由两个源码组成,主程序为main.py,主要负责运行UI,处理各种信号与槽函数。
main.py
[Python] 纯文本查看 复制代码# -*- coding: utf-8 -*-
"""
Module implementing MainWindow.
"""
from PyQt6.QtCore import pyqtSlot
from PyQt6.QtWidgets import QMainWindow
from PyQt6 import QtWidgets
from PyQt6.QtCore import pyqtSlot
from PyQt6.QtWidgets import QMainWindow
import sys,os
from sever import Server
from PyQt6.QtCore import Qt
from Ui_mian import Ui_MainWindow
import qrcode,clipboard
from io import BytesIO
from PIL.ImageQt import ImageQt
from PyQt6.QtGui import QPixmap
from PyQt6.QtWidgets import QMessageBox
class MainWindow(QMainWindow, Ui_MainWindow):
"""
Class documentation goes here.
"""
def __init__(self, parent=None):
"""
Constructor
@Param parent reference to the parent widget (defaults to None)
@type QWidget (optional)
"""
super().__init__(parent)
self.setupUi(self)
self.redirect_output()
self.server=Server()
self.comboBox.addItems(self.server.all_ip)
if not os.path.exists(self.server.server_way):
# 目录不存在,弹出错误提示
self.show_error_message(f"目录不存在:\n{self.server.server_way}")
def redirect_output(self,log_file="http.log"):
# 打开日志文件并将标准输出和标准错误重定向
sys.stdout = open(log_file, "a", encoding="utf-8") # 标准输出重定向到日志文件
sys.stderr = open(log_file, "a", encoding="utf-8") # 标准错误重定向到日志文件
def show_error_message(self, message):
error_box = QMessageBox(self)
error_box.setIcon(QMessageBox.Icon.Critical)
error_box.setWindowTitle("错误")
error_box.setText(message)
error_box.exec()
@pyqtSlot(int)
def on_comboBox_currentIndexChanged(self, index):
"""
Slot documentation goes here.
@param index DESCRIPTION
@type int
"""
# TODO: not implemented yet
now_data=self.server.all_ip_dict[index]
url=self.server.get_url(now_data["ip"],now_data["ipv4"])
# 生成二维码
qr = qrcode.QRCode()
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill="black", back_color="white")
# 转换为 PyQt 可显示的格式
qt_image = ImageQt(img)
pixmap = QPixmap.fromImage(qt_image)
self.label.setPixmap(pixmap)
self.label.setWindowTitle("HTTP Server QR Code")
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.label.resize(pixmap.width(), pixmap.height())
self.label.show()
self.url_label.setText(f'[url=]{url}[/url]')
self.url_label.setOpenExternalLinks(True) # 允许点击打开外部链接
self.url_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextBrowserInteraction)
clipboard.copy(url)
def closeEvent(self, event):
# 在窗口关闭时直接终止线程
print("识别到用户关闭窗口,开始关闭监听线程")
self.server.close_th()
event.accept() # 接受关闭事件,关闭窗口
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec())
另一个为sever.py,主要为实现功能
[Python] 纯文本查看 复制代码import http.server
import socketserver
import socket
import os
import threading
import qrcode
import clipboard
import psutil
import ipaddress
import threading
import json,requests,time
class Server(object):
def __init__(self):
self.ipv4_list=[]
self.ipv6_list=[]
self.ipv4_server_thread=None
self.ipv6_server_thread=None
self.port=80
self.server_way=""
self.all_ip=[]
self.all_ip_dict={}
self.stop_event = threading.Event()
self.load_config()
self.get_non_loopback_ip()
self.run_http_server()
num=-1
for name,ip in self.ipv4_list:
num=num+1
self.all_ip.append(f"{name}-{ip}")
self.all_ip_dict[num]={
"name":name,
"ip":ip,
"ipv4":True
}
for name,ip in self.ipv6_list:
num=num+1
self.all_ip.append(f"{name}-{ip}")
self.all_ip_dict[num]={
"name":name,
"ip":ip,
"ipv4":False
}
def get_non_loopback_ip(self,):
network = ipaddress.IPv4Network('169.254.0.0/16')
interfaces = psutil.net_if_addrs()
for name, info in interfaces.items():
for addr in info:
if addr.family == socket.AF_INET: # IPv4
# 检查是否是有效的IP地址(排除广播地址等)
ip = ipaddress.ip_address(addr.address)
if not ip.is_loopback and not ip.is_multicast:
if ip not in network:
self.ipv4_list.append([name,addr.address])
elif addr.family == socket.AF_INET6: # IPv6
ip = ipaddress.ip_address(addr.address)
if not ip.is_loopback and not ip.is_multicast:
if ip not in network:
self.ipv6_list.append([name,addr.address])
# 启动 HTTP 服务
def start_http_server_v6(self, ip='::', port=80):
if port != self.port:
self.port = port
os.chdir(self.server_way)
handler = http.server.SimpleHTTPRequestHandler
class DualStackTCPServer(socketserver.TCPServer):
allow_reuse_address = True
def __init__(self, server_address, RequestHandlerClass):
self.address_family = socket.AF_INET6
super().__init__(server_address, RequestHandlerClass)
with DualStackTCPServer((ip, port), handler) as httpd:
print(f"HTTP服务已经运行,地址为:http://[{ip}]:{port}/")
while not self.stop_event.is_set(): # 判断是否需要停止
httpd.handle_request() # 处理一次请求
# 启动 HTTP 服务
def start_http_server_v4(self, ip="0.0.0.0", port=80):
if port != self.port:
self.port = port
os.chdir(self.server_way)
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer((ip, port), handler) as httpd:
print(f"HTTP服务已经运行,地址为:http://{ip}:{port}/")
while not self.stop_event.is_set(): # 判断是否需要停止
httpd.handle_request() # 处理一次请求
def run_http_server(self, ipv4="0.0.0.0", ipv6="::", port=80):
if port != self.port:
self.port = port
self.ipv4_server_thread = threading.Thread(target=self.start_http_server_v4, args=(ipv4, port))
self.ipv6_server_thread = threading.Thread(target=self.start_http_server_v6, args=(ipv6, port))
self.ipv4_server_thread.start()
self.ipv6_server_thread.start()
# 生成二维码并复制到剪贴板
def generate_qr_and_copy(self,url):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=1,
border=1,
)
qr.add_data(url)
qr.make(fit=True)
qr_ascii = qr.print_ascii(invert=True, tty=True)
print(qr_ascii)
clipboard.copy(url)
print(f"服务地址: {url} 已经复制到您的剪切板中。")
# 获取当前用户桌面路径
def get_desktop(self):
self.server_way= os.path.join(os.path.expanduser("~"), "Desktop")
# 创建或读取配置文件
def load_config(self):
config_file = "config.ini"
self.get_desktop()
if not os.path.exists(config_file):
config = {"server_dir": self.server_way}
with open(config_file, "w",encoding="utf-8") as f:
json.dump(config, f, indent=4)
else:
with open(config_file, "r",encoding="utf-8") as f:
config = json.load(f)
self.server_way=config.get("server_dir")
def get_url(self,ip_addr,ipv4=True):
"""
生成URL
"""
if ipv4:
return f"http://{ip_addr.strip()}:{self.port}"
else:
return f"http://[{ip_addr.strip()}]:{self.port}"
def close_th(self):
"""
"""
self.stop_event.set() # 设置停止事件,通知线程退出
time.sleep(0.3)
try:
requests.get(f"http://[::1]:{self.port}",timeout=1)
except Exception as err:
pass
try:
requests.get(f"http://127.0.0.1:{self.port}",timeout=1)
except Exception as err:
pass
self.ipv4_server_thread.join() # 等待线程结束
self.ipv6_server_thread.join() # 等待线程结束
Ui_mian.py文件
[Python] 纯文本查看 复制代码# Form implementation generated from reading ui file 'F:\同步文件\BaiduNetdiskWorkspace\文件快传\开发\快捷http服务\gui\mian.ui'
#
# Created by: PyQt6 UI code generator 6.2.3
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(350, 331)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(self.centralWidget)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.comboBox = QtWidgets.QComboBox(self.centralWidget)
self.comboBox.setObjectName("comboBox")
self.horizontalLayout.addWidget(self.comboBox)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.url_label = QtWidgets.QLabel(self.centralWidget)
self.url_label.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextBrowserInteraction)
self.url_label.setObjectName("url_label")
self.verticalLayout_2.addWidget(self.url_label)
self.verticalLayout.addLayout(self.verticalLayout_2)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralWidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "二维码"))
self.url_label.setText(_translate("MainWindow", "url"))
MainWindow.setWindowTitle("HTTP服务")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec())
打包好exe下载地址:
https://wwnd.lanzouw.com/idy9z2ltp7id
密码:ahws