打包时需要有upx.exe,我放附件里。

image.png (76.97 KB, 下载次数: 0)
下载附件
2025-4-22 15:47 上传
upx.zip
(575.04 KB, 下载次数: 348)
2025-4-22 15:46 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB
[Python] 纯文本查看 复制代码import os
import shutil
import subprocess
import sys
import time
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QLineEdit, QPushButton, QComboBox, QCheckBox, QMessageBox,
QProgressBar, QFileDialog, QFrame)
from PyQt5.QtGui import QFont, QIcon, QPalette, QColor
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSize, QMimeData
def resource_path(relative_path):
"""
获取资源文件的绝对路径,无论是在开发环境还是打包后的环境中。
"""
try:
# PyInstaller 创建的临时文件夹路径
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
class WorkerThread(QThread):
progress_signal = pyqtSignal(int)
finished_signal = pyqtSignal()
error_signal = pyqtSignal(str)
def __init__(self, command):
super().__init__()
self.command = command
def run(self):
try:
# 隐藏子进程窗口
startupinfo = None
if os.name == 'nt':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
process = subprocess.Popen(
self.command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
startupinfo=startupinfo
)
start_time = time.time()
total_time_estimate = 10 # 估计的总时间,单位为秒
while True:
if process.poll() is not None:
break
elapsed_time = time.time() - start_time
progress = int((elapsed_time / total_time_estimate) * 100)
if progress > 100:
progress = 100
self.progress_signal.emit(progress)
time.sleep(0.1)
self.finished_signal.emit()
except Exception as e:
self.error_signal.emit(str(e))
class UPXTool(QWidget):
def __init__(self):
super().__init__()
self.setup_style()
self.initUI()
# 动态获取upx.exe路径
self.upx_path = self.get_upx_path()
self.file_path = ""
self.compression_level = "-9"
self.create_backup = False
self.worker = None
# 启用拖拽功能
self.setAcceptDrops(True)
def get_upx_path(self):
"""动态获取upx.exe路径,处理打包后和开发环境两种情况"""
try:
# 如果是打包后的环境
if getattr(sys, 'frozen', False):
# 获取打包后的可执行文件所在目录
base_path = os.path.dirname(sys.executable)
upx_path = os.path.join(base_path, 'upx.exe')
else:
# 开发环境,使用脚本所在目录
base_path = os.path.dirname(os.path.abspath(__file__))
upx_path = os.path.join(base_path, 'upx.exe')
# 检查文件是否存在
if not os.path.exists(upx_path):
# 尝试在系统PATH中查找
which_upx = shutil.which('upx')
if which_upx:
return which_upx
raise FileNotFoundError("无法找到upx.exe")
return upx_path
except Exception as e:
QMessageBox.critical(self, "错误", f"初始化失败: {str(e)}")
return "upx.exe" # 最后尝试直接使用系统PATH中的upx
def setup_style(self):
# 设置应用程序的全局样式
self.setStyleSheet("""
QWidget {
background-color: #f5f5f5;
color: #333333;
}
QLineEdit {
border: 2px solid #cccccc;
border-radius: 5px;
padding: 10px;
font-size: 14px;
background-color: white;
min-height: 20px;
}
QLineEdit:focus {
border: 2px solid #4CAF50;
}
QPushButton {
border: none;
border-radius: 5px;
padding: 12px 24px;
font-size: 14px;
font-weight: bold;
color: white;
min-width: 120px;
min-height: 30px;
}
QPushButton:hover {
opacity: 0.9;
}
QPushButton:pressed {
padding: 12px 24px;
}
QComboBox {
border: 2px solid #cccccc;
border-radius: 5px;
padding: 10px;
font-size: 14px;
background-color: white;
min-height: 20px;
}
QComboBox:focus {
border: 2px solid #4CAF50;
}
QCheckBox {
font-size: 14px;
spacing: 8px;
min-height: 20px;
}
QCheckBox::indicator {
width: 20px;
height: 20px;
}
QProgressBar {
border: 2px solid #cccccc;
border-radius: 5px;
text-align: center;
font-size: 14px;
height: 30px;
}
QProgressBar::chunk {
background-color: #4CAF50;
border-radius: 3px;
}
QLabel {
font-size: 14px;
}
.TitleLabel {
font-size: 28px;
font-weight: bold;
color: #333333;
padding: 10px 0;
}
.SectionFrame {
border-radius: 8px;
background-color: white;
border: 1px solid #e0e0e0;
padding: 5px;
}
/* 拖拽文件时的样式 */
QLineEdit[fileDrag="true"] {
border: 2px dashed #4CAF50;
background-color: #f0fff0;
}
""")
def initUI(self):
self.setWindowTitle("UPX5.0 - 加壳/脱壳工具 By:Killerzeno")
self.setWindowIcon(QIcon(resource_path("logo.ico"))) # 使用 resource_path 处理图标路径
# 设置窗口大小并禁止最大化
self.setFixedSize(800, 600) # 增大窗口尺寸
# 主布局
main_layout = QVBoxLayout()
main_layout.setContentsMargins(30, 20, 30, 20) # 增加边距
main_layout.setSpacing(25) # 增加控件间距
# 标题 - 增大字体
title_label = QLabel("UPX5.0 - 加壳/脱壳工具")
title_label.setObjectName("TitleLabel")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("""
QLabel {
font-size: 28px;
font-weight: bold;
color: #333333;
padding: 10px 0;
}
""")
main_layout.addWidget(title_label)
# 文件选择部分
file_frame = QFrame()
file_frame.setObjectName("SectionFrame")
file_layout = QVBoxLayout(file_frame)
file_layout.setContentsMargins(20, 20, 20, 20) # 增加内边距
file_layout.setSpacing(15)
file_label = QLabel("选择要处理的文件 (或直接拖拽文件到此处):")
file_label.setStyleSheet("font-weight: bold; font-size: 15px;")
file_input_layout = QHBoxLayout()
self.file_entry = QLineEdit()
self.file_entry.setPlaceholderText("点击浏览选择文件或拖拽文件到这里...")
self.file_entry.setProperty("fileDrag", "false") # 初始化拖拽状态属性
file_button = QPushButton("浏览")
file_button.setStyleSheet("""
background-color: #2196F3;
font-size: 14px;
min-width: 100px;
""")
file_button.setIcon(QIcon.fromTheme("document-open"))
file_button.setIconSize(QSize(18, 18)) # 增大图标
file_button.clicked.connect(self.browse_file)
file_input_layout.addWidget(self.file_entry, stretch=5)
file_input_layout.addWidget(file_button, stretch=1)
file_input_layout.setSpacing(15)
file_layout.addWidget(file_label)
file_layout.addLayout(file_input_layout)
main_layout.addWidget(file_frame)
# 设置部分
settings_frame = QFrame()
settings_frame.setObjectName("SectionFrame")
settings_layout = QVBoxLayout(settings_frame)
settings_layout.setContentsMargins(20, 20, 20, 20)
settings_layout.setSpacing(20)
# 压缩级别
level_layout = QHBoxLayout()
level_label = QLabel("压缩级别:")
level_label.setStyleSheet("font-weight: bold; font-size: 15px;")
self.level_combobox = QComboBox()
self.level_combobox.addItems([f"级别 {i} " for i in range(1, 10)])
self.level_combobox.setCurrentIndex(8) # 默认选择级别9
self.level_combobox.setStyleSheet("font-size: 14px; min-height: 30px;")
level_layout.addWidget(level_label)
level_layout.addWidget(self.level_combobox, stretch=1)
level_layout.addStretch()
# 备份选项
self.backup_checkbox = QCheckBox("创建备份文件 (.bak)")
self.backup_checkbox.setChecked(True)
self.backup_checkbox.setStyleSheet("font-size: 14px;")
settings_layout.addLayout(level_layout)
settings_layout.addWidget(self.backup_checkbox)
main_layout.addWidget(settings_frame)
# 操作按钮 - 增大按钮尺寸
button_layout = QHBoxLayout()
button_layout.setSpacing(30) # 增加按钮间距
self.compress_button = QPushButton("加壳")
self.compress_button.setStyleSheet("""
background-color: #4CAF50;
font-size: 16px;
min-width: 150px;
min-height: 40px;
""")
self.compress_button.setIcon(QIcon.fromTheme("document-edit"))
self.compress_button.setIconSize(QSize(18, 18))
self.compress_button.clicked.connect(self.compress)
self.decompress_button = QPushButton("脱壳")
self.decompress_button.setStyleSheet("""
background-color: #FF5722;
font-size: 16px;
min-width: 150px;
min-height: 40px;
""")
self.decompress_button.setIcon(QIcon.fromTheme("document-revert"))
self.decompress_button.setIconSize(QSize(18, 18))
self.decompress_button.clicked.connect(self.decompress)
button_layout.addStretch()
button_layout.addWidget(self.compress_button)
button_layout.addWidget(self.decompress_button)
button_layout.addStretch()
main_layout.addLayout(button_layout)
# 进度条 - 增大高度
self.progress_bar = QProgressBar()
self.progress_bar.setRange(0, 100)
self.progress_bar.setTextVisible(True)
self.progress_bar.setFormat("等待操作...")
self.progress_bar.setStyleSheet("font-size: 14px;")
main_layout.addWidget(self.progress_bar)
# 状态栏 - 增大字体
self.status_label = QLabel("就绪")
self.status_label.setAlignment(Qt.AlignRight)
self.status_label.setStyleSheet("""
color: #666666;
font-size: 13px;
padding-top: 10px;
""")
main_layout.addWidget(self.status_label)
self.setLayout(main_layout)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
self.file_entry.setProperty("fileDrag", "true")
self.file_entry.style().polish(self.file_entry) # 刷新样式
def dragLeaveEvent(self, event):
self.file_entry.setProperty("fileDrag", "false")
self.file_entry.style().polish(self.file_entry) # 刷新样式
def dropEvent(self, event):
self.file_entry.setProperty("fileDrag", "false")
self.file_entry.style().polish(self.file_entry) # 刷新样式
if event.mimeData().hasUrls():
urls = event.mimeData().urls()
if urls:
file_path = urls[0].toLocalFile()
if os.path.isfile(file_path):
self.file_path = file_path
self.file_entry.setText(file_path)
self.status_label.setText(f"已选择文件: {os.path.basename(file_path)}")
else:
QMessageBox.warning(self, "警告", "请拖拽有效的文件")
def browse_file(self):
path, _ = QFileDialog.getOpenFileName(
self,
"选择文件",
"",
"可执行文件 (*.exe);;所有文件 (*)"
)
if path:
self.file_path = path
self.file_entry.setText(path)
self.status_label.setText(f"已选择文件: {os.path.basename(path)}")
def compress(self):
file_path = self.file_path
level = f"-{self.level_combobox.currentIndex() + 1}" # 从1-9转换为-1到-9
if not self.validate_inputs():
return
self.create_backup = self.backup_checkbox.isChecked()
if self.create_backup:
if not self.create_backup_file(file_path):
return
command = [self.upx_path, level, file_path]
self.start_worker(command, "加壳")
def decompress(self):
file_path = self.file_path
if not self.validate_inputs():
return
self.create_backup = self.backup_checkbox.isChecked()
if self.create_backup:
if not self.create_backup_file(file_path):
return
command = [self.upx_path, "-d", file_path]
self.start_worker(command, "脱壳")
def validate_inputs(self):
if not os.path.exists(self.upx_path):
QMessageBox.critical(
self,
"错误",
f"未找到UPX可执行文件,请确保upx.exe与程序在同一目录下\n当前路径: {self.upx_path}"
)
return False
if not os.path.exists(self.file_path):
QMessageBox.critical(
self,
"错误",
"请先选择有效的文件路径"
)
return False
return True
def create_backup_file(self, file_path):
backup_path = file_path + ".bak"
try:
shutil.copy2(file_path, backup_path)
self.status_label.setText(f"已创建备份文件: {os.path.basename(backup_path)}")
return True
except Exception as e:
QMessageBox.critical(
self,
"备份失败",
f"无法创建备份文件: {str(e)}"
)
return False
def start_worker(self, command, operation_name):
self.worker = WorkerThread(command)
self.worker.progress_signal.connect(self.update_progress)
self.worker.finished_signal.connect(lambda: self.on_finished(operation_name))
self.worker.error_signal.connect(self.on_error)
self.compress_button.setEnabled(False)
self.decompress_button.setEnabled(False)
self.file_entry.setEnabled(False)
self.progress_bar.setFormat(f"{operation_name}中... %p%")
self.status_label.setText(f"{operation_name}文件...")
self.worker.start()
def update_progress(self, value):
self.progress_bar.setValue(value)
def on_finished(self, operation_name):
self.progress_bar.setValue(100)
self.progress_bar.setFormat("操作完成")
# 创建自定义的消息框
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setWindowTitle("成功")
msg.setText(f"{operation_name}操作已完成!")
msg.setStyleSheet("""
QMessageBox {
background-color: #f5f5f5;
font-size: 14px;
}
QMessageBox QLabel {
color: #333333;
font-size: 15px;
}
QMessageBox QPushButton {
color: #333333;
background-color: #e0e0e0;
border: 1px solid #cccccc;
padding: 8px 20px;
border-radius: 4px;
font-size: 14px;
min-width: 80px;
}
QMessageBox QPushButton:hover {
background-color: #d0d0d0;
}
""")
msg.exec_()
self.reset_ui()
self.status_label.setText(f"{operation_name}完成 - {os.path.basename(self.file_path)}")
def on_error(self, error):
self.progress_bar.setFormat("操作失败")
QMessageBox.critical(
self,
"错误",
f"操作失败: {error}"
)
self.reset_ui()
self.status_label.setText(f"错误: {error}")
def reset_ui(self):
self.compress_button.setEnabled(True)
self.decompress_button.setEnabled(True)
self.file_entry.setEnabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置应用程序字体
font = QFont()
font.setFamily("Microsoft YaHei" if sys.platform == "win32" else "Noto Sans")
font.setPointSize(10)
app.setFont(font)
# 创建并显示主窗口
ex = UPXTool()
ex.show()
sys.exit(app.exec_())