吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 855|回复: 25
上一主题 下一主题
收起左侧

[原创工具] 注册表监控工具--精准追踪器

[复制链接]
跳转到指定楼层
楼主
situhaonan 发表于 2026-5-8 13:37 回帖奖励
用PYTHON写了个注册表监视器。有需要的用








附加下载:https://wwamp.lanzouu.com/imuCr3p02zxe

免费评分

参与人数 5吾爱币 +5 热心值 +4 收起 理由
beatone + 1 我很赞同!
abcd00abcd + 1 + 1 热心回复!
cioceo + 1 + 1 谢谢@Thanks!
henrylong1989 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
helh0275 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| situhaonan 发表于 2026-5-8 14:10 |楼主
riyuexiaoyao 发表于 2026-5-8 14:08
好工具  大佬可以共享一下Python代码吗

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
注册表监视工具 - 精准程序监控版(笔记本优化版)
监视指定程序从启动到运行过程中的所有注册表修改
"""

import sys
import os
import threading
import time
import subprocess
from datetime import datetime
from typing import Dict, List, Tuple
import ctypes
from ctypes import wintypes

try:
    import tkinter as tk
    from tkinter import ttk, messagebox, filedialog, scrolledtext
    import winreg
    import psutil
except ImportError:
    print("请先安装 psutil: pip install psutil")
    sys.exit(1)

# 注册表根键映射
ROOT_KEYS = {
    "HKEY_CLASSES_ROOT": winreg.HKEY_CLASSES_ROOT,
    "HKEY_CURRENT_USER": winreg.HKEY_CURRENT_USER,
    "HKEY_LOCAL_MACHINE": winreg.HKEY_LOCAL_MACHINE,
    "HKEY_USERS": winreg.HKEY_USERS,
    "HKEY_CURRENT_CONFIG": winreg.HKEY_CURRENT_CONFIG,
}

VALUE_TYPES = {
    winreg.REG_SZ: "REG_SZ",
    winreg.REG_EXPAND_SZ: "REG_EXPAND_SZ",
    winreg.REG_BINARY: "REG_BINARY",
    winreg.REG_MULTI_SZ: "REG_MULTI_SZ",
    winreg.REG_DWORD: "REG_DWORD",
    winreg.REG_QWORD: "REG_QWORD",
}

# 系统进程列表(需要过滤的)
SYSTEM_PROCESSES = [
    "System", "System Idle Process", "svchost.exe", "explorer.exe", "csrss.exe",
    "winlogon.exe", "services.exe", "lsass.exe", "wininit.exe", "spoolsv.exe",
    "taskhost.exe", "dwm.exe", "SearchIndexer.exe", "WmiPrvSE.exe", "conhost.exe",
    "ctfmon.exe", "sihost.exe", "RuntimeBroker.exe", "ShellExperienceHost.exe",
    "SearchUI.exe", "StartMenuExperienceHost.exe", "TextInputHost.exe", "cmd.exe"
]


class RegistrySnapshot:
    """注册表快照类"""
   
    def __init__(self):
        self.data = {}
        
    def add_key(self, key_path: str, value_name: str, value, value_type: int):
        if key_path not in self.data:
            self.data[key_path] = {}
        self.data[key_path][value_name] = (value, value_type)
   
    def compare(self, other: 'RegistrySnapshot') -> List[Dict]:
        """比较两个快照"""
        changes = []
        
        # 检查删除和修改
        for key_path, values in self.data.items():
            if key_path not in other.data:
                for value_name, (val, val_type) in values.items():
                    changes.append({
                        'type': 'delete',
                        'key': key_path,
                        'value': value_name if value_name else '(默认)',
                        'old_value': self._format_value(val),
                        'new_value': None,
                        'value_type': VALUE_TYPES.get(val_type, f'Type_{val_type}')
                    })
            else:
                other_values = other.data[key_path]
                for value_name, (old_val, old_type) in values.items():
                    if value_name not in other_values:
                        changes.append({
                            'type': 'delete',
                            'key': key_path,
                            'value': value_name if value_name else '(默认)',
                            'old_value': self._format_value(old_val),
                            'new_value': None,
                            'value_type': VALUE_TYPES.get(old_type, f'Type_{old_type}')
                        })
                    else:
                        new_val, new_type = other_values[value_name]
                        if str(old_val) != str(new_val) or old_type != new_type:
                            changes.append({
                                'type': 'modify',
                                'key': key_path,
                                'value': value_name if value_name else '(默认)',
                                'old_value': self._format_value(old_val),
                                'new_value': self._format_value(new_val),
                                'value_type': VALUE_TYPES.get(old_type, f'Type_{old_type}')
                            })
        
        # 检查新增
        for key_path, values in other.data.items():
            if key_path not in self.data:
                for value_name, (new_val, new_type) in values.items():
                    changes.append({
                        'type': 'create',
                        'key': key_path,
                        'value': value_name if value_name else '(默认)',
                        'old_value': None,
                        'new_value': self._format_value(new_val),
                        'value_type': VALUE_TYPES.get(new_type, f'Type_{new_type}')
                    })
            else:
                self_values = self.data[key_path]
                for value_name, (new_val, new_type) in values.items():
                    if value_name not in self_values:
                        changes.append({
                            'type': 'create',
                            'key': key_path,
                            'value': value_name if value_name else '(默认)',
                            'old_value': None,
                            'new_value': self._format_value(new_val),
                            'value_type': VALUE_TYPES.get(new_type, f'Type_{new_type}')
                        })
        
        return changes
   
    def _format_value(self, value):
        """格式化值用于显示"""
        if isinstance(value, bytes):
            if len(value) > 64:
                return value.hex()[:64] + "..."
            return value.hex()
        elif isinstance(value, list):
            if len(value) > 5:
                return "|".join(str(v) for v in value[:5]) + "..."
            return "|".join(str(v) for v in value)
        else:
            return str(value)[:200]


class RegistryScanner:
    """注册表扫描器"""
   
    @staticmethod
    def scan_registry(selected_keys: List[str], callback=None) -> RegistrySnapshot:
        """扫描注册表"""
        snapshot = RegistrySnapshot()
        
        for root_name in selected_keys:
            if root_name not in ROOT_KEYS:
                continue
            
            if callback:
                callback(f"正在扫描 {root_name}...")
            
            try:
                RegistryScanner._scan_key(ROOT_KEYS[root_name], "", root_name, snapshot)
            except Exception as e:
                print(f"扫描 {root_name} 出错: {e}")
        
        return snapshot
   
    @staticmethod
    def _scan_key(root_handle, sub_key: str, root_name: str, snapshot: RegistrySnapshot):
        """递归扫描注册表键"""
        key_path = f"{root_name}\\{sub_key}" if sub_key else root_name
        
        try:
            key = winreg.OpenKey(root_handle, sub_key, 0, winreg.KEY_READ)
            
            # 读取值
            index = 0
            while True:
                try:
                    value_name, value_data, value_type = winreg.EnumValue(key, index)
                    
                    if value_type == winreg.REG_BINARY:
                        if isinstance(value_data, bytes):
                            value_data = value_data
                    elif value_type == winreg.REG_MULTI_SZ:
                        if value_data:
                            value_data = value_data
                    
                    snapshot.add_key(key_path, value_name, value_data, value_type)
                    index += 1
                except OSError:
                    break
            
            # 递归扫描子键
            index = 0
            while True:
                try:
                    sub_key_name = winreg.EnumKey(key, index)
                    new_sub_key = f"{sub_key}\\{sub_key_name}" if sub_key else sub_key_name
                    RegistryScanner._scan_key(root_handle, new_sub_key, root_name, snapshot)
                    index += 1
                except OSError:
                    break
            
            winreg.CloseKey(key)
        except PermissionError:
            pass
        except Exception:
            pass


class RegistryMonitorApp:
    """主应用程序"""
   
    def __init__(self, root):
        self.root = root
        self.root.title("注册表监控工具 - 精准追踪器")
        self.root.geometry("1100x600")  # 缩小尺寸,适合笔记本
        
        # 颜色配置
        self.bg_color = "#1e1e1e"
        self.fg_color = "#ffffff"
        
        # 监控状态
        self.before_snapshot = None
        self.after_snapshot = None
        self.selected_program = None
        self.target_process_name = None
        self.target_process_pid = None
        
        self.setup_ui()
        
    def setup_ui(self):
        """设置界面"""
        self.root.configure(bg=self.bg_color)
        
        # 主框架
        main_frame = tk.Frame(self.root, bg=self.bg_color)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 左侧控制面板(宽度减小)
        left_frame = tk.Frame(main_frame, bg=self.bg_color, width=320)
        left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 5))
        left_frame.pack_propagate(False)
        
        # 程序选择区域
        program_group = tk.LabelFrame(left_frame, text="1. 选择要监控的程序",
                                      bg=self.bg_color, fg=self.fg_color,
                                      font=("Arial", 10, "bold"))
        program_group.pack(fill=tk.X, pady=(0, 5))
        
        tk.Label(program_group, text="程序路径:", bg=self.bg_color, fg=self.fg_color, font=("Arial", 9)).grid(row=0, column=0, padx=3, pady=3, sticky=tk.W)
        self.program_path = tk.Entry(program_group, width=28, bg="#2d2d2d", fg=self.fg_color,
                                     insertbackground="white", font=("Arial", 8))
        self.program_path.grid(row=0, column=1, padx=3, pady=3)
        
        self.btn_browse = tk.Button(program_group, text="浏览", command=self.browse_program,
                                   bg="#3c3c3c", fg=self.fg_color, relief=tk.FLAT, font=("Arial", 8))
        self.btn_browse.grid(row=0, column=2, padx=3, pady=3)
        
        tk.Label(program_group, text="程序参数:", bg=self.bg_color, fg=self.fg_color, font=("Arial", 9)).grid(row=1, column=0, padx=3, pady=3, sticky=tk.W)
        self.program_args = tk.Entry(program_group, width=28, bg="#2d2d2d", fg=self.fg_color,
                                     insertbackground="white", font=("Arial", 8))
        self.program_args.grid(row=1, column=1, columnspan=2, padx=3, pady=3, sticky=tk.W+tk.E)
        
        # 过滤选项
        filter_group = tk.LabelFrame(left_frame, text="过滤选项",
                                     bg=self.bg_color, fg=self.fg_color,
                                     font=("Arial", 10, "bold"))
        filter_group.pack(fill=tk.X, pady=(0, 5))
        
        self.filter_system = tk.BooleanVar(value=True)
        tk.Checkbutton(filter_group, text="过滤系统进程", variable=self.filter_system,
                      bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                      font=("Arial", 9)).pack(anchor=tk.W, padx=5, pady=2)
        
        self.filter_common = tk.BooleanVar(value=True)
        tk.Checkbutton(filter_group, text="过滤常见系统操作", variable=self.filter_common,
                      bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                      font=("Arial", 9)).pack(anchor=tk.W, padx=5, pady=2)
        
        # 注册表区域选择
        registry_group = tk.LabelFrame(left_frame, text="2. 监控的注册表区域",
                                       bg=self.bg_color, fg=self.fg_color,
                                       font=("Arial", 10, "bold"))
        registry_group.pack(fill=tk.X, pady=(0, 5))
        
        self.registry_vars = {}
        registry_keys = [
            "HKEY_CLASSES_ROOT",
            "HKEY_CURRENT_USER",
            "HKEY_LOCAL_MACHINE",
            "HKEY_USERS",
            "HKEY_CURRENT_CONFIG"
        ]
        
        for i, key in enumerate(registry_keys):
            var = tk.BooleanVar(value=(key == "HKEY_CURRENT_USER" or key == "HKEY_LOCAL_MACHINE"))
            self.registry_vars[key] = var
            cb = tk.Checkbutton(registry_group, text=key, variable=var,
                               bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                               font=("Arial", 8))
            cb.grid(row=i, column=0, padx=5, pady=1, sticky=tk.W)
        
        # 控制按钮
        control_group = tk.LabelFrame(left_frame, text="3. 开始监控",
                                      bg=self.bg_color, fg=self.fg_color,
                                      font=("Arial", 10, "bold"))
        control_group.pack(fill=tk.X, pady=(0, 5))
        
        self.btn_step1 = tk.Button(control_group, text="步骤1: 创建监控前快照",
                                   command=self.create_before_snapshot,
                                   bg="#0d7377", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9))
        self.btn_step1.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_step2 = tk.Button(control_group, text="步骤2: 启动程序",
                                   command=self.start_program,
                                   bg="#4caf50", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_step2.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_step3 = tk.Button(control_group, text="步骤3: 对比注册表变化",
                                   command=self.create_after_snapshot,
                                   bg="#ff9800", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_step3.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_export = tk.Button(control_group, text="导出报告",
                                   command=self.export_report,
                                   bg="#2196f3", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_export.pack(fill=tk.X, padx=5, pady=3)
        
        # 状态显示
        status_group = tk.LabelFrame(left_frame, text="状态",
                                     bg=self.bg_color, fg=self.fg_color,
                                     font=("Arial", 10, "bold"))
        status_group.pack(fill=tk.X)
        
        self.status_label = tk.Label(status_group, text="就绪",
                                     bg=self.bg_color, fg="#00ff00",
                                     font=("Arial", 9), anchor=tk.W)
        self.status_label.pack(fill=tk.X, padx=5, pady=5)
        
        # 右侧结果显示区域
        right_frame = tk.Frame(main_frame, bg=self.bg_color)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 标签页
        notebook = ttk.Notebook(right_frame)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 变化日志页
        log_frame = ttk.Frame(notebook)
        notebook.add(log_frame, text="目标程序变化")
        
        self.log_text = scrolledtext.ScrolledText(log_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                   font=("Consolas", 9), insertbackground="white")
        self.log_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
        # 配置日志颜色
        self.log_text.tag_config("create", foreground="#6a9955")
        self.log_text.tag_config("modify", foreground="#ce9178")
        self.log_text.tag_config("delete", foreground="#f48771")
        self.log_text.tag_config("info", foreground="#569cd6")
        self.log_text.tag_config("success", foreground="#6a9955")
        self.log_text.tag_config("error", foreground="#f48771")
        self.log_text.tag_config("filtered", foreground="#808080")
        
        # 所有变化页
        all_log_frame = ttk.Frame(notebook)
        notebook.add(all_log_frame, text="所有变化")
        
        self.all_log_text = scrolledtext.ScrolledText(all_log_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                       font=("Consolas", 9), insertbackground="white")
        self.all_log_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
        for tag in ["create", "modify", "delete", "info", "success", "error"]:
            self.all_log_text.tag_config(tag, foreground=self.log_text.tag_cget(tag, "foreground"))
        
        # 统计信息页
        stats_frame = ttk.Frame(notebook)
        notebook.add(stats_frame, text="统计信息")
        
        self.stats_text = scrolledtext.ScrolledText(stats_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                     font=("Consolas", 9), insertbackground="white")
        self.stats_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
    def browse_program(self):
        """浏览选择程序"""
        file_path = filedialog.askopenfilename(
            title="选择要监控的程序",
            filetypes=[("可执行文件", "*.exe"), ("所有文件", "*.*")]
        )
        if file_path:
            self.program_path.delete(0, tk.END)
            self.program_path.insert(0, file_path)
            self.selected_program = file_path
            self.target_process_name = os.path.basename(file_path).lower()
            self.log(f"已选择程序: {self.target_process_name}", "info")
   
    def log(self, message: str, tag: str = "info", to_all=True):
        """添加日志"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        
        # 主日志
        self.log_text.insert(tk.END, f"[{timestamp}] ", "info")
        self.log_text.insert(tk.END, f"{message}\n", tag)
        self.log_text.see(tk.END)
        
        # 所有变化日志
        if to_all:
            self.all_log_text.insert(tk.END, f"[{timestamp}] ", "info")
            self.all_log_text.insert(tk.END, f"{message}\n", tag)
            self.all_log_text.see(tk.END)
        
        self.root.update_idletasks()
   
    def log_change(self, change: Dict, is_target: bool = False):
        """记录变化"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        change_type = change['type']
        
        if change_type == 'create':
            tag = "create"
            icon = "➕"
            msg = f"{icon} 新增: {change['key']}\\{change['value']}"
        elif change_type == 'modify':
            tag = "modify"
            icon = "✏️"
            msg = f"{icon} 修改: {change['key']}\\{change['value']}"
        else:
            tag = "delete"
            icon = "❌"
            msg = f"{icon} 删除: {change['key']}\\{change['value']}"
        
        # 始终记录到所有变化日志
        self.all_log_text.insert(tk.END, f"[{timestamp}] ", "info")
        self.all_log_text.insert(tk.END, f"{msg}\n", tag)
        self.all_log_text.see(tk.END)
        
        # 只记录目标程序相关的变化到主日志
        if is_target:
            self.log_text.insert(tk.END, f"[{timestamp}] ", "info")
            self.log_text.insert(tk.END, f"{msg}\n", tag)
            self.log_text.see(tk.END)
        elif not self.filter_system.get():
            self.log_text.insert(tk.END, f"[{timestamp}] ", "filtered")
            self.log_text.insert(tk.END, f"[过滤] {msg}\n", "filtered")
            self.log_text.see(tk.END)
        
        self.root.update_idletasks()
   
    def update_status(self, message: str, color: str = "#00ff00"):
        """更新状态栏"""
        self.status_label.config(text=message, fg=color)
        self.root.update_idletasks()
   
    def is_change_from_target(self, change: Dict) -> bool:
        """判断变化是否来自目标程序"""
        if not self.target_process_name:
            return False
        
        # 检查变化路径是否包含目标程序名
        key_lower = change['key'].lower()
        value_lower = str(change['value']).lower()
        old_val_lower = str(change['old_value']).lower() if change['old_value'] else ""
        new_val_lower = str(change['new_value']).lower() if change['new_value'] else ""
        
        # 检查是否包含目标程序名
        target_name = self.target_process_name.replace('.exe', '')
        if target_name in key_lower:
            return True
        if self.target_process_name in value_lower:
            return True
        if self.target_process_name in old_val_lower:
            return True
        if self.target_process_name in new_val_lower:
            return True
        
        # 检查是否包含目标程序的完整路径
        if self.selected_program and self.selected_program.lower() in key_lower:
            return True
        
        return False
   
    def filter_common_operations(self, changes: List[Dict]) -> List[Dict]:
        """过滤常见系统操作"""
        if not self.filter_common.get():
            return changes
        
        filtered = []
        common_patterns = [
            "\\SessionInfo\\",
            "\\FeatureUsage\\",
            "\\UserAssist\\",
            "\\ActivityDataModel\\",
            "\\bam\\State\\",
            "\\Notifications\\Data",
            "\\DolbySettings\\",
            "\\SystemAppData\\",
            "\\hivelist",
        ]
        
        for change in changes:
            key_lower = change['key'].lower()
            is_common = False
            for pattern in common_patterns:
                if pattern.lower() in key_lower:
                    is_common = True
                    break
            
            if not is_common:
                filtered.append(change)
        
        return filtered
   
    def create_before_snapshot(self):
        """创建监控前的快照"""
        selected_keys = [key for key, var in self.registry_vars.items() if var.get()]
        if not selected_keys:
            messagebox.showwarning("警告", "请至少选择一个注册表区域")
            return
        
        self.log("=" * 50, "info")
        self.log("开始创建监控前的注册表快照...", "info")
        self.update_status("正在创建快照...", "#ffff00")
        
        def scan_thread():
            try:
                snapshot = RegistryScanner.scan_registry(selected_keys, self.log_status)
                self.before_snapshot = snapshot
               
                total_keys = len(snapshot.data)
                total_values = sum(len(values) for values in snapshot.data.values())
               
                self.root.after(0, lambda: self.log(f"✅ 监控前快照创建完成!", "success"))
                self.root.after(0, lambda: self.log(f"   扫描到 {total_keys} 个键, {total_values} 个值", "info"))
                self.root.after(0, lambda: self.update_status("快照创建完成", "#00ff00"))
                self.root.after(0, lambda: self.btn_step2.config(state=tk.NORMAL))
               
            except Exception as e:
                self.root.after(0, lambda: self.log(f"❌ 创建快照失败: {e}", "error"))
                self.root.after(0, lambda: self.update_status("快照创建失败", "#ff0000"))
        
        threading.Thread(target=scan_thread, daemon=True).start()
   
    def log_status(self, message: str):
        """记录扫描状态"""
        self.root.after(0, lambda: self.log(message, "info"))
   
    def start_program(self):
        """启动程序"""
        program = self.program_path.get().strip()
        if not program:
            messagebox.showwarning("警告", "请选择要监控的程序")
            return
        
        if not os.path.exists(program):
            messagebox.showerror("错误", f"程序文件不存在:\n{program}")
            return
        
        args = self.program_args.get().strip()
        
        try:
            self.log("=" * 50, "info")
            self.log(f"正在启动程序: {os.path.basename(program)}", "info")
            
            if args:
                cmd = f'"{program}" {args}'
            else:
                cmd = f'"{program}"'
            
            self.process = subprocess.Popen(cmd, shell=True)
            self.target_process_pid = self.process.pid
            
            self.log(f"程序已启动 (PID: {self.target_process_pid})", "success")
            self.update_status(f"程序运行中 (PID: {self.target_process_pid})", "#00ff00")
            
            self.log("", "info")
            self.log("提示: 操作程序后点击'步骤3'查看变化", "info")
            
            self.btn_step2.config(state=tk.DISABLED)
            self.btn_step3.config(state=tk.NORMAL)
            
        except Exception as e:
            self.log(f"❌ 启动程序失败: {e}", "error")
            self.update_status("程序启动失败", "#ff0000")
   
    def create_after_snapshot(self):
        """创建监控后的快照并对比"""
        selected_keys = [key for key, var in self.registry_vars.items() if var.get()]
        if not selected_keys:
            messagebox.showwarning("警告", "请至少选择一个注册表区域")
            return
        
        self.log("=" * 50, "info")
        self.log("开始创建监控后的注册表快照...", "info")
        self.update_status("正在创建快照...", "#ffff00")
        
        def scan_thread():
            try:
                after_snapshot = RegistryScanner.scan_registry(selected_keys, self.log_status)
               
                self.log("正在对比注册表变化...", "info")
                all_changes = self.before_snapshot.compare(after_snapshot)
               
                # 过滤常见系统操作
                all_changes = self.filter_common_operations(all_changes)
               
                # 分离目标程序的变化
                target_changes = []
                other_changes = []
               
                for change in all_changes:
                    if self.is_change_from_target(change):
                        target_changes.append(change)
                    else:
                        other_changes.append(change)
               
                # 显示结果
                self.root.after(0, lambda: self.display_results(target_changes, other_changes, all_changes))
               
            except Exception as e:
                self.root.after(0, lambda: self.log(f"❌ 对比失败: {e}", "error"))
                self.root.after(0, lambda: self.update_status("对比失败", "#ff0000"))
        
        threading.Thread(target=scan_thread, daemon=True).start()
   
    def display_results(self, target_changes: List[Dict], other_changes: List[Dict], all_changes: List[Dict]):
        """显示结果"""
        # 显示目标程序的变化
        if target_changes:
            create_count = sum(1 for c in target_changes if c['type'] == 'create')
            modify_count = sum(1 for c in target_changes if c['type'] == 'modify')
            delete_count = sum(1 for c in target_changes if c['type'] == 'delete')
            
            self.log("=" * 50, "info")
            self.log(f"🎯 目标程序 ({self.target_process_name}) 变化:", "success")
            self.log(f"   ➕ 新增: {create_count} 项", "create")
            self.log(f"   ✏️ 修改: {modify_count} 项", "modify")
            self.log(f"   ❌ 删除: {delete_count} 项", "delete")
            self.log("=" * 50, "info")
            
            for change in target_changes:
                self.log_change(change, is_target=True)
        else:
            self.log("🎉 未检测到目标程序的注册表变化!", "success")
            self.log("提示: 程序可能没有修改注册表", "info")
        
        # 更新统计
        self.update_stats(target_changes, other_changes, all_changes)
        self.update_status("监控完成", "#00ff00")
        self.btn_export.config(state=tk.NORMAL)
   
    def update_stats(self, target_changes: List[Dict], other_changes: List[Dict], all_changes: List[Dict]):
        """更新统计信息"""
        self.stats_text.delete(1.0, tk.END)
        
        target_create = [c for c in target_changes if c['type'] == 'create']
        target_modify = [c for c in target_changes if c['type'] == 'modify']
        target_delete = [c for c in target_changes if c['type'] == 'delete']
        
        stats = f"""
