commit ab4706bb000a7a1abd288379aeac13e2118b51a0 Author: dvs-dvsxt Date: Fri Aug 28 09:07:05 2026 +0800 Initial commit: Windows Mining Trojan Remover diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adce3c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Python +__pycache__/ +*.py[cod] +*.egg-info/ +dist/ +build/ +.eggs/ +.venv/ +venv/ +env/ + +# Logs (scan logs from the tool) +SysMonitorLogs/ +*.log + +# System files +Thumbs.db +.DS_Store +desktop.ini diff --git a/BOOTICE.exe b/BOOTICE.exe new file mode 100644 index 0000000..8860318 Binary files /dev/null and b/BOOTICE.exe differ diff --git a/BootVerify.exe b/BootVerify.exe new file mode 100644 index 0000000..6e4af75 Binary files /dev/null and b/BootVerify.exe differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fddd2dd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 DVS (dvs-dvsxt) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f094e02 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +# 🛡️ Windows Mining Trojan Remover (WMTR) + +> A one-click **mining trojan removal toolkit** for Windows. Scans, detects, and removes cryptocurrency mining malware, restores registry integrity, and verifies boot-sector persistence. + +**Windows Mining Trojan Remover (WMTR)** is a comprehensive toolkit designed to detect and eliminate mining trojans, remote-control backdoors, and boot-sector persistence on Windows systems. It combines multiple scan engines — file, registry, scheduled tasks, processes, network, and boot verification — into one streamlined workflow. + +> **⚠️ IMPORTANT**: This tool performs privileged system operations (killing processes, deleting files, modifying registry, boot-sector verification). **Run as Administrator or SYSTEM.** Use at your own risk. + +--- + +## ✨ Features + +| Feature | Description | +|---------|-------------| +| 🗂️ **File Scan** | Scans key folders (`ProgramData`, `Public`, `Program Files`, `Temp`) for malicious files | +| 🔑 **Registry Scan** | Detects suspicious startup entries & restores Windows Defender exclusions | +| ⏰ **Scheduled Task Scan** | Detects malicious scheduled tasks (including English-word deception) | +| ⚙️ **Process Scan** | Identifies and kills malicious processes | +| 🌐 **Network Scan** | Flags connections to known mining pools / C2 servers | +| 🔤 **Random-Name Checker** | Detects virus-like random filenames (e.g. `UT7ejTkn`, `5ghAHv`) | +| ♻️ **Post-Restart Compare** | Compares logs after reboot to detect old/new viruses | +| 🧹 **Auto-Cleanup** | Removes autostart when system is confirmed clean | +| 💾 **Scan Logs** | Saves detailed scan & cleanup records to `C:\SysMonitorLogs` | +| 🔒 **Privilege Check** | Verifies ADMIN / NT / SYSTEM privileges before running | + +### Boot Verification (BootVerify) +- 🔎 Verifies **MBR**, **EFI**, and **WMI** persistence for trojan infection +- Uses Python libraries, system tools, and `BOOTICE.exe` + +--- + +## 🚀 Quick Start + +### Prerequisites +- Windows 7 / 8 / 10 / 11 +- **Administrator privileges** (right-click → *Run as administrator*) + +### Run (Compiled EXE) + +```powershell +# Run main cleanup tool (as administrator) +WMTR_MAIN.exe + +# Run system monitor +sys_monitor.exe + +# Run boot verification +BootVerify.exe +``` + +### Run from Source (Python) + +```powershell +# Requires Python 3.x +python code/WMTR.py +python code/sys_monitor.py +python code/BootVerify.py +``` + +--- + +## 📦 Project Structure + +``` +Windows-Mining-Trojan-Remover/ +├── code/ # Python source code +│ ├── WMTR.py # Main mining trojan remover +│ ├── sys_monitor.py # Continuous system monitor +│ ├── BootVerify.py # Boot sector verification +│ └── BOOTICE.exe # Boot sector management tool +├── WMTR_MAIN.exe # Compiled main cleanup tool +├── sys_monitor.exe # Compiled system monitor +├── BootVerify.exe # Compiled boot verification +├── BOOTICE.exe # Boot sector management tool +└── README.md # This document +``` + +--- + +## 🔧 How It Works + +1. **Scan** — Scans files, registry, scheduled tasks, processes, and network for malicious indicators (known mining keywords + dynamic startup-keyword extraction) +2. **Cleanup** — Kills malicious processes, deletes malicious files, restores registry & security software +3. **Autostart** — Sets up `sys_monitor` and `WMTR` autostart to continue monitoring after reboot +4. **Compare** — After restart, compares logs to detect old/new viruses +5. **Auto-remove** — Removes autostart when system is confirmed clean + +### Detection Coverage +- **Mining trojans**: lolMiner, SRBMiner, gminer, miniZ, UT7ejTkn, RuntimeHost, etc. +- **Remote control**: ScreenConnect, ConnectWise, rasedy, Windows VC +- **Mining pools / C2**: kryptex, gleeze, 176.96.137.253, etc. +- **English-word deception**: fake task names like "Efficiently Achieve Analysis", "Windows System Health" + +--- + +## 📄 License + +This project is licensed under the **MIT License**. See [LICENSE](LICENSE) for details. + +--- + +## 🙏 Disclaimer + +> This tool modifies system-critical components (registry, startup, boot sector). **Use at your own risk.** Always back up important data and disable antivirus tamper protection if prompted. The authors are not responsible for any system damage or data loss. diff --git a/WMTR_MAIN.exe b/WMTR_MAIN.exe new file mode 100644 index 0000000..49fafd4 Binary files /dev/null and b/WMTR_MAIN.exe differ diff --git a/code/BOOTICE.exe b/code/BOOTICE.exe new file mode 100644 index 0000000..8860318 Binary files /dev/null and b/code/BOOTICE.exe differ diff --git a/code/BootVerify.py b/code/BootVerify.py new file mode 100644 index 0000000..4e435e5 --- /dev/null +++ b/code/BootVerify.py @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +""" +BootVerify.py - Boot Sector Insurance Verification Script +Verifies MBR, EFI, and WMI persistence for trojan infection +Uses Python libs, system tools, and BOOTICE.exe +""" +import os +import sys +import time +import subprocess +import datetime +import ctypes +import json + +# ============ Configuration ============ +WORK_DIR = r"C:\Windows-Mining-Trojan-Remover" +BOOTICE = os.path.join(WORK_DIR, "BOOTICE.exe") +REPORT_FILE = os.path.join(WORK_DIR, "BootVerify_Report.txt") +MBR_BACKUP = os.path.join(WORK_DIR, "MBR_backup.bin") + +# Suspicious keywords for detection +SUSPICIOUS_KEYWORDS = [ + 'UT7ejTkn', 'WE93mndC', 'WpSJj0lv', 'YRbL1xSX', 'RuntimeHost', 'RuntimeTask', + 'ScreenConnect', 'kryptex', 'gleeze', 'rasedy', 'lolMiner', 'SRBMiner', + 'gminer', 'miniZ', 'Diagnostics.Client', 'SimpleRunPE', 'ccv', 'mzcv', + 'Windows VC', 'proxies-peer', '15AB6CF5', 'B95EB893', '0AzjkAEd', '6E7B6FD3', + 'TfuSTvhb', '5ghAHv', 'jHkYtN', 'zQM241sm', 'nAumBAO1', 'lw5ypO', + 'P41H56Vb', 'KxDQmm', '8B86CBC', '2FA7F989', 'ABE94A11', 'SecurityHealthHost', + 'Efficiently Achieve Analysis', 'productivity Deadlines Priority', + 'Windows System Health', 'Workflow Contingency', 'Elevate Plans Interface', +] + + +def is_admin(): + """Check admin privileges""" + try: + if 'SYSTEM' in os.environ.get('USERNAME', '').upper(): + return True, 'SYSTEM' + return ctypes.windll.shell32.IsUserAnAdmin() != 0, 'ADMIN' + except Exception: + return False, 'UNKNOWN' + + +def now(): + return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + +def run_cmd(cmd, timeout=60): + try: + result = subprocess.run(cmd, shell=True, capture_output=True, + text=True, timeout=timeout, errors='ignore') + return result.stdout + result.stderr + except Exception as e: + return f"ERROR: {e}" + + +def log_write(f, section, content): + f.write(f"\n{'='*60}\n[{section}] - {now()}\n{'='*60}\n") + f.write(content + "\n") + f.flush() + + +# ============ 1. MBR Verification ============ + +def verify_mbr(): + """Verify MBR using BOOTICE""" + results = [] + if not os.path.exists(BOOTICE): + return "BOOTICE not found, cannot verify MBR" + + # Backup MBR + result = run_cmd(f'"{BOOTICE}" /DEVICE=0:0 /mbr /backup /file="{MBR_BACKUP}" /sectors=1 /quiet') + if os.path.exists(MBR_BACKUP): + results.append(f"MBR backup created: {MBR_BACKUP}") + # Read MBR content + try: + with open(MBR_BACKUP, 'rb') as f: + mbr = f.read() + results.append(f"MBR size: {len(mbr)} bytes") + # Check signature (last 2 bytes should be 55 AA) + if len(mbr) >= 2: + sig = mbr[-2:] + if sig == b'\x55\xAA': + results.append("MBR signature: 55 AA (VALID)") + else: + results.append(f"MBR signature: {sig.hex().upper()} (INVALID!)") + # Check partition table type (EE = GPT) + if len(mbr) >= 447: + pt_type = mbr[450] # First partition type at offset 450 + if pt_type == 0xEE: + results.append("Partition table: GPT (EE type)") + elif pt_type == 0x00: + results.append("Partition table: Empty") + else: + results.append(f"Partition table type: 0x{pt_type:02X}") + # Check for suspicious boot code (first 446 bytes) + boot_code = mbr[:446] + if boot_code.count(b'\x00') > 400: + results.append("Boot code: Mostly empty (normal for GPT)") + else: + results.append("Boot code: Present (check for anomalies)") + except Exception as e: + results.append(f"MBR read error: {e}") + else: + results.append("MBR backup FAILED") + + # Get disk info + result2 = run_cmd(f'"{BOOTICE}" /diskinfo /list /file="{WORK_DIR}\\diskinfo.txt" /quiet') + if os.path.exists(os.path.join(WORK_DIR, 'diskinfo.txt')): + with open(os.path.join(WORK_DIR, 'diskinfo.txt'), 'r', encoding='utf-8', errors='ignore') as f: + results.append("Disk info:\n" + f.read()) + + return '\n'.join(results) + + +# ============ 2. EFI Verification ============ + +def verify_efi(): + """Verify EFI boot entries and ESP content""" + results = [] + + # Check BCD boot entries + bcd = run_cmd('bcdedit /enum firmware') + results.append("=== BCD Firmware Boot Entries ===") + results.append(bcd) + + # Check for suspicious boot entries + suspicious_entries = [] + for line in bcd.split('\n'): + if 'description' in line.lower(): + desc = line.split('description')[1].strip() if 'description' in line else '' + # Check for suspicious descriptions + for kw in SUSPICIOUS_KEYWORDS: + if kw.lower() in desc.lower(): + suspicious_entries.append(f"Suspicious boot entry: {desc}") + if suspicious_entries: + results.append("\n=== SUSPICIOUS BOOT ENTRIES ===") + results.extend(suspicious_entries) + else: + results.append("\nNo suspicious boot entries found") + + # Check ESP content + results.append("\n=== EFI System Partition Check ===") + # Try to find ESP and list EFI directory + ps_cmd = r''' + $esp = Get-Partition | Where-Object { $_.Type -eq 'EFI System Partition' } + if ($esp) { + $esp | Format-List DiskNumber,PartitionNumber,DriveLetter,Size + } else { + Write-Output "No ESP found" + } + ''' + import base64 + encoded = base64.b64encode(ps_cmd.encode('utf-16-le')).decode('ascii') + esp_info = run_cmd(f'powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand {encoded}') + results.append(esp_info) + + return '\n'.join(results) + + +# ============ 3. WMI Verification ============ + +def verify_wmi(): + """Verify WMI persistence""" + results = [] + + # Check WMI event filters + filters = run_cmd('wmic /namespace:\\\\root\\subscription path __EventFilter get Name,Query') + results.append("=== WMI Event Filters ===") + results.append(filters) + + # Check WMI event consumers (command line) + consumers = run_cmd('wmic /namespace:\\\\root\\subscription path CommandLineEventConsumer get Name,CommandLineTemplate') + results.append("\n=== WMI Command Line Consumers ===") + results.append(consumers if consumers.strip() else "No command line consumers") + + # Check WMI event consumers (script) + script_consumers = run_cmd('wmic /namespace:\\\\root\\subscription path ActiveScriptEventConsumer get Name,ScriptText') + results.append("\n=== WMI Script Consumers ===") + results.append(script_consumers if script_consumers.strip() else "No script consumers") + + # Check WMI bindings + bindings = run_cmd('wmic /namespace:\\\\root\\subscription path __FilterToConsumerBinding get Filter,Consumer') + results.append("\n=== WMI Filter to Consumer Bindings ===") + results.append(bindings) + + # Analyze for suspicious + all_wmi = filters + consumers + script_consumers + bindings + suspicious = [] + for kw in SUSPICIOUS_KEYWORDS: + if kw.lower() in all_wmi.lower(): + suspicious.append(f"Suspicious WMI: {kw}") + if suspicious: + results.append("\n=== SUSPICIOUS WMI ===") + results.extend(suspicious) + else: + results.append("\nNo suspicious WMI persistence found") + + return '\n'.join(results) + + +# ============ Main ============ + +def main(): + print("=" * 60) + print("BootVerify - Boot Sector Insurance Verification") + print("Verifies MBR, EFI, and WMI persistence") + print("=" * 60) + + # Check admin privileges + admin, priv_type = is_admin() + if not admin: + print("\n[ERROR] Insufficient privileges!") + print("Please run as Administrator or SYSTEM.") + input("Press Enter to exit...") + return + print(f"\n[OK] Running with {priv_type} privileges") + + # Open report file + with open(REPORT_FILE, 'w', encoding='utf-8') as f: + f.write(f"BootVerify Report\nTime: {now()}\n") + f.write(f"System: {os.environ.get('COMPUTERNAME', 'Unknown')}\n") + + # 1. MBR + print("\n[1/3] Verifying MBR...") + mbr_result = verify_mbr() + print(mbr_result) + log_write(f, "1. MBR Verification", mbr_result) + + # 2. EFI + print("\n[2/3] Verifying EFI...") + efi_result = verify_efi() + print(efi_result[:2000]) + log_write(f, "2. EFI Verification", efi_result) + + # 3. WMI + print("\n[3/3] Verifying WMI...") + wmi_result = verify_wmi() + print(wmi_result[:2000]) + log_write(f, "3. WMI Verification", wmi_result) + + f.write(f"\n{'='*60}\nVerification Complete: {now()}\n") + + print(f"\nReport saved: {REPORT_FILE}") + print("\nVerification complete!") + input("Press Enter to exit...") + + +if __name__ == '__main__': + main() diff --git a/code/WMTR.py b/code/WMTR.py new file mode 100644 index 0000000..d57308e --- /dev/null +++ b/code/WMTR.py @@ -0,0 +1,500 @@ +# -*- coding: utf-8 -*- +""" +WMTR.py - Windows Mining Trojan Remover +One-click antivirus script +Features: +1. Scan key folders, startup items, registry (including English-word deception) +2. Delete files + kill processes + restore registry + restore security software +3. Setup autostart (add 2 registry Run entries) +4. Ask to restart, save scan log +5. After restart, auto-compare logs to detect old/new viruses +6. Built-in random-name checker +7. Auto-remove autostart when confirmed clean +8. Check admin/NT/SYSTEM privileges +""" +import os +import sys +import time +import subprocess +import datetime +import shutil +import ctypes + +# ============ Configuration ============ +WORK_DIR = r"C:\Windows-Mining-Trojan-Remover" +LOG_DIR = r"C:\SysMonitorLogs" +INITIAL_LOG = os.path.join(LOG_DIR, "WMTR_initial_scan.log") +COMPARE_LOG = os.path.join(LOG_DIR, "WMTR_compare.log") +SYSMONITOR_EXE = os.path.join(WORK_DIR, "sys_monitor.exe") +WMTR_EXE = os.path.join(WORK_DIR, "WMTR.exe") + +# Known malicious keywords (including English-word deception) +MALICIOUS_KEYWORDS = [ + # Mining trojans + 'UT7ejTkn', 'WE93mndC', 'WpSJj0lv', 'YRbL1xSX', 'RuntimeHost', 'RuntimeTask', + '8B86CBC', '2FA7F989', 'ABE94A11', '15205438', 'D3F4E2A1', '50AB775E', + 'proxies-peer', '15AB6CF5', 'B95EB893', '5ghAHv', 'jHkYtN', 'zQM241sm', + 'nAumBAO1', 'lw5ypO', 'P41H56Vb', 'WE93mndC', 'KxDQmm', 'ccv', 'mzcv', + 'lolMiner', 'SRBMiner', 'gminer', 'miniZ', 'SecurityHealthHost', + '0AzjkAEd', '6E7B6FD3', 'Diagnostics.Client', 'SimpleRunPE', + # Remote control + 'ScreenConnect', 'Windows VC', 'rasedy', 'ConnectWise', + # Mining pools / C2 + 'kryptex', 'gleeze', '176.96.137.253', '217.216.109.4', + # English-word deception (fake normal English task names) + 'Efficiently Achieve Analysis', 'productivity Deadlines Priority', + 'Windows System Health', 'Workflow Contingency', 'Elevate Plans Interface', +] + + +def is_admin(): + """Check if running with admin/NT/SYSTEM privileges""" + try: + # Check if SYSTEM + if 'SYSTEM' in os.environ.get('USERNAME', '').upper(): + return True, 'SYSTEM' + # Check if admin + return ctypes.windll.shell32.IsUserAnAdmin() != 0, 'ADMIN' + except Exception: + return False, 'UNKNOWN' + + +def is_random_name(name): + """Check if name looks like a virus random name (e.g. 5ghAHv, UT7ejTkn)""" + base = os.path.splitext(name)[0] + if len(base) < 6 or len(base) > 12: + return False + has_upper = any(c.isupper() for c in base) + has_lower = any(c.islower() for c in base) + has_digit = any(c.isdigit() for c in base) + if has_upper and has_lower and has_digit: + vowels = 'aeiouAEIOU' + vowel_count = sum(1 for c in base if c in vowels) + if vowel_count / len(base) < 0.25: + return True + return False + + +def now(): + return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + +def run_cmd(cmd, timeout=30): + try: + result = subprocess.run(cmd, shell=True, capture_output=True, + text=True, timeout=timeout, errors='ignore') + return result.stdout + result.stderr + except Exception as e: + return f"ERROR: {e}" + + +def log_write(f, section, content): + f.write(f"\n{'='*60}\n[{section}] - {now()}\n{'='*60}\n") + f.write(content + "\n") + f.flush() + + +# ============ 1. Scan Phase ============ + +# 动态关键词:从启动项提取文件名并添加到关键词列表 +def extract_startup_keywords(): + """Scan startup items, extract file names, dynamically add to keywords""" + added = [] + keys = [ + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', + r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce', + ] + for k in keys: + out = run_cmd(f'reg query "{k}"') + # 提取所有 exe/dll 文件名 + for line in out.split('\n'): + # 提取路径中的文件名 + import re as _re + exes = _re.findall(r'[\\/]([A-Za-z0-9_]+\.(?:exe|dll|bat|cmd|ps1))', line, _re.IGNORECASE) + for exe in exes: + base = os.path.splitext(exe)[0] + if base.lower() not in [k.lower() for k in MALICIOUS_KEYWORDS]: + # 只添加看起来可疑的(随机名或不在系统正常程序中的) + if is_random_name(exe) or base.lower() not in ['securityhealth', 'awe sun', 'onedrive', 'thunder', 'palminput', 'wujie', 'msedge']: + MALICIOUS_KEYWORDS.append(base) + added.append(f"Dynamic keyword added: {base}") + return '\n'.join(added) if added else "No new dynamic keywords" + + + + +def scan_files(): + """Scan key folders for malicious files""" + results = [] + base_dirs = [ + r'C:\ProgramData', + r'C:\Users\Public', + r'C:\Program Files (x86)', + r'C:\Program Files', + r'C:\Windows\Temp', + ] + for base in base_dirs: + if not os.path.exists(base): + continue + try: + for root, dirs, files in os.walk(base): + depth = root[len(base):].count(os.sep) + if depth > 4: + dirs[:] = [] + continue + for item in dirs + files: + full = os.path.join(root, item) + if any(k.lower() in (item + full).lower() for k in MALICIOUS_KEYWORDS): + results.append(f"MALICIOUS: {full}") + elif is_random_name(item) and item.lower().endswith(('.exe', '.dll', '.dat', '.tmp')): + results.append(f"RANDOM-NAME: {full}") + except Exception: + pass + return '\n'.join(results) if results else "No malicious files found" + + +def scan_registry(): + """Scan registry startup items, dynamically add found paths to keywords""" + results = [] + keys = [ + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', + r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce', + ] + for k in keys: + out = run_cmd(f'reg query "{k}"') + if any(m.lower() in out.lower() for m in MALICIOUS_KEYWORDS): + results.append(f"REGISTRY SUSPICIOUS [{k}]: {out}") + # Dynamically extract file names from startup paths + import re as _re + for line in out.split('\n'): + exes = _re.findall(r'[\\/]([A-Za-z0-9_]+\.(?:exe|dll|bat|cmd|ps1))', line, _re.IGNORECASE) + for exe in exes: + base = os.path.splitext(exe)[0] + if is_random_name(exe) and base.lower() not in [k.lower() for k in MALICIOUS_KEYWORDS]: + MALICIOUS_KEYWORDS.append(base) + results.append(f"DYNAMIC keyword from startup: {base}") + return '\n'.join(results) if results else "Registry startup items clean" + + +def scan_tasks(): + """Scan scheduled tasks (including English-word deception)""" + results = [] + tasks_dir = r'C:\Windows\System32\Tasks' + if os.path.exists(tasks_dir): + for root, dirs, files in os.walk(tasks_dir): + for f in files: + full = os.path.join(root, f) + try: + with open(full, 'r', encoding='utf-8', errors='ignore') as fh: + content = fh.read() + if any(k.lower() in content.lower() for k in MALICIOUS_KEYWORDS): + results.append(f"TASK SUSPICIOUS: {full}") + except Exception: + pass + return '\n'.join(results) if results else "Scheduled tasks clean" + + +def scan_processes(): + """Scan running malicious processes""" + results = [] + out = run_cmd('wmic process get name,processid,executablepath /format:csv') + for line in out.split('\n'): + if any(k.lower() in line.lower() for k in MALICIOUS_KEYWORDS): + results.append(f"PROCESS SUSPICIOUS: {line.strip()}") + return '\n'.join(results) if results else "No malicious processes" + + +def scan_network(): + """Scan malicious network connections""" + results = [] + out = run_cmd('netstat -ano') + for line in out.split('\n'): + if any(p in line for p in ['kryptex', 'gleeze', 'rasedy', '176.96.137.253', '217.216.109.4', ':4041', ':8041', ':8443']): + results.append(f"NETWORK SUSPICIOUS: {line.strip()}") + return '\n'.join(results) if results else "No malicious network connections" + + +# ============ 2. Cleanup Phase ============ + +def kill_processes(): + """Kill malicious processes""" + procs = ['UT7ejTkn', 'WE93mndC', 'WpSJj0lv', 'YRbL1xSX', 'RuntimeHost', + 'RuntimeTask', 'ScreenConnect', 'lolMiner', 'SRBMiner', 'gminer', + 'miniZ', 'lw5ypO', 'P41H56Vb', 'KxDQmm', 'ccv', 'mzcv'] + killed = [] + for p in procs: + result = run_cmd(f'taskkill /F /IM {p}.exe 2>nul') + if 'SUCCESS' in result.upper() or '成功' in result: + killed.append(f"{p}.exe") + return '\n'.join(killed) if killed else "No malicious processes to kill" + + +def delete_files(): + """Delete malicious files""" + deleted = [] + mal_dirs = [ + r'C:\ProgramData\UT7ejTkn.exe', + r'C:\ProgramData\TfuSTvhb', + r'C:\ProgramData\0AzjkAEd', + r'C:\ProgramData\6E7B6FD3', + r'C:\ProgramData\proxies-peer', + r'C:\ProgramData\15AB6CF5', + r'C:\ProgramData\B95EB893', + r'C:\Program Files (x86)\Windows VC', + r'C:\Program Files (x86)\Common Files\Microsoft Shared\2FA7F989', + ] + for d in mal_dirs: + if os.path.exists(d): + try: + if os.path.isfile(d): + os.remove(d) + else: + shutil.rmtree(d, ignore_errors=True) + deleted.append(f"Deleted: {d}") + except Exception as e: + deleted.append(f"Delete failed: {d} | {e}") + return '\n'.join(deleted) if deleted else "No malicious files to delete" + + +def restore_registry(): + """Restore registry (remove malicious exclusions and startup items)""" + restored = [] + cmds = [ + 'reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Paths" /f', + 'reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Processes" /f', + 'reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Extensions" /f', + 'reg delete "HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows Defender\\Exclusions" /f', + 'schtasks /delete /tn "Efficiently Achieve Analysis Your" /f', + 'schtasks /delete /tn "productivity Deadlines Priority" /f', + 'schtasks /delete /tn "Windows System Health" /f', + 'schtasks /delete /tn "Workflow Contingency Delegation With Maximum" /f', + 'schtasks /delete /tn "Elevate Plans Interface productivity Organize" /f', + ] + for cmd in cmds: + run_cmd(cmd) + restored.append(cmd) + return '\n'.join(restored) + + +def restore_security(): + """Restore security software (prompt user to disable protection, wait 15s)""" + print("[Security Restore] Please manually disable 'Tamper Protection' in Windows Security") + print("[Security Restore] Waiting 15 seconds...") + time.sleep(15) + out = run_cmd('powershell -NoProfile -Command "$s = Get-MpComputerStatus -ErrorAction SilentlyContinue; Write-Output $s.IsTamperProtected"') + if 'False' in out: + return "Tamper Protection disabled, cleanup can proceed" + else: + return "Tamper Protection still enabled, some operations may be limited" + + +# ============ 3. Autostart Setup ============ + +def setup_autostart(): + """Setup sys_monitor and WMTR autostart (add 2 registry Run entries each)""" + added = [] + if os.path.exists(SYSMONITOR_EXE): + run_cmd(f'reg add "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" /v "SysMonitor" /t REG_SZ /d "{SYSMONITOR_EXE}" /f') + run_cmd(f'reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "SysMonitor" /t REG_SZ /d "{SYSMONITOR_EXE}" /f') + added.append("Added SysMonitor to HKLM/HKCU Run") + if os.path.exists(WMTR_EXE): + run_cmd(f'reg add "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" /v "WMTR" /t REG_SZ /d "{WMTR_EXE}" /f') + run_cmd(f'reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "WMTR" /t REG_SZ /d "{WMTR_EXE}" /f') + added.append("Added WMTR to HKLM/HKCU Run") + return '\n'.join(added) if added else "Autostart setup complete" + + +def remove_autostart(): + """Remove autostart for both exe when confirmed clean""" + removed = [] + run_cmd('reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" /v "SysMonitor" /f') + run_cmd('reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "SysMonitor" /f') + run_cmd('reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" /v "WMTR" /f') + run_cmd('reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "WMTR" /f') + removed.append("Removed SysMonitor and WMTR autostart from registry") + return '\n'.join(removed) + + +# ============ 4. Log Saving ============ + +def save_initial_log(): + """Save initial scan record""" + with open(INITIAL_LOG, 'w', encoding='utf-8') as f: + f.write(f"WMTR Initial Scan Record\nTime: {now()}\n") + log_write(f, "1. Malicious File Scan", scan_files()) + log_write(f, "2. Registry Startup Items", scan_registry()) + log_write(f, "3. Scheduled Tasks", scan_tasks()) + log_write(f, "4. Malicious Processes", scan_processes()) + log_write(f, "5. Malicious Network", scan_network()) + log_write(f, "6. Killed Processes", kill_processes()) + log_write(f, "7. Deleted Files", delete_files()) + log_write(f, "8. Registry Restore", restore_registry()) + log_write(f, "9. Security Restore", restore_security()) + return INITIAL_LOG + + +# ============ 5. Post-restart Compare ============ + +def compare_logs(): + """Compare logs after restart to detect old/new viruses""" + results = [] + if not os.path.exists(LOG_DIR): + return "Log directory does not exist" + logs = [f for f in os.listdir(LOG_DIR) if f.startswith('continuous_monitor_')] + if not logs: + return "No monitor logs found" + latest = max(logs, key=lambda f: (os.path.getmtime(os.path.join(LOG_DIR, f)), os.path.getsize(os.path.join(LOG_DIR, f)))) + latest_path = os.path.join(LOG_DIR, latest) + with open(latest_path, 'r', encoding='utf-8') as f: + latest_content = f.read() + + old_viruses = [] + if os.path.exists(INITIAL_LOG): + with open(INITIAL_LOG, 'r', encoding='utf-8') as f: + old_content = f.read() + for kw in MALICIOUS_KEYWORDS: + if kw in old_content: + old_viruses.append(kw) + + old_still_present = [] + old_cleared = [] + for v in old_viruses: + if v in latest_content: + old_still_present.append(v) + else: + old_cleared.append(v) + + results.append("=== OLD VIRUS COMPARISON ===") + results.append(f"Cleared: {', '.join(old_cleared) if old_cleared else 'None'}") + results.append(f"Still present: {', '.join(old_still_present) if old_still_present else 'None'}") + + new_viruses = [] + for kw in MALICIOUS_KEYWORDS: + if kw in latest_content and kw not in old_viruses: + new_viruses.append(kw) + + results.append("\n=== NEW VIRUS DETECTION ===") + results.append(f"New found: {', '.join(new_viruses) if new_viruses else 'None'}") + + return '\n'.join(results) + + +# ============ 6. Random Name Checker ============ + +def random_name_checker(): + """Built-in random-name checker""" + results = [] + scan_dirs = [r'C:\ProgramData', r'C:\Users\Public', r'C:\Windows\Temp'] + for base in scan_dirs: + if not os.path.exists(base): + continue + for root, dirs, files in os.walk(base): + for item in dirs + files: + if is_random_name(item): + results.append(f"Random name: {os.path.join(root, item)}") + return '\n'.join(results) if results else "No random-named files found" + + +# ============ Main Flow ============ + +def main(): + print("=" * 60) + print("WMTR - Windows Mining Trojan Remover") + print("One-click antivirus script") + print("=" * 60) + + # Check admin privileges + admin, priv_type = is_admin() + if not admin: + print("\n[ERROR] Insufficient privileges!") + print("Please run this program as Administrator or SYSTEM.") + print("Right-click the exe and select 'Run as administrator'.") + input("Press Enter to exit...") + return + print(f"\n[OK] Running with {priv_type} privileges") + + # Check if post-restart mode + restart_marker = os.path.join(WORK_DIR, "restart_marker.txt") + if os.path.exists(restart_marker): + print("\n[Post-restart Mode] Restart marker detected, comparing logs...") + os.remove(restart_marker) + result = compare_logs() + print(result) + + # If clean, remove autostart + if "Still present: None" in result and "New found: None" in result: + print("\n[OK] System confirmed clean!") + print("[OK] Removing autostart for both exe...") + print(remove_autostart()) + print("[OK] Autostart removed. Antivirus tools will not auto-start.") + else: + print("\n[WARNING] Viruses still detected or new viruses found!") + print("Please run the cleanup again.") + + with open(COMPARE_LOG, 'w', encoding='utf-8') as f: + f.write(f"WMTR Post-restart Compare\nTime: {now()}\n{result}\n") + print(f"\nCompare result saved: {COMPARE_LOG}") + input("Press Enter to exit...") + return + + # First run mode + # Step 0: Scan startup items FIRST to dynamically add keywords + print("\n[0/8] Scanning startup items (dynamic keyword extraction)...") + dyn = extract_startup_keywords() + print(dyn) + print(scan_registry()) + + print("\n[1/8] Scanning malicious files...") + print(scan_files()) + print("\n[2/8] Scanning scheduled tasks...") + print(scan_tasks()) + print("\n[3/8] Scanning malicious processes...") + print(scan_processes()) + print("\n[4/8] Killing malicious processes...") + print(kill_processes()) + print("\n[5/8] Deleting malicious files...") + print(delete_files()) + print("\n[6/8] Restoring registry + security software...") + print(restore_registry()) + print(restore_security()) + + # Setup autostart + print("\n[7/8] Setting up autostart...") + print(setup_autostart()) + + # Save initial log + print("\n[8/8] Saving initial scan record...") + + # Save initial log + print("\nSaving initial scan record...") + log_file = save_initial_log() + print(f"Log saved: {log_file}") + + # Random name check + print("\nRandom name checker...") + print(random_name_checker()) + + # Ask to restart + print("\n" + "=" * 60) + choice = input("Restart now? (y/n): ").strip().lower() + if choice == 'y': + with open(restart_marker, 'w') as f: + f.write(now()) + print("Restarting...") + run_cmd('shutdown /r /t 5') + else: + print("Not restarting. Please restart manually to complete comparison.") + + +if __name__ == '__main__': + main() diff --git a/code/sys_monitor.py b/code/sys_monitor.py new file mode 100644 index 0000000..610eda6 --- /dev/null +++ b/code/sys_monitor.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +""" +持续系统安全监控程序 v2 +从启动开始持续监控系统,直到 C:\f.ini 被删除 或 运行满 3 分钟 +监控服务、计划任务、自启动、进程、文件、网络、Windows安全中心等 +""" +import os +import sys +import time +import subprocess +import datetime +import socket +import platform + +# 结束条件文件 +STOP_FILE = r"C:\f.ini" +# 最大运行时间(秒) +MAX_RUNTIME = 180 # 3 分钟 + +# 日志目录 +LOG_DIR = r"C:\SysMonitorLogs" +os.makedirs(LOG_DIR, exist_ok=True) + +# 已知恶意关键词 +MALICIOUS_KEYWORDS = [ + 'TfuSTvhb', 'YRbL1xSX', 'WpSJj0lv', 'RuntimeHost', 'RuntimeTask', + '8B86CBC', '2FA7F989', 'ABE94A11', '15205438', 'D3F4E2A1', '50AB775E', + 'proxies-peer', '15AB6CF5', 'B95EB893', '5ghAHv', 'jHkYtN', 'zQM241sm', + 'nAumBAO1', 'lw5ypO', 'P41H56Vb', 'WE93mndC', 'KxDQmm', 'ccv', 'mzcv', + 'lolMiner', 'SRBMiner', 'gminer', 'miniZ', 'SecurityHealthHost', + '0AzjkAEd', '6E7B6FD3', 'UT7ejTkn', 'ScreenConnect', 'Windows VC', + 'rasedy', 'Elevate Plans Interface', 'Windows System Health', + 'Workflow Contingency', 'Diagnostics.Client', 'SimpleRunPE' +] + +# 挖矿矿池 +MINING_POOLS = ['kryptex', '176.96.137.253', '217.216.109.4', '4041', 'rasedy.com', 'gleeze'] + + +def now(): + return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + +def run_cmd(cmd, timeout=30): + try: + result = subprocess.run(cmd, shell=True, capture_output=True, + text=True, timeout=timeout, errors='ignore') + return result.stdout + result.stderr + except Exception as e: + return f"ERROR: {e}" + + +def log_write(f, section, content): + f.write(f"\n{'='*60}\n[{section}] - {now()}\n{'='*60}\n") + f.write(content + "\n") + f.flush() + + +def collect_services(): + out = run_cmd('wmic service get name,displayname,state,startmode,pathname /format:csv') + lines = [l for l in out.split('\n') if l.strip() and 'Node' not in l] + result = [] + for l in lines[1:]: + parts = l.strip().split(',') + if len(parts) >= 6: + name = parts[1].strip() + state = parts[2].strip() + start = parts[3].strip() + path = parts[5].strip() if len(parts) > 5 else '' + flag = ' <<< 可疑' if any(k.lower() in (name + path).lower() for k in MALICIOUS_KEYWORDS) else '' + result.append(f"[{state}] {name} | Start={start} | {path}{flag}") + return '\n'.join(result) + + +def collect_tasks(): + out = run_cmd('schtasks /query /fo csv /v') + lines = [l for l in out.split('\n') if l.strip()] + result = [] + for l in lines: + flag = ' <<< 可疑' if any(k.lower() in l.lower() for k in MALICIOUS_KEYWORDS) else '' + result.append(l.strip() + flag) + return '\n'.join(result) + + +def collect_registry_run(): + result = [] + keys = [ + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', + r'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', + r'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run', + r'HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', + ] + for k in keys: + out = run_cmd(f'reg query "{k}"') + flag = ' <<< 可疑' if any(m.lower() in out.lower() for m in MALICIOUS_KEYWORDS) else '' + result.append(f"--- {k} ---{flag}\n{out}") + return '\n'.join(result) + + +def collect_startup_folders(): + result = [] + folders = [ + r'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup', + os.path.join(os.environ.get('APPDATA', ''), r'Microsoft\Windows\Start Menu\Programs\Startup'), + ] + for f in folders: + if os.path.exists(f): + files = os.listdir(f) + result.append(f"--- {f} ---\n" + '\n'.join(files)) + return '\n'.join(result) + + +def collect_processes(): + out = run_cmd('wmic process get name,processid,parentprocessid,executablepath /format:csv') + lines = [l for l in out.split('\n') if l.strip() and 'Node' not in l] + result = [] + for l in lines[1:]: + parts = l.strip().split(',') + if len(parts) >= 5: + name = parts[1].strip() + pid = parts[2].strip() + ppid = parts[3].strip() + path = parts[4].strip() + flag = ' <<< 可疑' if any(k.lower() in (name + path).lower() for k in MALICIOUS_KEYWORDS) else '' + if flag or name in ['RuntimeHost.exe', 'RuntimeTask.exe', 'SecurityHealthHost.exe', + 'ScreenConnect.ClientService.exe', 'ScreenConnect.WindowsClient.exe']: + result.append(f"[{pid}] {name} | PPID={ppid} | {path}{flag}") + return '\n'.join(result) + + +def collect_suspicious_files(): + result = [] + base_dirs = [ + r'C:\ProgramData', + r'C:\Users\Public', + r'C:\Program Files (x86)', + r'C:\ProgramData\Microsoft\Windows\Caches', + ] + for base in base_dirs: + if not os.path.exists(base): + continue + try: + for root, dirs, files in os.walk(base): + depth = root[len(base):].count(os.sep) + if depth > 3: + dirs[:] = [] + continue + for item in dirs + files: + full = os.path.join(root, item) + if any(k.lower() in (item + full).lower() for k in MALICIOUS_KEYWORDS): + result.append(f"可疑: {full}") + except Exception: + pass + return '\n'.join(result) if result else "未发现已知恶意文件" + + +def collect_network(): + out = run_cmd('netstat -ano') + result = [] + for l in out.split('\n'): + if any(p in l for p in MINING_POOLS): + result.append(l.strip()) + return '\n'.join(result) if result else "未发现可疑网络连接" + + +def collect_defender_full(): + """Windows 安全中心完整检测""" + result = [] + # 1. Defender 服务状态 + for svc in ['WinDefend', 'SecurityHealthService', 'wscsvc', 'MDCoreSvc', 'WdNisSvc']: + out = run_cmd(f'sc query {svc}') + state = 'RUNNING' if 'RUNNING' in out else 'STOPPED' + result.append(f"{svc}: {state}") + + # 2. Defender 引擎状态 + out = run_cmd('powershell -NoProfile -Command "$s = Get-MpComputerStatus -ErrorAction SilentlyContinue; if ($s) { Write-Output (\'AV: \' + $s.AntivirusEnabled); Write-Output (\'RTP: \' + $s.RealTimeProtectionEnabled); Write-Output (\'SigVer: \' + $s.AntivirusSignatureVersion); Write-Output (\'EngineVer: \' + $s.AMEngineVersion); Write-Output (\'Tamper: \' + $s.IsTamperProtected); Write-Output (\'FullScanEnd: \' + $s.FullScanEndTime); Write-Output (\'QuickScanEnd: \' + $s.QuickScanEndTime) } else { Write-Output \'无法获取Defender状态\' }"') + result.append("--- Defender 引擎状态 ---") + result.append(out) + + # 3. Defender 排除项检测 + result.append("--- Defender 排除项 ---") + out2 = run_cmd('powershell -NoProfile -Command "$p = Get-MpPreference -ErrorAction SilentlyContinue; Write-Output (\'Path: \' + ($p.ExclusionPath -join \', \')); Write-Output (\'Process: \' + ($p.ExclusionProcess -join \', \')); Write-Output (\'Extension: \' + ($p.ExclusionExtension -join \', \'))"') + flag = ' <<< 可疑排除项' if any(k.lower() in out2.lower() for k in MALICIOUS_KEYWORDS) else '' + result.append(out2 + flag) + + # 4. Defender 筛选器驱动 + result.append("--- Defender 驱动 ---") + out3 = run_cmd('driverquery /v /fo csv 2>nul | findstr /i "WdFilter WdBoot WdNisDrv MsSecFlt"') + result.append(out3) + + # 5. 最近引擎崩溃事件 + result.append("--- 最近引擎崩溃事件 ---") + out4 = run_cmd('powershell -NoProfile -Command "Get-WinEvent -LogName \'Microsoft-Windows-Windows Defender/Operational\' -MaxEvents 10 -ErrorAction SilentlyContinue | Where-Object {$_.Id -eq 5008 -or $_.Id -eq 3002} | ForEach-Object { Write-Output ($_.TimeCreated.ToString() + \' | ID=\' + $_.Id + \' | \' + $_.Message.Substring(0, [Math]::Min(100, $_.Message.Length))) }"') + result.append(out4 if out4.strip() else "无引擎崩溃事件") + + # 6. WDAC 策略检查 + result.append("--- WDAC 策略 ---") + if os.path.exists(r'C:\Windows\System32\CodeIntegrity\SiPolicy.p7b'): + result.append("SiPolicy.p7b 存在 (可疑)") + else: + result.append("SiPolicy.p7b 已删除 (正常)") + + return '\n'.join(result) + + +def collect_lsa_authpackages(): + out = run_cmd('reg query "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa" /v "Authentication Packages"') + flag = ' <<< 可疑' if any(k.lower() in out.lower() for k in MALICIOUS_KEYWORDS) else '' + return out + flag + + +def collect_services_registry(): + out = run_cmd('wmic service get name,pathname /format:csv') + result = [] + for l in out.split('\n'): + if any(k.lower() in l.lower() for k in MALICIOUS_KEYWORDS): + result.append(l.strip()) + return '\n'.join(result) if result else "服务注册表中未发现可疑路径" + + +def snapshot(f, round_num, elapsed): + log_write(f, f"快照 #{round_num} (运行 {elapsed:.0f} 秒)", "") + log_write(f, "1. 所有系统服务", collect_services()) + log_write(f, "2. 所有计划任务", collect_tasks()) + log_write(f, "3. 注册表自启动项", collect_registry_run()) + log_write(f, "4. 启动文件夹", collect_startup_folders()) + log_write(f, "5. 可疑进程", collect_processes()) + log_write(f, "6. 可疑文件扫描", collect_suspicious_files()) + log_write(f, "7. 网络连接", collect_network()) + log_write(f, "8. Windows安全中心完整检测", collect_defender_full()) + log_write(f, "9. LSA认证包", collect_lsa_authpackages()) + log_write(f, "10. 服务注册表可疑路径", collect_services_registry()) + + +def main(): + start_time = time.time() + log_file = os.path.join(LOG_DIR, f'continuous_monitor_{datetime.datetime.now().strftime("%Y%m%d_%H%M%S")}.log') + + with open(log_file, 'w', encoding='utf-8') as f: + f.write(f"持续系统安全监控日志 v2\n开始时间: {now()}\n") + f.write(f"主机名: {socket.gethostname()}\n") + f.write(f"系统: {platform.platform()}\n") + f.write(f"停止条件: {STOP_FILE} 被删除 或 运行 {MAX_RUNTIME} 秒\n") + f.write(f"采样间隔: 5 秒\n") + f.flush() + + round_num = 0 + while True: + elapsed = time.time() - start_time + + stop_reason = None + if not os.path.exists(STOP_FILE): + stop_reason = f"停止文件 {STOP_FILE} 已被删除" + elif elapsed >= MAX_RUNTIME: + stop_reason = f"运行时间达到 {MAX_RUNTIME} 秒" + + round_num += 1 + snapshot(f, round_num, elapsed) + + if stop_reason: + log_write(f, "停止", f"停止原因: {stop_reason}") + break + + time.sleep(5) + + f.write(f"\n{'='*60}\n监控结束: {now()}\n总采样次数: {round_num}\n") + + print(f"监控日志已写入: {log_file}") + + +if __name__ == '__main__': + main() diff --git a/sys_monitor.exe b/sys_monitor.exe new file mode 100644 index 0000000..85fe5a1 Binary files /dev/null and b/sys_monitor.exe differ