Skip to content

Commit

Permalink
Merge pull request #165 from GoSecure/doc-docker
Browse files Browse the repository at this point in the history
doc: docker refinements
  • Loading branch information
obilodeau authored Nov 26, 2019
2 parents 0476777 + a7b564d commit 70c32de
Showing 1 changed file with 119 additions and 82 deletions.
201 changes: 119 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,49 +28,68 @@ In August 2019, PyRDP was demo'ed at BlackHat Arsenal ([slides](https://docs.goo
## Table of Contents
- [Supported Systems](#supported-systems)
- [Installing](#installing)
* [Installing on Windows](#installing-on-windows)
* [Installing with Docker](#installing-with-docker)
* [Migrating away from pycrypto](#Migrating-away-from-pycrypto)
- [Using the PyRDP Man-in-the-Middle](#using-the-pyrdp-man-in-the-middle)
* [Specifying the private key and certificate](#specifying-the-private-key-and-certificate)
* [Connecting to the PyRDP player](#connecting-to-the-pyrdp-player)
+ [Connecting to a PyRDP player when the MITM is running on a server](#connecting-to-a-pyrdp-player-when-the-mitm-is-running-on-a-server)
* [Running payloads on new connections](#running-payloads-on-new-connections)
+ [Setting the payload](#setting-the-payload)
+ [Choosing when to start the payload](#choosing-when-to-start-the-payload)
+ [Choosing when to resume normal activity](#choosing-when-to-resume-normal-activity)
* [Other MITM arguments](#other-mitm-arguments)
- [Using the PyRDP Player](#using-the-pyrdp-player)
* [Playing a replay file](#playing-a-replay-file)
* [Listening for live connections](#listening-for-live-connections)
* [Changing the listening address](#changing-the-listening-address)
* [Other player arguments](#other-player-arguments)
- [Using the PyRDP Certificate Cloner](#using-the-pyrdp-certificate-cloner)
* [Cloning a certificate](#cloning-a-certificate)
* [Using a custom private key](#using-a-custom-private-key)
* [Other cloner arguments](#other-cloner-arguments)
- [Using PyRDP as a Library](#using-pyrdp-as-a-library)
- [Using PyRDP with Bettercap](#using-pyrdp-with-bettercap)
* [Using the Docker Image](#using-the-docker-image)
* [From Git Source](#from-git-source)
* [Installing on Windows](#installing-on-windows)
* [Building the Docker Image](#building-the-docker-image)
* [Migrating away from pycrypto](#migrating-away-from-pycrypto)
- [Using PyRDP](#using-pyrdp)
* [Using the PyRDP Man-in-the-Middle](#using-the-pyrdp-man-in-the-middle)
+ [Specifying the private key and certificate](#specifying-the-private-key-and-certificate)
+ [Connecting to the PyRDP player](#connecting-to-the-pyrdp-player)
- [Connecting to a PyRDP player when the MITM is running on a server](#connecting-to-a-pyrdp-player-when-the-mitm-is-running-on-a-server)
+ [Running payloads on new connections](#running-payloads-on-new-connections)
- [Setting the payload](#setting-the-payload)
- [Choosing when to start the payload](#choosing-when-to-start-the-payload)
- [Choosing when to resume normal activity](#choosing-when-to-resume-normal-activity)
+ [Other MITM arguments](#other-mitm-arguments)
* [Using the PyRDP Player](#using-the-pyrdp-player)
+ [Playing a replay file](#playing-a-replay-file)
+ [Listening for live connections](#listening-for-live-connections)
+ [Changing the listening address](#changing-the-listening-address)
+ [Other player arguments](#other-player-arguments)
* [Using the PyRDP Certificate Cloner](#using-the-pyrdp-certificate-cloner)
+ [Cloning a certificate](#cloning-a-certificate)
+ [Using a custom private key](#using-a-custom-private-key)
+ [Other cloner arguments](#other-cloner-arguments)
* [Using PyRDP as a Library](#using-pyrdp-as-a-library)
* [Using PyRDP with Bettercap](#using-pyrdp-with-bettercap)
* [Docker Specific Usage Instructions](#docker-specific-usage-instructions)
+ [Mapping a Listening Port](#mapping-a-listening-port)
+ [Logs and Artifacts Storage](#logs-and-artifacts-storage)
+ [Using the GUI Player in Docker](#using-the-gui-player-in-docker)
- [PyRDP Presentations](#pyrdp-presentations)
- [Contributing to PyRDP](#contributing-to-pyrdp)
- [Acknowledgements](#acknowledgements)


## Supported Systems
PyRDP should work on Python 3.6 and up.

This tool has been tested to work on Python 3.6 on Linux (Ubuntu 18.04) and Windows (See section [Installing on Windows](#installing-on-windows)). It has not been tested on OSX.

## Installing

_Note: PyRDP cannot be installed on 32bit systems. See: [this issue.](https://github.com/GoSecure/pyrdp/issues/150)_

### Using the Docker Image

This is the easiest installation method if you have docker installed and working.

```
docker pull gosecure/pyrdp:latest
```

### From Git Source

We recommend installing PyRDP in a
[virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/)
to avoid dependency issues.

_Note: PyRDP cannot be installed on 32bit systems. See: [this issue.](https://github.com/GoSecure/pyrdp/issues/150)_

First, make sure to install the prerequisite packages (on Ubuntu):

```
sudo apt install libdbus-1-dev libdbus-glib-1-dev libgl1-mesa-glx
sudo apt install libdbus-1-dev libdbus-glib-1-dev libgl1-mesa-glx git
```

On some systems, you may need to install the `python3-venv` package:
Expand All @@ -79,7 +98,13 @@ On some systems, you may need to install the `python3-venv` package:
sudo apt install python3-venv
```

Then, create your virtual environment in PyRDP's directory:
Grab PyRDP's source code:

```
git clone https://github.com/gosecure/pyrdp.git
```

Then, create your virtual environment in the `venv` directory inside PyRDP's directory:

```
cd pyrdp
Expand Down Expand Up @@ -154,47 +179,15 @@ deactivate
Note that you will have to activate your environment every time you want to have the PyRDP scripts available as shell
commands.

### Installing with Docker
### Building the Docker Image

First of all, build the image by executing this command at the root of PyRDP (where Dockerfile is located):

```
docker build -t pyrdp .
```

Afterwards, you can execute the following command to run the container:

```
docker run -it -p 3389:3389 pyrdp pyrdp-mitm.py 192.168.1.10
```

For more information about the various commands and arguments, please refer to these sections:

- [Using the PyRDP MITM](#using-the-pyrdp-man-in-the-middle)
- [Using the PyRDP Player](#using-the-pyrdp-player)
- [Using the PyRDP Certificate Cloner](#using-the-pyrdp-certificate-cloner)

To store the PyRDP output permanently (logs, files, etc.), add the -v option to the previous command. For example:

```
docker run -v $PWD/pyrdp_output:/home/pyrdp/pyrdp_output -p 3389:3389 pyrdp pyrdp-mitm.py 192.168.1.10
```

Make sure that your destination directory is owned by a user with a UID of 1000, otherwise you will get a permission denied error.
If you're the only user on the system, you should not need to worry about this.

#### Using the player in Docker

Using the player will require you to export the DISPLAY environment variable from the host to the docker.
This redirects the GUI of the player to the host screen.
You also need to expose the host's network and stop Qt from using the MIT-SHM X11 Shared Memory Extension.
To do so, add the -e and --net options to the run command:

```
docker run -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 --net=host pyrdp pyrdp-player.py
```

Keep in mind that exposing the host's network to the docker can compromise the isolation between your container and the host.
If you plan on using the player, X11 forwarding using an SSH connection would be a more secure way.
Afterwards, you can execute PyRDP by invoking the `pyrdp` docker container. See [Usage instructions](#using-pyrdp) and the [Docker specific instructions](#docker-specific-usage-instructions) for details.

### Migrating away from pycrypto
Since pycrypto isn't maintained anymore, we chose to migrate to pycryptodome.
Expand All @@ -214,7 +207,9 @@ pip3 uninstall pycrypto
pip3 install -U -e .
```

## Using the PyRDP Man-in-the-Middle
## Using PyRDP

### Using the PyRDP Man-in-the-Middle
Use `pyrdp-mitm.py <ServerIP>` or `pyrdp-mitm.py <ServerIP>:<ServerPort>` to run the MITM.

Assuming you have an RDP server running on `192.168.1.10` and listening on port 3389, you would run:
Expand All @@ -227,23 +222,23 @@ When running the MITM for the first time on Linux, a private key and certificate
These are used when TLS security is used on a connection. You can use them to decrypt PyRDP traffic in Wireshark, for
example.

### Specifying the private key and certificate
#### Specifying the private key and certificate
If key generation didn't work or you want to use a custom key and certificate, you can specify them using the
`-c` and `-k` arguments:

```
pyrdp-mitm.py 192.168.1.10 -k private_key.pem -c certificate.pem
```

### Connecting to the PyRDP player
#### Connecting to the PyRDP player
If you want to see live RDP connections through the PyRDP player, you will need to specify the ip and port on which the
player is listening using the `-i` and `-d` arguments. Note: the port argument is optional, the default port is 3000.

```
pyrdp-mitm.py 192.168.1.10 -i 127.0.0.1 -d 3000
```

#### Connecting to a PyRDP player when the MITM is running on a server
##### Connecting to a PyRDP player when the MITM is running on a server
If you are running the MITM on a server and still want to see live RDP connections, you should use
[SSH remote port forwarding](https://www.booleanworld.com/guide-ssh-port-forwarding-tunnelling/)
to forward a port on your server to the player's port on your machine. Once this is done, you pass `127.0.0.1` and the forwarded
Expand All @@ -254,7 +249,7 @@ this would be the command to use:
pyrdp-mitm.py 192.168.1.10 -i 127.0.0.1 -d 4000
```

### Running payloads on new connections
#### Running payloads on new connections
PyRDP has support for running console commands or PowerShell payloads automatically when new connections are made.
Due to the nature of RDP, the process is a bit hackish and is not always 100% reliable. Here is how it works:

Expand All @@ -271,14 +266,14 @@ For this to work, you need to set 3 arguments:
- the delay before the payload starts
- the payload's duration

#### Setting the payload
##### Setting the payload
You can use one of the following arguments to set the payload to run:

- `--payload`, a string containing console commands
- `--payload-powershell`, a string containing PowerShell commands
- `--payload-powershell-file`, a path to a PowerShell script

#### Choosing when to start the payload
##### Choosing when to start the payload
For the moment, PyRDP does not detect when the user is logged on.
You must give it an amount of time to wait for before running the payload.
After this amount of time has passed, it will send the fake key sequences and expect the payload to run properly.
Expand All @@ -292,7 +287,7 @@ For example, if you expect the user to be logged in within the first 5 seconds,
This could be made more accurate by leveraging some messages exchanged during RDPDR initialization.
See [this issue](https://github.com/GoSecure/pyrdp/issues/98) if you're interested in making this work better.

#### Choosing when to resume normal activity
##### Choosing when to resume normal activity
Because there is no direct way to know when the console has stopped running, you must tell PyRDP how long you want
the client's input / output to be blocked. We recommend you set this to the maximum amount of time you would expect the
console that is running your payload to be visible. In other words, the amount of time you would expect your payload to
Expand All @@ -307,13 +302,13 @@ For example, if you expect your payload to take up to 5 seconds to complete, you
This will block the client's input / output for 5 seconds to hide the console and prevent interference.
After 5 seconds, input / output is restored back to normal.

### Other MITM arguments
#### Other MITM arguments
Run `pyrdp-mitm.py --help` for a full list of arguments.

## Using the PyRDP Player
### Using the PyRDP Player
Use `pyrdp-player.py` to run the player.

### Playing a replay file
#### Playing a replay file
You can use the menu to open a new replay file: File > Open.

You can also open replay files when launching the player:
Expand All @@ -322,32 +317,32 @@ You can also open replay files when launching the player:
pyrdp-player.py <FILE1> <FILE2> ...
```

### Listening for live connections
#### Listening for live connections
The player always listens for live connections. By default, the listening port is 3000, but it can be changed:

```
pyrdp-player.py -p <PORT>
```

### Changing the listening address
#### Changing the listening address
By default, the player only listens to connections coming from the local machine. We do not recommend opening up the player
to other machines. If you still want to change the listening address, you can do it with `-b`:

```
pyrdp-player.py -b <ADDRESS>
```

### Other player arguments
#### Other player arguments
Run `pyrdp-player.py --help` for a full list of arguments.

## Using the PyRDP Certificate Cloner
### Using the PyRDP Certificate Cloner
The PyRDP certificate cloner creates a brand new X509 certificate by using the values from an existing RDP server's
certificate. It connects to an RDP server, downloads its certificate, generates a new private key and replaces the
public key and signature of the certificate using the new private key. This can be used in a pentest if, for example,
you're trying to trick a legitimate user into going through your MITM. Using a certificate that looks like a legitimate
certificate could increase your success rate.

### Cloning a certificate
#### Cloning a certificate
You can clone a certificate by using `pyrdp-clonecert.py`:

```
Expand All @@ -356,24 +351,66 @@ pyrdp-clonecert.py 192.168.1.10 cert.pem -o key.pem

The `-o` parameter defines the path name to use for the generated private key.

### Using a custom private key
#### Using a custom private key
If you want to use your own private key instead of generating a new one:

```
pyrdp-clonecert.py 192.168.1.10 cert.pem -i input_key.pem
```

### Other cloner arguments
#### Other cloner arguments
Run `pyrdp-clonecert.py --help` for a full list of arguments.

## Using PyRDP as a Library
### Using PyRDP as a Library
If you're interested in experimenting with RDP and making your own tools, head over to our
[documentation section](docs/README.md) for more information.

## Using PyRDP with Bettercap
### Using PyRDP with Bettercap
We developped our own Bettercap module, `rdp.proxy`, to man-in-the-middle all RDP connections
on a given LAN. Check out [this document](docs/bettercap-rdp-mitm.md) for more information.

### Docker Specific Usage Instructions

Since docker restricts the interactions with the host system (filesystem and network), the PyRDP docker image must be run with some parameters depending on your use case. This section documents those parameters.

We refer to the publicly provided docker image but if you [built your own](#building-the-docker-image) replace `gosecure/pyrdp` with the name of your locally built image.

#### Mapping a Listening Port

In most of the man-in-the-middle cases you will need to map a port of your host into the docker image. This is achieved by the `--publish` (`-p`) parameters applied to `docker run`.

For example, to listen on 3389 (RDP's default port) on all interfaces, use:

```
docker run -p 3389:3389 gosecure/pyrdp pyrdp-mitm.py 192.168.1.10
```

#### Logs and Artifacts Storage

To store the PyRDP output permanently (logs, files, etc.), add the `--volume` (`-v`) option to the previous command. In this example we store the files relatively to the current directory in `pyrdp_output`:

```
docker run -v $PWD/pyrdp_output:/home/pyrdp/pyrdp_output -p 3389:3389 gosecure/pyrdp pyrdp-mitm.py 192.168.1.10
```

Make sure that your destination directory is owned by a user with a UID of 1000, otherwise you will get permission denied errors.
If you are the only non-root user on the system, usually your user will be assigned UID 1000.

#### Using the GUI Player in Docker

Using the player will require you to export the `DISPLAY` environment variable from the host to the docker.
This redirects the GUI of the player to the host screen.
You also need to expose the host's network and prevent Qt from using the MIT-SHM X11 Shared Memory Extension.
To do so, add the `-e` and `--net` options to the run command:

```
docker run -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 --net=host gosecure/pyrdp pyrdp-player.py
```

Keep in mind that exposing the host's network to docker can compromise the isolation between your container and the host.
If you plan on using the player, X11 forwarding using an SSH connection would be a more secure way.


## PyRDP Presentations

## Contributing to PyRDP
Expand Down

0 comments on commit 70c32de

Please sign in to comment.