╔════════════════════════════════════════════════╗
║           注册表监控统计报告                    ║
╚════════════════════════════════════════════════╝

监控时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
监控程序: {os.path.basename(self.program_path.get())}
程序PID: {self.target_process_pid}

┌────────────────────────────────────────────────┐
│              目标程序变化统计                    │
├────────────────────────────────────────────────┤
│ 总计变化数: {len(target_changes)} 项               │
│                                                │
│  ➕ 新增: {len(target_create)} 项                  │
│  ✏️ 修改: {len(target_modify)} 项                  │
│  ❌ 删除: {len(target_delete)} 项                  │
└────────────────────────────────────────────────┘

┌────────────────────────────────────────────────┐
│              所有程序变化统计                    │
├────────────────────────────────────────────────┤
│ 总计变化数: {len(all_changes)} 项                  │
│  ├─ 目标程序: {len(target_changes)} 项              │
│  └─ 其他程序: {len(other_changes)} 项              │
└────────────────────────────────────────────────┘

"""
        
        # 详细变化列表
        if target_changes:
            stats += "\n\n详细变化列表:\n"
            stats += "-" * 50 + "\n"
            
            for i, change in enumerate(target_changes, 1):
                stats += f"\n[{i}] {change['type'].upper()}\n"
                stats += f"    路径: {change['key']}\n"
                stats += f"    值名: {change['value']}\n"
                if change['type'] == 'create':
                    stats += f"    新值: {change['new_value']}\n"
                elif change['type'] == 'modify':
                    stats += f"    原值: {change['old_value']}\n"
                    stats += f"    新值: {change['new_value']}\n"
                else:
                    stats += f"    原值: {change['old_value']}\n"
                stats += f"    类型: {change['value_type']}\n"
        
        self.stats_text.insert(1.0, stats)
   
    def export_report(self):
        """导出报告"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                content = f"""注册表监控报告
