Two compounding bugs in wmiexec / atexec / smbexec / dcomexec made
the output-retrieval loop return early on any command that didn't
finish within the first 100ms poll, leaking the temp file in ADMIN$
/ C$. Issue #22 reports the symptom for wmiexec (systeminfo, ping);
the same broken pattern existed in all four tools.
1. Wrong call site. The polling loop treated a sharing-violation
on smbClient.Cat as the signal "command still running." Cat
opens with FILE_SHARE_READ-compatible access — it succeeds
against the writer on the first poll and returns the file as
it currently exists (typically empty). The conflict actually
lives on Rm: deleting the file requires DELETE access, which
conflicts with the writer's share mode. Moved the sharing-
violation check from Cat to Rm. Matches Impacket's wmiexec.py.
2. Dead string match. The check was
strings.Contains(err.Error(), "STATUS_SHARING_VIOLATION"). The
underlying smb2 library's NtStatus.Error() returns only the
human-readable description ("A file cannot be opened because
the share access flags are incompatible.") — the literal
constant name never appears in err.Error(), so the check could
never fire. Same issue for STATUS_OBJECT_NAME_NOT_FOUND in the
not-found branch (further muddled by smb2/conn.go translating
that NTSTATUS to os.ErrNotExist before wrapping).
Added typed helpers in pkg/smb (IsSharingViolation, IsNotFound)
that unwrap through *os.PathError and match on
*smb2.ResponseError.Code plus the os.ErrNotExist sentinel.
NTSTATUS values are hardcoded since the smb2/internal/erref
package can't be imported from outside the smb2 tree.
The dcomexec "broken / connection reset / use of closed" branch
stays string-matched — those errors come from net, not smb2.
Thanks to @aimogging in #22 for the diagnosis and proof-of-concept
in #29; this change applies the same Cat-vs-Rm insight across all
four exec tools and replaces the err.Error() substring matching
with typed-error helpers so future smb2 library changes don't
silently break the check again.
Verified against GOAD winterfell: wmiexec whoami / systeminfo /
ping -n 4 1.1.1.1 all return full output, exit 0, no ADMIN$
residue, both directly from the operator box and over SOCKS5H
proxy.