Add JSON and HTML writers for reporting Hunter findings

This commit is contained in:
Evan Hosinski
2025-10-10 16:06:48 -04:00
parent 10b1bb7ed6
commit e2015b3df2
9 changed files with 894 additions and 30 deletions
+80
View File
@@ -1 +1,81 @@
package writer
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"rmm-hunter/internal/pkg"
"rmm-hunter/internal/pkg/writer/disposition"
"rmm-hunter/internal/suspicious"
"time"
)
type JSONReport struct {
ReportName string `json:"reportName"`
GeneratedAt string `json:"generatedAt"`
RiskRating *disposition.Disposition `json:"riskRating"`
Findings interface{} `json:"findings"`
}
// WriteJSONReport generates a JSON report from Hunter findings
func WriteJSONReport(sus *suspicious.Suspicious, opts *pkg.RunOptions) error {
if sus == nil {
return fmt.Errorf("suspicious instance is nil")
}
if opts == nil {
opts = &pkg.RunOptions{Name: "rmm-hunter-report"}
}
if opts.Name == "" {
opts.Name = "rmm-hunter-report"
}
// Calculate risk disposition
riskRating := disposition.CalculateDisposition(sus)
// Create report structure
report := JSONReport{
ReportName: opts.Name,
GeneratedAt: time.Now().UTC().Format(time.RFC3339),
RiskRating: riskRating,
Findings: safeFindings(sus),
}
// Marshal to JSON
jsonData, err := json.MarshalIndent(report, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal JSON: %w", err)
}
// Ensure output directory exists
filename := fmt.Sprintf("%s.json", opts.Name)
if err := ensureDir(filepath.Dir(filename)); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
// Write to file
if err := os.WriteFile(filename, jsonData, 0644); err != nil {
return fmt.Errorf("failed to write JSON file: %w", err)
}
fmt.Printf("[+] JSON report written to: %s\n", filename)
return nil
}
// safeFindings ensures all findings are safe for JSON serialization
func safeFindings(sus interface{}) interface{} {
if sus == nil {
return map[string]interface{}{}
}
return sus
}
// ensureDir creates directory if it doesn't exist
func ensureDir(dir string) error {
if dir == "" || dir == "." {
return nil
}
return os.MkdirAll(dir, 0755)
}