生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
监控程序: {self.program_path.get()}
程序参数: {self.program_args.get()}
程序PID: {self.target_process_pid}

{'=' * 70}

【目标程序注册表变化】

{self.log_text.get("1.0", tk.END)}

{'=' * 70}

【所有程序注册表变化(含系统)】

{self.all_log_text.get("1.0", tk.END)}

{'=' * 70}

{self.stats_text.get("1.0", tk.END)}
"""
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
               
                self.log(f"✅ 报告已导出: {file_path}", "success")
                messagebox.showinfo("成功", f"报告已保存到:\n{file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"导出失败: {e}")


def main():
    # 检查管理员权限
    try:
        is_admin = ctypes.windll.shell32.IsUserAnAdmin()
        if not is_admin:
            root = tk.Tk()
            root.withdraw()
            result = messagebox.askyesno(
                "权限提示",
                "建议以管理员身份运行以获得完整的注册表访问权限。\n"
                "是否继续运行?"
            )
            root.destroy()
            if not result:
                return
    except:
        pass
   
    root = tk.Tk()
    app = RegistryMonitorApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
推荐
dork 发表于 2026-5-8 15:04
[Asm] 纯文本查看 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
注册表监视工具 - 精准程序监控版(笔记本优化版)
监视指定程序从启动到运行过程中的所有注册表修改
"""

