36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
//go:build windows
|
|
|
|
package source
|
|
|
|
import (
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"github.com/pranshuparmar/witr/pkg/model"
|
|
)
|
|
|
|
func detectWindowsService(ancestry []model.Process) *model.Source {
|
|
// 1. Check for explicit service name in process metadata (prioritize target)
|
|
for i := len(ancestry) - 1; i >= 0; i-- {
|
|
p := ancestry[i]
|
|
if p.Service != "" {
|
|
registryKey := `HKLM\SYSTEM\CurrentControlSet\Services\` + p.Service
|
|
description := resolveWindowsServiceDescription(p.Service)
|
|
|
|
return &model.Source{
|
|
Type: model.SourceWindowsService,
|
|
Name: p.Service,
|
|
Description: description,
|
|
UnitFile: registryKey,
|
|
Details: map[string]string{
|
|
"manager": "services.exe",
|
|
"service": p.Service,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. Fallback: Check if services.exe is in ancestry without explicit service name
|
|
for _, p := range ancestry {
|
|
if strings.ToLower(p.Command) == "services.exe" {
|
|
return &model.Source{
|
|
Type: model.SourceWindowsService,
|
|
Name: "Service Control Manager",
|
|
Details: map[string]string{
|
|
"manager": "services.exe",
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Check for children of services.exe where valid service name wasn't found
|
|
if len(ancestry) >= 2 {
|
|
parent := ancestry[len(ancestry)-2]
|
|
target := ancestry[len(ancestry)-1]
|
|
if strings.ToLower(parent.Command) == "services.exe" {
|
|
name := strings.TrimSuffix(target.Command, ".exe")
|
|
|
|
registryKey := `HKLM\SYSTEM\CurrentControlSet\Services\` + name
|
|
description := resolveWindowsServiceDescription(name)
|
|
|
|
return &model.Source{
|
|
Type: model.SourceWindowsService,
|
|
Name: name,
|
|
Description: description,
|
|
UnitFile: registryKey,
|
|
Details: map[string]string{
|
|
"manager": "services.exe",
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func resolveWindowsServiceDescription(serviceName string) string {
|
|
if _, err := exec.LookPath("sc"); err != nil {
|
|
return ""
|
|
}
|
|
|
|
cmd := exec.Command("sc", "GetDisplayName", serviceName)
|
|
out, _ := cmd.Output()
|
|
|
|
output := string(out)
|
|
if idx := strings.Index(output, "Name = "); idx != -1 {
|
|
return strings.TrimSpace(output[idx+7:])
|
|
}
|
|
|
|
return ""
|
|
}
|