From a78aea2678b7fc7bd665576d922e0b8d33dea1c9 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Thu, 7 Nov 2019 16:18:57 -0500 Subject: [PATCH 1/3] doc: docker refinements --- README.md | 147 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index baa89e7ca..321a5470b 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ target machine. PyRDP was [first introduced in a blogpost](https://www.gosecure.net/blog/2018/12/19/rdp-man-in-the-middle-smile-youre-on-camera) in which we [demonstrated that we can catch a real threat actor in action](https://www.youtube.com/watch?v=eB7RC9FmL6Q). In May 2019 a [presentation by its authors](https://docs.google.com/presentation/d/1avcn8Sh2b3IE7AA0G9l7Cj5F1pxqizUm98IbXUo2cvY/edit#slide=id.g404b70030f_0_581) was given at NorthSec and two demos were performed. [The first one covered](https://youtu.be/5JztJzi-m48) credential logging, clipboard stealing, client-side file browsing and a session take-over. [The second one covered](https://youtu.be/bU67tj1RkMA) the execution of cmd or powershell payloads when a client successfully authenticates. In August 2019, PyRDP was demo'ed at BlackHat Arsenal ([slides](https://docs.google.com/presentation/d/17P_l2n-hgCehQ5eTWilru4IXXHnGIRTj4ftoW4BiX5A/edit?usp=sharing)). +// TODO: regen ToC ## Table of Contents - [Supported Systems](#supported-systems) - [Installing](#installing) @@ -61,16 +62,26 @@ This tool has been tested to work on Python 3.6 on Linux (Ubuntu 18.04) and Wind ## 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 +sudo apt install libdbus-1-dev libdbus-glib-1-dev git ``` On some systems, you may need to install the `python3-venv` package: @@ -79,7 +90,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 @@ -154,47 +171,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](TODO) and the [Docker specific instructions](TODO) for details. ### Migrating away from pycrypto Since pycrypto isn't maintained anymore, we chose to migrate to pycryptodome. @@ -214,7 +199,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 ` or `pyrdp-mitm.py :` to run the MITM. Assuming you have an RDP server running on `192.168.1.10` and listening on port 3389, you would run: @@ -227,7 +214,7 @@ 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: @@ -235,7 +222,7 @@ If key generation didn't work or you want to use a custom key and certificate, y 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. @@ -243,7 +230,7 @@ player is listening using the `-i` and `-d` arguments. Note: the port argument i 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 @@ -254,7 +241,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: @@ -271,14 +258,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. @@ -292,7 +279,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 @@ -307,13 +294,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: @@ -322,14 +309,14 @@ You can also open replay files when launching the player: pyrdp-player.py ... ``` -### 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 ``` -### 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`: @@ -337,17 +324,17 @@ to other machines. If you still want to change the listening address, you can do pyrdp-player.py -b
``` -### 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`: ``` @@ -356,24 +343,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](TODO) 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 From 9b83e0e5b2116b16f2ba71e7768a55a6759f7796 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Mon, 25 Nov 2019 11:50:49 -0500 Subject: [PATCH 2/3] doc: Updated ToC --- README.md | 56 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 321a5470b..f54a93b6a 100644 --- a/README.md +++ b/README.md @@ -25,36 +25,44 @@ target machine. PyRDP was [first introduced in a blogpost](https://www.gosecure.net/blog/2018/12/19/rdp-man-in-the-middle-smile-youre-on-camera) in which we [demonstrated that we can catch a real threat actor in action](https://www.youtube.com/watch?v=eB7RC9FmL6Q). In May 2019 a [presentation by its authors](https://docs.google.com/presentation/d/1avcn8Sh2b3IE7AA0G9l7Cj5F1pxqizUm98IbXUo2cvY/edit#slide=id.g404b70030f_0_581) was given at NorthSec and two demos were performed. [The first one covered](https://youtu.be/5JztJzi-m48) credential logging, clipboard stealing, client-side file browsing and a session take-over. [The second one covered](https://youtu.be/bU67tj1RkMA) the execution of cmd or powershell payloads when a client successfully authenticates. In August 2019, PyRDP was demo'ed at BlackHat Arsenal ([slides](https://docs.google.com/presentation/d/17P_l2n-hgCehQ5eTWilru4IXXHnGIRTj4ftoW4BiX5A/edit?usp=sharing)). -// TODO: regen ToC ## 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. From 7f0214480ebe876a8c822f5d2cf271ff494c7a35 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Mon, 25 Nov 2019 11:54:36 -0500 Subject: [PATCH 3/3] doc: fixed internal links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f54a93b6a..d84b21ee7 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ First of all, build the image by executing this command at the root of PyRDP (wh docker build -t pyrdp . ``` -Afterwards, you can execute PyRDP by invoking the `pyrdp` docker container. See [Usage instructions](TODO) and the [Docker specific instructions](TODO) for details. +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. @@ -373,7 +373,7 @@ on a given LAN. Check out [this document](docs/bettercap-rdp-mitm.md) for more i 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](TODO) replace `gosecure/pyrdp` with the name of your locally built image. +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