import sys
import os
import threading
import time
import subprocess
from datetime import datetime
from typing import Dict, List, Tuple
import ctypes
from ctypes import wintypes

try:
    import tkinter as tk
    from tkinter import ttk, messagebox, filedialog, scrolledtext
    import winreg
    import psutil
except ImportError:
    print("请先安装 psutil: pip install psutil")
    sys.exit(1)

# 注册表根键映射
ROOT_KEYS = {
    "HKEY_CLASSES_ROOT": winreg.HKEY_CLASSES_ROOT,
    "HKEY_CURRENT_USER": winreg.HKEY_CURRENT_USER,
    "HKEY_LOCAL_MACHINE": winreg.HKEY_LOCAL_MACHINE,
    "HKEY_USERS": winreg.HKEY_USERS,
    "HKEY_CURRENT_CONFIG": winreg.HKEY_CURRENT_CONFIG,
}

VALUE_TYPES = {
    winreg.REG_SZ: "REG_SZ",
    winreg.REG_EXPAND_SZ: "REG_EXPAND_SZ",
    winreg.REG_BINARY: "REG_BINARY",
    winreg.REG_MULTI_SZ: "REG_MULTI_SZ",
    winreg.REG_DWORD: "REG_DWORD",
    winreg.REG_QWORD: "REG_QWORD",
}

