From cd8463346c6846b795a31417649e122e470bbfe6 Mon Sep 17 00:00:00 2001 From: psycep Date: Thu, 23 Apr 2026 23:37:14 -0500 Subject: [PATCH] relay: re-TreeConnect IPC$ in RemoteRegistry restore After a successful relay samdump/secretsdump the deferred restoreRemoteRegistryState tried to CreatePipe("svcctl") and got STATUS_OBJECT_NAME_NOT_FOUND (0xc0000034). The attack downloads its hives from ADMIN$ before returning, which switches the SMB session's tree away from IPC$, and svcctl lives on IPC$. Fixed by re-TreeConnect'ing to IPC$ at the top of restoreRemoteRegistryState. The function is now tree-state-agnostic and safe to invoke from any defer position without coupling to the attack's tree management. Verified live against GOAD srv02 with RemoteRegistry set to Stopped+Manual and eddard.stark relayed via net use: attack auto-starts the service, dumps SAM hashes, then cleanup stops the service and srv02's final state is Stopped+Manual again (was Running+Manual before this fix). --- pkg/relay/remoteregistry.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/relay/remoteregistry.go b/pkg/relay/remoteregistry.go index 08169e5..c739dc2 100644 --- a/pkg/relay/remoteregistry.go +++ b/pkg/relay/remoteregistry.go @@ -94,11 +94,21 @@ func ensureRemoteRegistryStarted(client *SMBRelayClient) *remoteRegistryState { // it) and re-applies the SERVICE_DISABLED start type (if it was disabled // before we enabled it). Errors are logged but not returned; we're on the // cleanup path after the real work has completed. +// +// The caller's tree state may have moved off IPC$ (e.g., the attack switched +// to ADMIN$ to download a saved hive), so we re-TreeConnect to IPC$ before +// opening svcctl. That makes this function safe to invoke from any defer +// position without coupling it to the attack's tree management. func restoreRemoteRegistryState(client *SMBRelayClient, state *remoteRegistryState) { if state == nil || (!state.startedByUs && !state.wasDisabled) { return } + if err := client.TreeConnect("IPC$"); err != nil { + log.Printf("[-] Warning: could not re-tree-connect to IPC$ for RemoteRegistry restore: %v", err) + return + } + sc, closeFn, err := openSvcctl(client) if err != nil { log.Printf("[-] Warning: could not reopen svcctl to restore RemoteRegistry: %v", err)