RunasCs
So one time I found my runas command wasn't working and I couldn't authenticate to the domain. I found some articles indicating that AD passwords ending with % might have problems when using them from domain-joined machines. So I found the fix was to run RunasCs to run the command I was hoping to run in a runas context.
Running with a Snaffler job as an example:
RunasCs\RunasCs.exe low-priv "Summer2026%" "snaffler.exe -s -d domain.com -c 10.10.7.7 -o c:\tools\snaffy.json -m c:\tools\snaffdump -t JSON" -d domain.com -l 9 -t 0
[+] Running in session 2 with process function CreateProcessWithTokenW()
[+] Using Station\Desktop: WinSta0\Default
[+] Async process 'snaffler.exe....blah blah blah' with pid 2504 created in background.
Context:
-l 9 — netonly logon type, same semantics as runas /netonly. Required since you're on a non-domain-joined box.
-t 0 — background mode, no output capture. You want this because RunasCs defaults to a 120-second timeout and then kills the child. Snaffler on any real environment runs for tens of minutes to hours, so without -t 0 it'll get whacked mid-collection. Snaffler is writing to snaffy.json anyway, so you don't need RunasCs to tee stdout.
Absolute path for -o — when RunasCs spawns the process, the working directory of the new process isn't guaranteed to be your current cwd. If you use a relative path like snaffy.json, the output may end up in C:\Windows\System32 or wherever the spawned context lands. Always pin it with a full path.
Password quoting — "password%" in cmd is fine. cmd only expands %VAR% pairs; a trailing lone % with nothing after it is left alone. Don't double it here (that was the PingCastle case where the password went through cmd's argv parsing; RunasCs grabs its args via its own C# parser, and the relevant mangling already happened when cmd handed the args to RunasCs).
Also note that the command prompt will immediately look like snaffler finished, so babysit taskmanager to see when the job is truly done:
tasklist /fi "imagename eq snaffler.exe"
Once snaffler.exe is not in the list, the gig is done.
Running with PowerUpSQL as an example
Get the base64 for the command:
$cmd = @'
Import-Module C:\Users\Public\pentest-tools\PowerUpSQL-master\PowerUpSQL.ps1
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Threads 10 | Where-Object {$_.Status -like "Accessible"} | Export-Csv -NoTypeInformation -Path C:\Users\Public\pentest-tools\PowerUpSQL-master\sql_accessible.csv
'@
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
Run within RunasCs:
RunasCs\RunasCs.exe low-priv "Summer2026%" "powershell.exe -ExecutionPolicy Bypass -EncodedCommand <PASTE_BASE64_HERE>" -d domain.com -l 9 -t 0
Running with SharpHound as an example
RunasCs\RunasCs.exe low-priv "Summer2026%" "C:\Users\Public\pentest-tools\sharphound\SharpHound.exe -d domain.com --domaincontroller dc01.domain.com -c All" -l 9 -d domain.com" -d domain.com -l 9 -t 0
The SharpHound zip file will end up in c:\windows\system32!