From f06484ed24497878580770f05c15e2c9adeaacc8 Mon Sep 17 00:00:00 2001 From: wuko233 Date: Wed, 8 Apr 2026 09:09:44 +0800 Subject: [PATCH] =?UTF-8?q?[cmd]=20safe=E5=88=9D=E6=AD=A5=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/safe/safe.go | 141 +++++++++++++++++++++++++++++++++++++++++++++++ main.go | 2 + 2 files changed, 143 insertions(+) create mode 100644 cmd/safe/safe.go diff --git a/cmd/safe/safe.go b/cmd/safe/safe.go new file mode 100644 index 0000000..f7744e7 --- /dev/null +++ b/cmd/safe/safe.go @@ -0,0 +1,141 @@ +package safe + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" + "sysmonitord/internal/config" + "sysmonitord/internal/storage" + "sysmonitord/pkg/logger" + "time" + + "github.com/spf13/cobra" + "go.uber.org/zap" +) + +var SafeCmd = &cobra.Command{ + Use: "safe", + Short: "交互式安全确认,将可疑对象加入白名单", + Long: "查看当前的可疑文件和进程列表,并选择将其移入白名单。", + Run: func(cmd *cobra.Command, args []string) { + cfg, err := config.LoadConfig("./config.yaml") + if err != nil { + fmt.Printf("加载配置失败: %v\n", err) + os.Exit(1) + } + + interactiveSafe(cfg) + }, +} + +func interactiveSafe(cfg *config.Config) { + dataDir := cfg.Storage.DataDir + + dubiousFiles, err := readDubiousList(filepath.Join(dataDir, cfg.Storage.DubiousFileListFile)) + if err != nil { + fmt.Printf("无法读取可疑文件列表: %v\n", err) + return + } + if len(dubiousFiles) == 0 { + fmt.Println("没有可疑文件需要处理。") + return + } + + fmt.Println("\n╔══════════════════════════════════════════════╗") + fmt.Println("║ 可疑文件清单 (" + fmt.Sprintf("%d", len(dubiousFiles)) + "个) ║") + fmt.Println("╠══════════════════════════════════════════════╣") + + for i, file := range dubiousFiles { + fmt.Printf("║ %d. %-40s║\n", i+1, file.Path) + fmt.Printf("║ Hash: %-36s║\n", file.Hash[:8]+"...") + } + fmt.Println("╚══════════════════════════════════════════════╝") + + fmt.Println("\n请选择操作:") + fmt.Println("[1] 将以上可疑文件全部确认为安全 (移至白名单)") + // Todo: 支持逐个确认 + fmt.Println("[2] 退出不处理") + fmt.Print("请输入选项 (1-2): ") + + reader := bufio.NewReader(os.Stdin) + input, _ := reader.ReadString('\n') + input = strings.TrimSpace(input) + + switch input { + case "1": + fmt.Println("正在处理...") + if err := confirmFilesAsSafe(cfg, dubiousFiles); err != nil { + fmt.Printf("处理失败: %v\n", err) + } else { + fmt.Println("已将可疑文件移入白名单。") + } + case "2": + fmt.Println("已取消操作。") + default: + fmt.Println("无效选项,已退出。") + } +} + +func readDubiousList(filePath string) ([]storage.DubiousFileInfo, error) { + file, err := os.Open(filePath) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + defer file.Close() + + var list []storage.DubiousFileInfo + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + parts := strings.Split(line, ":") + if len(parts) >= 3 { + list = append(list, storage.DubiousFileInfo{ + Path: parts[0], + Hash: parts[1], + }) + } + } + return list, scanner.Err() +} + +func confirmFilesAsSafe(cfg *config.Config, files []storage.DubiousFileInfo) error { + dataDir := cfg.Storage.DataDir + whiteListPath := filepath.Join(dataDir, cfg.Storage.FileSystemFile) + dubiousFile := filepath.Join(dataDir, cfg.Storage.DubiousFileListFile) + + f, err := os.OpenFile(whiteListPath, os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("无法打开白名单文件: %v", err) + } + defer f.Close() + + writer := bufio.NewWriter(f) + currentTime := time.Now().Format("2006-01-02 15:04:05") + for _, file := range files { + line := fmt.Sprintf("%s:%s:%s\n", file.Path, file.Hash, currentTime) + if _, err := writer.WriteString(line); err != nil { + return fmt.Errorf("写入白名单失败: %v", err) + } + logger.Log.Info("已将可疑文件移入白名单", zap.String("path", file.Path), zap.String("hash", file.Hash)) + } + if err := writer.Flush(); err != nil { + return fmt.Errorf("刷新写入缓冲区失败: %v", err) + } + + // Todo: 逐个删除条目 + + if err := os.Remove(dubiousFile); err != nil && !os.IsNotExist(err) { + return fmt.Errorf("删除可疑文件列表失败: %v", err) + } + + return nil +} diff --git a/main.go b/main.go index b821ab6..9a6c79f 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "os" + "sysmonitord/cmd/safe" "sysmonitord/cmd/start" "sysmonitord/cmd/status" "sysmonitord/cmd/version" @@ -32,6 +33,7 @@ func main() { rootCmd.AddCommand(start.StartCmd) rootCmd.AddCommand(version.VersionCmd) rootCmd.AddCommand(status.StatusCmd) + rootCmd.AddCommand(safe.SafeCmd) if err := rootCmd.Execute(); err != nil { logger.Log.Error("命令执行失败", zap.Error(err))