python病毒
2025-06-21 16:36:17
发布于:广东
import tkinter as tk
from tkinter import messagebox
import random
import platform
import subprocess
import os
import time
import threading
import ctypes
from ctypes import wintypes
import logging
# 配置日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class Popup:
"""弹窗类,管理弹窗生命周期"""
_all_popups = []
def __init__(self, root, window_id):
self.root = root
self.window_id = window_id
def close(self):
"""关闭弹窗并清理引用"""
if self.root and self.root.winfo_exists():
self.root.destroy()
if 0 <= self.window_id < len(Popup._all_popups):
Popup._all_popups[self.window_id] = None
Popup._all_popups = [p for p in Popup._all_popups if p is not None]
return self
class ScreenInverter:
"""屏幕反色管理器"""
_instance = None
_is_inverted = False
_platform = platform.system()
@staticmethod
def get_instance(root):
if ScreenInverter._instance is None:
ScreenInverter._instance = ScreenInverter(root)
return ScreenInverter._instance
def __init__(self, root):
self.root = root
self._original_state = None
self._overlay = None
logger.info(f"初始化屏幕反色管理器,当前平台: {self._platform}")
# Windows-specific setup
if self._platform == "Windows":
logger.info("配置Windows平台反色功能")
self._user32 = ctypes.windll.user32
class KBDINPUT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_ulong),
("wVk", ctypes.c_ushort),
("wScan", ctypes.c_ushort),
("dwFlags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", ctypes.POINTER(ctypes.c_ulong))
]
class INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = [
("ki", KBDINPUT),
]
_anonymous_ = ("_input",)
_fields_ = [
("type", ctypes.c_ulong),
("_input", _INPUT)
]
self._KBDINPUT = KBDINPUT
self._INPUT = INPUT
self._INPUT_KEYBOARD = 1
self._KEYEVENTF_KEYUP = 2
def invert_screen(self, duration_ms):
"""根据不同操作系统调用相应的反色API"""
logger.info(f"请求屏幕反色,持续时间: {duration_ms}毫秒")
threading.Thread(target=self._invert_and_restore, args=(duration_ms,), daemon=True).start()
def _invert_and_restore(self, duration_ms):
"""执行反色并在指定时间后恢复"""
try:
logger.info("开始执行屏幕反色...")
self._enable_inversion()
ScreenInverter._is_inverted = True
logger.info(f"屏幕已反色,等待 {duration_ms/1000} 秒")
time.sleep(duration_ms / 1000.0)
except Exception as e:
logger.error(f"反色过程中发生错误: {e}")
finally:
logger.info("准备恢复屏幕设置...")
self._disable_inversion()
ScreenInverter._is_inverted = False
logger.info("屏幕设置已恢复")
def _enable_inversion(self):
"""启用系统反色"""
logger.info(f"尝试在 {self._platform} 平台启用反色")
if self._platform == "Windows":
try:
# 使用ctypes模拟键盘输入 (Win+Ctrl+I)
self._send_key_combo([0x5B, 0x11, 0x49]) # Win+Ctrl+I
self._original_state = False
logger.info("Windows反色命令已发送")
except Exception as e:
logger.error(f"无法启用Windows反色: {e}")
# 回退到模拟反色
self._fallback_invert()
elif self._platform == "Darwin": # macOS
try:
script = 'tell application "System Events" to set value of ui element "Invert colors" of row 1 of table 1 of scroll area 1 of window "Display" of application process "System Preferences" to true'
subprocess.run(["osascript", "-e", script], check=True)
self._original_state = False
logger.info("macOS反色命令已发送")
except Exception as e:
logger.error(f"无法启用macOS反色: {e}")
self._fallback_invert()
elif self._platform == "Linux":
try:
subprocess.run(["xrandr", "--output", "HDMI-1", "--gamma", "0.1:0.1:0.1"], check=True)
self._original_state = True
logger.info("Linux反色命令已发送")
except Exception as e:
logger.error(f"无法启用Linux反色: {e}")
self._fallback_invert()
else:
logger.info(f"未知平台 {self._platform},使用模拟反色")
self._fallback_invert()
def _disable_inversion(self):
"""禁用系统反色"""
logger.info(f"尝试在 {self._platform} 平台禁用反色")
if self._platform == "Windows":
try:
if self._original_state is not None:
self._send_key_combo([0x5B, 0x11, 0x49]) # Win+Ctrl+I
logger.info("Windows恢复命令已发送")
except Exception as e:
logger.error(f"无法禁用Windows反色: {e}")
elif self._platform == "Darwin":
try:
script = 'tell application "System Events" to set value of ui element "Invert colors" of row 1 of table 1 of scroll area 1 of window "Display" of application process "System Preferences" to false'
subprocess.run(["osascript", "-e", script], check=True)
logger.info("macOS恢复命令已发送")
except Exception as e:
logger.error(f"无法禁用macOS反色: {e}")
elif self._platform == "Linux":
try:
if self._original_state is not None:
subprocess.run(["xrandr", "--output", "HDMI-1", "--gamma", "1.0:1.0:1.0"], check=True)
logger.info("Linux恢复命令已发送")
except Exception as e:
logger.error(f"无法禁用Linux反色: {e}")
def _send_key_combo(self, vk_codes):
"""使用ctypes模拟键盘组合键"""
if self._platform != "Windows":
return
logger.info(f"模拟键盘组合键: {[hex(code) for code in vk_codes]}")
inputs = []
# 按下所有键
for vk in vk_codes:
ki = self._KBDINPUT(
type=0,
wVk=vk,
wScan=0,
dwFlags=0,
time=0,
dwExtraInfo=ctypes.pointer(ctypes.c_ulong(0))
)
inputs.append(self._INPUT(type=self._INPUT_KEYBOARD, ki=ki))
time.sleep(0.2) # 增加按键间隔,确保系统接收
# 释放所有键(顺序相反)
for vk in reversed(vk_codes):
ki = self._KBDINPUT(
type=0,
wVk=vk,
wScan=0,
dwFlags=self._KEYEVENTF_KEYUP,
time=0,
dwExtraInfo=ctypes.pointer(ctypes.c_ulong(0))
)
inputs.append(self._INPUT(type=self._INPUT_KEYBOARD, ki=ki))
time.sleep(0.2) # 增加按键间隔,确保系统接收
# 执行输入
ctypes_array = (self._INPUT * len(inputs))(*inputs)
result = self._user32.SendInput(len(inputs), ctypes.byref(ctypes_array), ctypes.sizeof(self._INPUT))
logger.info(f"键盘输入模拟结果: {result}")
def _fallback_invert(self):
"""使用模拟反色(半透明覆盖层)"""
logger.info("使用模拟反色模式")
# 如果已有覆盖层,先销毁它
if self._overlay and self._overlay.winfo_exists():
self._overlay.destroy()
# 创建全屏覆盖窗口
self._overlay = tk.Toplevel(self.root)
self._overlay.attributes('-fullscreen', True)
self._overlay.attributes('-alpha', 0.5) # 半透明效果
self._overlay.configure(bg='black')
self._overlay.overrideredirect(True) # 无边框窗口
self._overlay.lift()
self._overlay.attributes('-topmost', True)
# 绑定ESC键退出反色模式(仅用于调试)
self._overlay.bind('<Escape>', lambda e: self._overlay.destroy())
logger.info("模拟反色窗口已创建")
def get_screen_info():
"""获取屏幕信息用于分辨率自适应"""
root = tk.Tk()
root.withdraw()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
base_width, base_height = 1920, 1080
width_ratio = screen_width / base_width
height_ratio = screen_height / base_height
scale_ratio = (width_ratio + height_ratio) / 2
root.destroy()
logger.info(f"屏幕信息: 宽度={screen_width}, 高度={screen_height}, 缩放比例={scale_ratio}")
return {"width": screen_width, "height": screen_height, "scale_ratio": scale_ratio}
def lonlat_to_window(lon, lat, win_width, win_height):
"""将经纬度转换为窗口左上角坐标(中心定位)"""
screen = get_screen_info()
scr_center_x, scr_center_y = screen["width"] / 2, screen["height"] / 2
lon_factor = (screen["width"] * 0.8) / 360
lat_factor = (screen["height"] * 0.8) / 720
center_x = scr_center_x + lon * lon_factor
center_y = scr_center_y + lat * lat_factor
left_x = int(center_x - win_width / 2)
top_y = int(center_y - win_height / 2)
left_x = max(10, min(left_x, screen["width"] - win_width - 10))
top_y = max(10, min(top_y, screen["height"] - win_height - 10))
logger.info(f"经纬度 ({lon}, {lat}) 转换为窗口坐标: ({left_x}, {top_y})")
return left_x, top_y
def mgx(x: float, y: float, n: int, message: str = "ERROR", title: str = "系统错误") -> Popup:
"""
在指定经纬度创建弹窗(中心定位)
参数:
x: 经度(-180~180),0为屏幕中心,正值向右
y: 纬度(-360~360),0为屏幕中心,正值向下
n: 显示此弹窗后多久显示下一个,单位:毫秒
message: 弹窗文本,默认"ERROR"
title: 弹窗标题,默认"系统错误"
返回: 弹窗对象,可调用close()关闭
"""
logger.info(f"创建弹窗: 位置=({x}, {y}), 延迟={n}ms, 标题='{title}', 消息='{message}'")
if not (-180 <= x <= 180 and -360 <= y <= 360):
logger.error(f"坐标超出范围: ({x}, {y})")
messagebox.showerror("坐标错误", f"经纬度范围应为(-180~180, -360~360),当前: ({x}, {y})")
return None
screen = get_screen_info()
root = tk.Toplevel()
root.title(title)
win_width = int(min(300, screen["width"] * 0.25))
win_height = int(min(180, screen["height"] * 0.2))
left_x, top_y = lonlat_to_window(x, y, win_width, win_height)
root.geometry(f"{win_width}x{win_height}+{left_x}+{top_y}")
root.attributes("-topmost", True)
root.resizable(False, False)
scale_ratio = screen["scale_ratio"]
err_font = max(10, int(14 * scale_ratio))
btn_font = max(8, int(10 * scale_ratio))
main_frame = tk.Frame(root, padx=int(15 * scale_ratio), pady=int(15 * scale_ratio))
main_frame.pack(fill="both", expand=True)
msg_label = tk.Label(
main_frame, text=message, font=("SimHei", err_font, "bold"),
fg="#E63946", wraplength=win_width-30, justify="center",
pady=int(12 * scale_ratio)
)
msg_label.pack(fill="both", expand=True)
btn_frame = tk.Frame(main_frame)
btn_frame.pack(pady=int(8 * scale_ratio))
tk.Button(
btn_frame, text="关闭", command=root.destroy,
width=8, height=1, font=("SimHei", btn_font),
bg="#E63946", fg="white", relief=tk.RAISED, bd=2
).pack()
root.protocol("WM_DELETE_WINDOW", root.destroy)
window_id = len(Popup._all_popups)
popup = Popup(root, window_id)
Popup._all_popups.append(popup)
logger.info(f"弹窗已创建,ID={window_id}")
return popup, n
def create_blue_screen(root, duration=5000):
"""创建全屏蓝屏弹窗,模拟电脑蓝屏效果"""
logger.info(f"创建蓝屏模拟,持续时间: {duration}毫秒")
# 创建全屏窗口
blue_screen = tk.Toplevel(root)
blue_screen.attributes('-fullscreen', True)
blue_screen.configure(bg='#000080') # 深蓝色背景(Windows蓝屏色)
blue_screen.overrideredirect(True) # 无边框
blue_screen.attributes('-topmost', True)
blue_screen.lift()
# 获取屏幕尺寸
screen_width = blue_screen.winfo_screenwidth()
screen_height = blue_screen.winfo_screenheight()
# 计算字体大小(自适应屏幕)
font_size = min(24, int(screen_width / 40))
# 错误代码文本
error_label = tk.Label(
blue_screen,
text="STOP: 0x0000007B (0xF78D2524, 0xC0000034, 0x00000000, 0x00000000)",
font=("Consolas", font_size, "bold"),
fg="white",
bg="#000080"
)
error_label.place(relx=0.5, rely=0.4, anchor="center")
# 提示文本
tip_label = tk.Label(
blue_screen,
text="你的电脑遇到问题,需要重新启动。",
font=("Consolas", font_size - 2),
fg="white",
bg="#000080"
)
tip_label.place(relx=0.5, rely=0.5, anchor="center")
# 重启倒计时
countdown_var = tk.StringVar()
countdown_var.set("将在 5 秒后重新启动...")
countdown = tk.Label(
blue_screen,
textvariable=countdown_var,
font=("Consolas", font_size - 2),
fg="white",
bg="#000080"
)
countdown.place(relx=0.5, rely=0.6, anchor="center")
# 绘制进度条
progress = tk.Canvas(blue_screen, width=screen_width * 0.8, height=20, bg="#000080", highlightthickness=0)
progress.place(relx=0.5, rely=0.7, anchor="center")
progress_bar = progress.create_rectangle(
0, 0, 0, 20,
fill="#45818e", outline="#1a5276", width=2
)
# 更新倒计时和进度条的函数
def update_countdown(seconds_left):
if seconds_left <= 0:
blue_screen.destroy()
# 关闭所有弹窗并退出程序
for popup in Popup._all_popups:
if popup:
popup.close()
root.after(100, root.quit)
return
# 更新倒计时文本
countdown_var.set(f"将在 {seconds_left} 秒后重新启动...")
# 更新进度条
progress_width = screen_width * 0.8 * (1 - seconds_left / 5)
progress.coords(progress_bar, 0, 0, progress_width, 20)
# 继续倒计时
blue_screen.after(1000, update_countdown, seconds_left - 1)
# 开始倒计时
blue_screen.after(1000, update_countdown, 5)
# 绑定ESC键退出蓝屏(仅用于调试)
blue_screen.bind('<Escape>', lambda e: blue_screen.destroy())
def create_popups_sequentially(popup_data, index=0, root=None, inverter=None):
"""按顺序创建弹窗,每个弹窗可设置独立延迟"""
if index >= len(popup_data):
logger.info("所有弹窗和命令已执行完毕")
# 执行蓝屏模拟
create_blue_screen(root)
return
item = popup_data[index]
logger.info(f"处理项目 #{index}: {item}")
# 处理普通弹窗
if isinstance(item, tuple) and len(item) == 5:
x, y, n, message, title = item
logger.info(f"创建弹窗: 位置=({x}, {y}), 延迟={n}ms, 标题='{title}', 消息='{message}'")
_, delay = mgx(x, y, n, message, title)
root.after(delay, create_popups_sequentially, popup_data, index + 1, root, inverter)
# 处理反色命令
elif callable(item) and hasattr(item, '__name__') and item.__name__ == 'fanse':
duration = item()
logger.info(f"执行反色命令,持续时间={duration}ms")
inverter.invert_screen(duration)
# 等待反色效果结束后继续
root.after(duration, create_popups_sequentially, popup_data, index + 1, root, inverter)
else:
logger.warning(f"未知类型的项目 #{index}: {item}")
root.after(100, create_popups_sequentially, popup_data, index + 1, root, inverter)
def fanse(n):
"""创建一个反色命令函数,持续n毫秒"""
def execute_fanse():
logger.info(f"反色命令被调用,返回持续时间={n}ms")
return n
execute_fanse.__name__ = 'fanse' # 设置函数名用于识别
return execute_fanse
if __name__ == "__main__":
logger.info("程序开始执行")
root = tk.Tk()
root.withdraw() # 隐藏主窗口
# 创建屏幕反色管理器
inverter = ScreenInverter.get_instance(root)
# 定义弹窗数据 - 增加反色持续时间以便观察
popup_data = [
(-180, -360, 500, "ERROR", "系统错误"),
(180, -360, 300, "ERROR", "系统错误"),
(-180, 360, 500, "ERROR", "系统错误"),
(180, 360, 300, "ERROR", "系统错误"),
(-140, -320, 0, "ERROR", "系统错误"),
(140, -320, 0, "ERROR", "系统错误"),
(-140, 320, 0, "ERROR", "系统错误"),
(140, 320, 50, "ERROR", "系统错误"),
(-100, -300, 0, "ERROR", "系统错误"),
(100, -300, 0, "ERROR", "系统错误"),
(-100, 300, 0, "ERROR", "系统错误"),
(100, 300, 30, "ERROR", "系统错误"),
(0, 0, 0, "ERROR", "系统错误"),
(0, 0, 0, "ERROR", "系统错误"),
(0, 0, 0, "ERROR", "系统错误"),
(0, 0, 30, "ERROR", "系统错误"),
(0, 100, 50, "ERROR", "系统错误"),
(0, -100, 30, "ERROR", "系统错误"),
(100, 0, 50, "ERROR", "系统错误"),
(-100, 0, 30, "ERROR", "系统错误"),
(0, 200, 50, "ERROR", "系统错误"),
(0, -200, 30, "ERROR", "系统错误"),
(180, 0, 50, "ERROR", "系统错误"),
(-180, 0, 30, "ERROR", "系统错误"),
(0, 300, 50, "ERROR", "系统错误"),
(0, -300, 30, "ERROR", "系统错误"),
(10, 0, 50, "ERROR", "系统错误"),
(-10, 0, 30, "ERROR", "系统错误"),
*[(random.uniform(-180, 180), random.uniform(-360, 360), 0, "ERROR", "系统错误") for _ in range(10)],
(0, 0, 0, "ERROR", "系统错误"),
*[(random.uniform(-180, 180), random.uniform(-360, 360), 0, "ERROR", "系统错误") for _ in range(10)],
fanse(3000), # 屏幕反色3000毫秒(3秒),便于观察
]
# 开始按顺序创建弹窗和执行反色命令
logger.info("开始执行弹窗和反色命令序列")
create_popups_sequentially(popup_data, 0, root, inverter)
root.mainloop()
logger.info("程序已成功退出")
只是一个观赏类病毒,不会对电脑造成伤害!
程序会自动退出,可以放心运行
最后有好东西
这里空空如也
有帮助,赞一个