inital commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package persistence
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
const registryKey = `SOFTWARE\Microsoft\Windows\CurrentVersion\Run`
|
||||
const registryValueName = "OverlordAgent"
|
||||
|
||||
func getTargetPath() (string, error) {
|
||||
appDataDir := os.Getenv("APPDATA")
|
||||
if appDataDir == "" {
|
||||
return "", fmt.Errorf("APPDATA environment variable not set")
|
||||
}
|
||||
return filepath.Join(appDataDir, "Overlord", "agent.exe"), nil
|
||||
}
|
||||
|
||||
func install(exePath string) error {
|
||||
|
||||
targetPath, err := getTargetPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
overlordDir := filepath.Dir(targetPath)
|
||||
err = os.MkdirAll(overlordDir, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Overlord directory: %w", err)
|
||||
}
|
||||
|
||||
if err := replaceExecutable(exePath, targetPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := registry.OpenKey(registry.CURRENT_USER, registryKey, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open registry key: %w", err)
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
err = k.SetStringValue(registryValueName, targetPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set registry value: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func replaceExecutable(exePath, targetPath string) error {
|
||||
srcFile, err := os.Open(exePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open source executable: %w", err)
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
dir := filepath.Dir(targetPath)
|
||||
tmpFile, err := os.CreateTemp(dir, "agent-*.tmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp executable: %w", err)
|
||||
}
|
||||
tmpPath := tmpFile.Name()
|
||||
defer func() {
|
||||
_ = tmpFile.Close()
|
||||
_ = os.Remove(tmpPath)
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(tmpFile, srcFile); err != nil {
|
||||
return fmt.Errorf("failed to copy executable: %w", err)
|
||||
}
|
||||
if err := tmpFile.Sync(); err != nil {
|
||||
return fmt.Errorf("failed to sync temp file: %w", err)
|
||||
}
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close temp file: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpPath, targetPath); err != nil {
|
||||
if removeErr := os.Remove(targetPath); removeErr == nil {
|
||||
if err = os.Rename(tmpPath, targetPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to replace executable at %s: %w", targetPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func configure(exePath string) error {
|
||||
k, err := registry.OpenKey(registry.CURRENT_USER, registryKey, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open registry key: %w", err)
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
if err := k.SetStringValue(registryValueName, exePath); err != nil {
|
||||
return fmt.Errorf("failed to set registry value: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func uninstall() error {
|
||||
|
||||
k, err := registry.OpenKey(registry.CURRENT_USER, registryKey, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open registry key: %w", err)
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
err = k.DeleteValue(registryValueName)
|
||||
if err != nil && err != registry.ErrNotExist {
|
||||
return fmt.Errorf("failed to delete registry value: %w", err)
|
||||
}
|
||||
|
||||
appDataDir := os.Getenv("APPDATA")
|
||||
if appDataDir != "" {
|
||||
targetPath := filepath.Join(appDataDir, "Overlord", "agent.exe")
|
||||
|
||||
os.Remove(targetPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user