# 系统进程列表(需要过滤的)
SYSTEM_PROCESSES = [
    "System", "System Idle Process", "svchost.exe", "explorer.exe", "csrss.exe",
    "winlogon.exe", "services.exe", "lsass.exe", "wininit.exe", "spoolsv.exe",
    "taskhost.exe", "dwm.exe", "SearchIndexer.exe", "WmiPrvSE.exe", "conhost.exe",
    "ctfmon.exe", "sihost.exe", "RuntimeBroker.exe", "ShellExperienceHost.exe",
    "SearchUI.exe", "StartMenuExperienceHost.exe", "TextInputHost.exe", "cmd.exe"
]


class RegistrySnapshot:
    """注册表快照类"""
   
    def __init__(self):
        self.data = {}
        
    def add_key(self, key_path: str, value_name: str, value, value_type: int):
        if key_path not in self.data:
            self.data[key_path] = {}
        self.data[key_path][value_name] = (value, value_type)
   
    def compare(self, other: 'RegistrySnapshot') -> List[Dict]:
        """比较两个快照"""
        changes = []
        
        # 检查删除和修改
        for key_path, values in self.data.items():
            if key_path not in other.data:
                for value_name, (val, val_type) in values.items():
                    changes.append({
                        'type': 'delete',
                        'key': key_path,
                        'value': value_name if value_name else '(默认)',
                        'old_value': self._format_value(val),
                        'new_value': None,
                        'value_type': VALUE_TYPES.get(val_type, f'Type_{val_type}')
                    })
            else:
                other_values = other.data[key_path]
                for value_name, (old_val, old_type) in values.items():
                    if value_name not in other_values:
                        changes.append({
                            'type': 'delete',
                            'key': key_path,
                            'value': value_name if value_name else '(默认)',
                            'old_value': self._format_value(old_val),
                            'new_value': None,
                            'value_type': VALUE_TYPES.get(old_type, f'Type_{old_type}')
                        })
                    else:
                        new_val, new_type = other_values[value_name]
                        if str(old_val) != str(new_val) or old_type != new_type:
                            changes.append({
                                'type': 'modify',
                                'key': key_path,
                                'value': value_name if value_name else '(默认)',
                                'old_value': self._format_value(old_val),
                                'new_value': self._format_value(new_val),
                                'value_type': VALUE_TYPES.get(old_type, f'Type_{old_type}')
                            })
        
        # 检查新增
        for key_path, values in other.data.items():
            if key_path not in self.data:
                for value_name, (new_val, new_type) in values.items():
                    changes.append({
                        'type': 'create',
                        'key': key_path,
                        'value': value_name if value_name else '(默认)',
                        'old_value': None,
                        'new_value': self._format_value(new_val),
                        'value_type': VALUE_TYPES.get(new_type, f'Type_{new_type}')
                    })
            else:
                self_values = self.data[key_path]
                for value_name, (new_val, new_type) in values.items():
                    if value_name not in self_values:
                        changes.append({
                            'type': 'create',
                            'key': key_path,
                            'value': value_name if value_name else '(默认)',
                            'old_value': None,
                            'new_value': self._format_value(new_val),
                            'value_type': VALUE_TYPES.get(new_type, f'Type_{new_type}')
                        })
        
        return changes
   
    def _format_value(self, value):
        """格式化值用于显示"""
        if isinstance(value, bytes):
            if len(value) > 64:
                return value.hex()[:64] + "..."
            return value.hex()
        elif isinstance(value, list):
            if len(value) > 5:
                return "|".join(str(v) for v in value[:5]) + "..."
            return "|".join(str(v) for v in value)
        else:
            return str(value)[:200]


class RegistryScanner:
    """注册表扫描器"""
   
    @staticmethod
    def scan_registry(selected_keys: List[str], callback=None) -> RegistrySnapshot:
        """扫描注册表"""
        snapshot = RegistrySnapshot()
        
        for root_name in selected_keys:
            if root_name not in ROOT_KEYS:
                continue
            
            if callback:
                callback(f"正在扫描 {root_name}...")
            
            try:
                RegistryScanner._scan_key(ROOT_KEYS[root_name], "", root_name, snapshot)
            except Exception as e:
                print(f"扫描 {root_name} 出错: {e}")
        
        return snapshot
   
    @staticmethod
    def _scan_key(root_handle, sub_key: str, root_name: str, snapshot: RegistrySnapshot):
        """递归扫描注册表键"""
        key_path = f"{root_name}\\{sub_key}" if sub_key else root_name
        
        try:
            key = winreg.OpenKey(root_handle, sub_key, 0, winreg.KEY_READ)
            
            # 读取值
            index = 0
            while True:
                try:
                    value_name, value_data, value_type = winreg.EnumValue(key, index)
                    
                    if value_type == winreg.REG_BINARY:
                        if isinstance(value_data, bytes):
                            value_data = value_data
                    elif value_type == winreg.REG_MULTI_SZ:
                        if value_data:
                            value_data = value_data
                    
                    snapshot.add_key(key_path, value_name, value_data, value_type)
                    index += 1
                except OSError:
                    break
            
            # 递归扫描子键
            index = 0
            while True:
                try:
                    sub_key_name = winreg.EnumKey(key, index)
                    new_sub_key = f"{sub_key}\\{sub_key_name}" if sub_key else sub_key_name
                    RegistryScanner._scan_key(root_handle, new_sub_key, root_name, snapshot)
                    index += 1
                except OSError:
                    break
            
            winreg.CloseKey(key)
        except PermissionError:
            pass
        except Exception:
            pass


class RegistryMonitorApp:
    """主应用程序"""
   
    def __init__(self, root):
        self.root = root
        self.root.title("注册表监控工具 - 精准追踪器")
        self.root.geometry("1100x600")  # 缩小尺寸,适合笔记本
        
        # 颜色配置
        self.bg_color = "#1e1e1e"
        self.fg_color = "#ffffff"
        
        # 监控状态
        self.before_snapshot = None
        self.after_snapshot = None
        self.selected_program = None
        self.target_process_name = None
        self.target_process_pid = None
        
        self.setup_ui()
        
    def setup_ui(self):
        """设置界面"""
        self.root.configure(bg=self.bg_color)
        
        # 主框架
        main_frame = tk.Frame(self.root, bg=self.bg_color)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 左侧控制面板(宽度减小)
        left_frame = tk.Frame(main_frame, bg=self.bg_color, width=320)
        left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 5))
        left_frame.pack_propagate(False)
        
        # 程序选择区域
        program_group = tk.LabelFrame(left_frame, text="1. 选择要监控的程序",
                                      bg=self.bg_color, fg=self.fg_color,
                                      font=("Arial", 10, "bold"))
        program_group.pack(fill=tk.X, pady=(0, 5))
        
        tk.Label(program_group, text="程序路径:", bg=self.bg_color, fg=self.fg_color, font=("Arial", 9)).grid(row=0, column=0, padx=3, pady=3, sticky=tk.W)
        self.program_path = tk.Entry(program_group, width=28, bg="#2d2d2d", fg=self.fg_color,
                                     insertbackground="white", font=("Arial", 8))
        self.program_path.grid(row=0, column=1, padx=3, pady=3)
        
        self.btn_browse = tk.Button(program_group, text="浏览", command=self.browse_program,
                                   bg="#3c3c3c", fg=self.fg_color, relief=tk.FLAT, font=("Arial", 8))
        self.btn_browse.grid(row=0, column=2, padx=3, pady=3)
        
        tk.Label(program_group, text="程序参数:", bg=self.bg_color, fg=self.fg_color, font=("Arial", 9)).grid(row=1, column=0, padx=3, pady=3, sticky=tk.W)
        self.program_args = tk.Entry(program_group, width=28, bg="#2d2d2d", fg=self.fg_color,
                                     insertbackground="white", font=("Arial", 8))
        self.program_args.grid(row=1, column=1, columnspan=2, padx=3, pady=3, sticky=tk.W+tk.E)
        
        # 过滤选项
        filter_group = tk.LabelFrame(left_frame, text="过滤选项",
                                     bg=self.bg_color, fg=self.fg_color,
                                     font=("Arial", 10, "bold"))
        filter_group.pack(fill=tk.X, pady=(0, 5))
        
        self.filter_system = tk.BooleanVar(value=True)
        tk.Checkbutton(filter_group, text="过滤系统进程", variable=self.filter_system,
                      bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                      font=("Arial", 9)).pack(anchor=tk.W, padx=5, pady=2)
        
        self.filter_common = tk.BooleanVar(value=True)
        tk.Checkbutton(filter_group, text="过滤常见系统操作", variable=self.filter_common,
                      bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                      font=("Arial", 9)).pack(anchor=tk.W, padx=5, pady=2)
        
        # 注册表区域选择
        registry_group = tk.LabelFrame(left_frame, text="2. 监控的注册表区域",
                                       bg=self.bg_color, fg=self.fg_color,
                                       font=("Arial", 10, "bold"))
        registry_group.pack(fill=tk.X, pady=(0, 5))
        
        self.registry_vars = {}
        registry_keys = [
            "HKEY_CLASSES_ROOT",
            "HKEY_CURRENT_USER",
            "HKEY_LOCAL_MACHINE",
            "HKEY_USERS",
            "HKEY_CURRENT_CONFIG"
        ]
        
        for i, key in enumerate(registry_keys):
            var = tk.BooleanVar(value=(key == "HKEY_CURRENT_USER" or key == "HKEY_LOCAL_MACHINE"))
            self.registry_vars[key] = var
            cb = tk.Checkbutton(registry_group, text=key, variable=var,
                               bg=self.bg_color, fg=self.fg_color, selectcolor=self.bg_color,
                               font=("Arial", 8))
            cb.grid(row=i, column=0, padx=5, pady=1, sticky=tk.W)
        
        # 控制按钮
        control_group = tk.LabelFrame(left_frame, text="3. 开始监控",
                                      bg=self.bg_color, fg=self.fg_color,
                                      font=("Arial", 10, "bold"))
        control_group.pack(fill=tk.X, pady=(0, 5))
        
        self.btn_step1 = tk.Button(control_group, text="步骤1: 创建监控前快照",
                                   command=self.create_before_snapshot,
                                   bg="#0d7377", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9))
        self.btn_step1.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_step2 = tk.Button(control_group, text="步骤2: 启动程序",
                                   command=self.start_program,
                                   bg="#4caf50", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_step2.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_step3 = tk.Button(control_group, text="步骤3: 对比注册表变化",
                                   command=self.create_after_snapshot,
                                   bg="#ff9800", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_step3.pack(fill=tk.X, padx=5, pady=3)
        
        self.btn_export = tk.Button(control_group, text="导出报告",
                                   command=self.export_report,
                                   bg="#2196f3", fg=self.fg_color, relief=tk.FLAT,
                                   height=1, font=("Arial", 9), state=tk.DISABLED)
        self.btn_export.pack(fill=tk.X, padx=5, pady=3)
        
        # 状态显示
        status_group = tk.LabelFrame(left_frame, text="状态",
                                     bg=self.bg_color, fg=self.fg_color,
                                     font=("Arial", 10, "bold"))
        status_group.pack(fill=tk.X)
        
        self.status_label = tk.Label(status_group, text="就绪",
                                     bg=self.bg_color, fg="#00ff00",
                                     font=("Arial", 9), anchor=tk.W)
        self.status_label.pack(fill=tk.X, padx=5, pady=5)
        
        # 右侧结果显示区域
        right_frame = tk.Frame(main_frame, bg=self.bg_color)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 标签页
        notebook = ttk.Notebook(right_frame)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 变化日志页
        log_frame = ttk.Frame(notebook)
        notebook.add(log_frame, text="目标程序变化")
        
        self.log_text = scrolledtext.ScrolledText(log_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                   font=("Consolas", 9), insertbackground="white")
        self.log_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
        # 配置日志颜色
        self.log_text.tag_config("create", foreground="#6a9955")
        self.log_text.tag_config("modify", foreground="#ce9178")
        self.log_text.tag_config("delete", foreground="#f48771")
        self.log_text.tag_config("info", foreground="#569cd6")
        self.log_text.tag_config("success", foreground="#6a9955")
        self.log_text.tag_config("error", foreground="#f48771")
        self.log_text.tag_config("filtered", foreground="#808080")
        
        # 所有变化页
        all_log_frame = ttk.Frame(notebook)
        notebook.add(all_log_frame, text="所有变化")
        
        self.all_log_text = scrolledtext.ScrolledText(all_log_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                       font=("Consolas", 9), insertbackground="white")
        self.all_log_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
        for tag in ["create", "modify", "delete", "info", "success", "error"]:
            self.all_log_text.tag_config(tag, foreground=self.log_text.tag_cget(tag, "foreground"))
        
        # 统计信息页
        stats_frame = ttk.Frame(notebook)
        notebook.add(stats_frame, text="统计信息")
        
        self.stats_text = scrolledtext.ScrolledText(stats_frame, bg="#1a1a1a", fg="#d4d4d4",
                                                     font=("Consolas", 9), insertbackground="white")
        self.stats_text.pack(fill=tk.BOTH, expand=True, padx=3, pady=3)
        
    def browse_program(self):
        """浏览选择程序"""
        file_path = filedialog.askopenfilename(
            title="选择要监控的程序",
            filetypes=[("可执行文件", "*.exe"), ("所有文件", "*.*")]
        )
        if file_path:
            self.program_path.delete(0, tk.END)
            self.program_path.insert(0, file_path)
            self.selected_program = file_path
            self.target_process_name = os.path.basename(file_path).lower()
            self.log(f"已选择程序: {self.target_process_name}", "info")
   
    def log(self, message: str, tag: str = "info", to_all=True):
        """添加日志"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        
        # 主日志
        self.log_text.insert(tk.END, f"[{timestamp}] ", "info")
        self.log_text.insert(tk.END, f"{message}\n", tag)
        self.log_text.see(tk.END)
        
        # 所有变化日志
        if to_all:
            self.all_log_text.insert(tk.END, f"[{timestamp}] ", "info")
            self.all_log_text.insert(tk.END, f"{message}\n", tag)
            self.all_log_text.see(tk.END)
        
        self.root.update_idletasks()
   
    def log_change(self, change: Dict, is_target: bool = False):
        """记录变化"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        change_type = change['type']
        
        if change_type == 'create':
            tag = "create"
            icon = "➕"
            msg = f"{icon} 新增: {change['key']}\\{change['value']}"
        elif change_type == 'modify':
            tag = "modify"
            icon = "✏️"
            msg = f"{icon} 修改: {change['key']}\\{change['value']}"
        else:
            tag = "delete"
            icon = "❌"
            msg = f"{icon} 删除: {change['key']}\\{change['value']}"
        
        # 始终记录到所有变化日志
        self.all_log_text.insert(tk.END, f"[{timestamp}] ", "info")
        self.all_log_text.insert(tk.END, f"{msg}\n", tag)
        self.all_log_text.see(tk.END)
        
        # 只记录目标程序相关的变化到主日志
        if is_target:
            self.log_text.insert(tk.END, f"[{timestamp}] ", "info")
            self.log_text.insert(tk.END, f"{msg}\n", tag)
            self.log_text.see(tk.END)
        elif not self.filter_system.get():
            self.log_text.insert(tk.END, f"[{timestamp}] ", "filtered")
            self.log_text.insert(tk.END, f"[过滤] {msg}\n", "filtered")
            self.log_text.see(tk.END)
        
        self.root.update_idletasks()
   
    def update_status(self, message: str, color: str = "#00ff00"):
        """更新状态栏"""
        self.status_label.config(text=message, fg=color)
        self.root.update_idletasks()
   
    def is_change_from_target(self, change: Dict) -> bool:
        """判断变化是否来自目标程序"""
        if not self.target_process_name:
            return False
        
        # 检查变化路径是否包含目标程序名
        key_lower = change['key'].lower()
        value_lower = str(change['value']).lower()
        old_val_lower = str(change['old_value']).lower() if change['old_value'] else ""
        new_val_lower = str(change['new_value']).lower() if change['new_value'] else ""
        
        # 检查是否包含目标程序名
        target_name = self.target_process_name.replace('.exe', '')
        if target_name in key_lower:
            return True
        if self.target_process_name in value_lower:
            return True
        if self.target_process_name in old_val_lower:
            return True
        if self.target_process_name in new_val_lower:
            return True
        
        # 检查是否包含目标程序的完整路径
        if self.selected_program and self.selected_program.lower() in key_lower:
            return True
        
        return False
   
    def filter_common_operations(self, changes: List[Dict]) -> List[Dict]:
        """过滤常见系统操作"""
        if not self.filter_common.get():
            return changes
        
        filtered = []
        common_patterns = [
            "\\SessionInfo\\",
            "\\FeatureUsage\\",
            "\\UserAssist\\",
            "\\ActivityDataModel\\",
            "\\bam\\State\\",
            "\\Notifications\\Data",
            "\\DolbySettings\\",
            "\\SystemAppData\\",
            "\\hivelist",
        ]
        
        for change in changes:
            key_lower = change['key'].lower()
            is_common = False
            for pattern in common_patterns:
                if pattern.lower() in key_lower:
                    is_common = True
                    break
            
            if not is_common:
                filtered.append(change)
        
        return filtered
   
    def create_before_snapshot(self):
        """创建监控前的快照"""
        selected_keys = [key for key, var in self.registry_vars.items() if var.get()]
        if not selected_keys:
            messagebox.showwarning("警告", "请至少选择一个注册表区域")
            return
        
        self.log("=" * 50, "info")
        self.log("开始创建监控前的注册表快照...", "info")
        self.update_status("正在创建快照...", "#ffff00")
        
        def scan_thread():
            try:
                snapshot = RegistryScanner.scan_registry(selected_keys, self.log_status)
                self.before_snapshot = snapshot
               
                total_keys = len(snapshot.data)
                total_values = sum(len(values) for values in snapshot.data.values())
               
                self.root.after(0, lambda: self.log(f"✅ 监控前快照创建完成!", "success"))
                self.root.after(0, lambda: self.log(f"   扫描到 {total_keys} 个键, {total_values} 个值", "info"))
                self.root.after(0, lambda: self.update_status("快照创建完成", "#00ff00"))
                self.root.after(0, lambda: self.btn_step2.config(state=tk.NORMAL))
               
            except Exception as e:
                self.root.after(0, lambda: self.log(f"❌ 创建快照失败: {e}", "error"))
                self.root.after(0, lambda: self.update_status("快照创建失败", "#ff0000"))
        
        threading.Thread(target=scan_thread, daemon=True).start()
   
    def log_status(self, message: str):
        """记录扫描状态"""
        self.root.after(0, lambda: self.log(message, "info"))
   
    def start_program(self):
        """启动程序"""
        program = self.program_path.get().strip()
        if not program:
            messagebox.showwarning("警告", "请选择要监控的程序")
            return
        
        if not os.path.exists(program):
            messagebox.showerror("错误", f"程序文件不存在:\n{program}")
            return
        
        args = self.program_args.get().strip()
        
        try:
            self.log("=" * 50, "info")
            self.log(f"正在启动程序: {os.path.basename(program)}", "info")
            
            if args:
                cmd = f'"{program}" {args}'
            else:
                cmd = f'"{program}"'
            
            self.process = subprocess.Popen(cmd, shell=True)
            self.target_process_pid = self.process.pid
            
            self.log(f"程序已启动 (PID: {self.target_process_pid})", "success")
            self.update_status(f"程序运行中 (PID: {self.target_process_pid})", "#00ff00")
            
            self.log("", "info")
            self.log("提示: 操作程序后点击'步骤3'查看变化", "info")
            
            self.btn_step2.config(state=tk.DISABLED)
            self.btn_step3.config(state=tk.NORMAL)
            
        except Exception as e:
            self.log(f"❌ 启动程序失败: {e}", "error")
            self.update_status("程序启动失败", "#ff0000")
   
    def create_after_snapshot(self):
        """创建监控后的快照并对比"""
        selected_keys = [key for key, var in self.registry_vars.items() if var.get()]
        if not selected_keys:
            messagebox.showwarning("警告", "请至少选择一个注册表区域")
            return
        
        self.log("=" * 50, "info")
        self.log("开始创建监控后的注册表快照...", "info")
        self.update_status("正在创建快照...", "#ffff00")
        
        def scan_thread():
            try:
                after_snapshot = RegistryScanner.scan_registry(selected_keys, self.log_status)
               
                self.log("正在对比注册表变化...", "info")
                all_changes = self.before_snapshot.compare(after_snapshot)
               
                # 过滤常见系统操作
                all_changes = self.filter_common_operations(all_changes)
               
                # 分离目标程序的变化
                target_changes = []
                other_changes = []
               
                for change in all_changes:
                    if self.is_change_from_target(change):
                        target_changes.append(change)
                    else:
                        other_changes.append(change)
               
                # 显示结果
                self.root.after(0, lambda: self.display_results(target_changes, other_changes, all_changes))
               
            except Exception as e:
                self.root.after(0, lambda: self.log(f"❌ 对比失败: {e}", "error"))
                self.root.after(0, lambda: self.update_status("对比失败", "#ff0000"))
        
        threading.Thread(target=scan_thread, daemon=True).start()
   
    def display_results(self, target_changes: List[Dict], other_changes: List[Dict], all_changes: List[Dict]):
        """显示结果"""
        # 显示目标程序的变化
        if target_changes:
            create_count = sum(1 for c in target_changes if c['type'] == 'create')
            modify_count = sum(1 for c in target_changes if c['type'] == 'modify')
            delete_count = sum(1 for c in target_changes if c['type'] == 'delete')
            
            self.log("=" * 50, "info")
            self.log(f"🎯 目标程序 ({self.target_process_name}) 变化:", "success")
            self.log(f"   ➕ 新增: {create_count} 项", "create")
            self.log(f"   ✏️ 修改: {modify_count} 项", "modify")
            self.log(f"   ❌ 删除: {delete_count} 项", "delete")
            self.log("=" * 50, "info")
            
            for change in target_changes:
                self.log_change(change, is_target=True)
        else:
            self.log("🎉 未检测到目标程序的注册表变化!", "success")
            self.log("提示: 程序可能没有修改注册表", "info")
        
        # 更新统计
        self.update_stats(target_changes, other_changes, all_changes)
        self.update_status("监控完成", "#00ff00")
        self.btn_export.config(state=tk.NORMAL)
   
    def update_stats(self, target_changes: List[Dict], other_changes: List[Dict], all_changes: List[Dict]):
        """更新统计信息"""
        self.stats_text.delete(1.0, tk.END)
        
        target_create = [c for c in target_changes if c['type'] == 'create']
        target_modify = [c for c in target_changes if c['type'] == 'modify']
        target_delete = [c for c in target_changes if c['type'] == 'delete']
        
        stats = f"""
╔════════════════════════════════════════════════╗
║           注册表监控统计报告                    ║
╚════════════════════════════════════════════════╝

监控时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
监控程序: {os.path.basename(self.program_path.get())}
程序PID: {self.target_process_pid}

┌────────────────────────────────────────────────┐
│              目标程序变化统计                    │
├────────────────────────────────────────────────┤
│ 总计变化数: {len(target_changes)} 项               │
│                                                │
│  ➕ 新增: {len(target_create)} 项                  │
│  ✏️ 修改: {len(target_modify)} 项                  │
│  ❌ 删除: {len(target_delete)} 项                  │
└────────────────────────────────────────────────┘

┌────────────────────────────────────────────────┐
│              所有程序变化统计                    │
├────────────────────────────────────────────────┤
│ 总计变化数: {len(all_changes)} 项                  │
│  ├─ 目标程序: {len(target_changes)} 项              │
│  └─ 其他程序: {len(other_changes)} 项              │
└────────────────────────────────────────────────┘

"""
        
        # 详细变化列表
        if target_changes:
            stats += "\n\n详细变化列表:\n"
            stats += "-" * 50 + "\n"
            
            for i, change in enumerate(target_changes, 1):
                stats += f"\n[{i}] {change['type'].upper()}\n"
                stats += f"    路径: {change['key']}\n"
                stats += f"    值名: {change['value']}\n"
                if change['type'] == 'create':
                    stats += f"    新值: {change['new_value']}\n"
                elif change['type'] == 'modify':
                    stats += f"    原值: {change['old_value']}\n"
                    stats += f"    新值: {change['new_value']}\n"
                else:
                    stats += f"    原值: {change['old_value']}\n"
                stats += f"    类型: {change['value_type']}\n"
        
        self.stats_text.insert(1.0, stats)
   
    def export_report(self):
        """导出报告"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                content = f"""注册表监控报告
生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
监控程序: {self.program_path.get()}
程序参数: {self.program_args.get()}
程序PID: {self.target_process_pid}

{'=' * 70}

【目标程序注册表变化】

{self.log_text.get("1.0", tk.END)}

{'=' * 70}

【所有程序注册表变化(含系统)】

{self.all_log_text.get("1.0", tk.END)}

{'=' * 70}

{self.stats_text.get("1.0", tk.END)}
"""
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
               
                self.log(f"✅ 报告已导出: {file_path}", "success")
                messagebox.showinfo("成功", f"报告已保存到:\n{file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"导出失败: {e}")


def main():
    # 检查管理员权限
    try:
        is_admin = ctypes.windll.shell32.IsUserAnAdmin()
        if not is_admin:
            root = tk.Tk()
            root.withdraw()
            result = messagebox.askyesno(
                "权限提示",
                "建议以管理员身份运行以获得完整的注册表访问权限。\n"
                "是否继续运行?"
            )
            root.destroy()
            if not result:
                return
    except:
        pass
   
    root = tk.Tk()
    app = RegistryMonitorApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
沙发
981930674 发表于 2026-5-8 13:43
3#
大白baymax 发表于 2026-5-8 13:51
好东西,可以监控一个软件是否有病毒,往注册表写入何等东西。
4#
redapple2015 发表于 2026-5-8 13:53
好工具,好想法,好支持
5#
riyuexiaoyao 发表于 2026-5-8 14:08
好工具  大佬可以共享一下Python代码吗
7#
w759003376 发表于 2026-5-8 14:11
建议可以增加,具体是什么程序修改了注册表的哪一项,具体做什么了操作
8#
riyuexiaoyao 发表于 2026-5-8 14:15
situhaonan 发表于 2026-5-8 14:10
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

多谢大佬
9#
CNMDDM 发表于 2026-5-8 14:15
牛啊,太有用了,赞
10#
 楼主| situhaonan 发表于 2026-5-8 14:18 |楼主
w759003376 发表于 2026-5-8 14:11
建议可以增加,具体是什么程序修改了注册表的哪一项,具体做什么了操作

已经是指定程序名称
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-9 10:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表