Minimal CLI to send or receive files over HTTP or SMB.
Project description
🔄 Exchanger (exchangertool)
Exchanger is a fast, lightweight, and flexible Python CLI utility designed to streamline file transfers, payload delivery, and data exchange between machines.
Whether you are a system administrator moving files or a security professional leveraging LOLBAS/GTFOBins during an engagement, exchangertool provides a seamless way to host, transfer, and exfiltrate your data.
✨ Features
- Quick Setup: Spin up a file exchange server in seconds.
- Cross-Platform Target Support: Serves files to Windows (
certutil,curl,PowerShell,iwr,bitsadmin,net use) and GNU/Linux (wget,curl,bash) targets. - Obfuscation (
-o): PowerShell-Obfuscation-Bible–style and Bashfuscator-style command obfuscation for authorized testing. - Basic Auth (
--auth): Protect downloads/uploads with HTTP Basic authentication. - One-Shot Mode (
--one-shot): Server exits after completing a single transfer. - Push Mode (
push): Actively push a file to a listening target. - Base64 Encoding (
--encode base64): Auto-encode on push, auto-decode on receive. - Clipboard Copy (
-c): Auto-copy first target command to clipboard. - QR Code (
-q): Display download URL as a QR code for air-gapped transfers. - Checksum Verification: SHA256 verification commands printed alongside downloads.
- DNS Exfil Commands: Ready-to-use DNS exfiltration stagers for Linux and Windows.
- Chunked Transfer Commands: Split large files into chunks for size-limit evasion.
- WebDAV Commands: Windows
net use/copycommands via WebDAV. - Proxy Support (
--proxy): Generate proxy-aware target commands (SOCKS5/HTTP). - Request Logging (
--log): Log all requests to a file (timestamp, IP, method, path, user-agent). - Auto-Rename: Uploads never overwrite — collisions auto-rename to
file.1,file.2, etc. - SMB Serve (
--protocol smb): Serve files over SMB using impacket (optional). - Standalone CLI: Runs smoothly from any terminal.
- Isolated Installation: Compatible with
pipx.
📦 Installation
pipx install exchangertool
Optional extras
# QR code support
pipx install exchangertool[qr]
# SMB support (requires impacket)
pipx install exchangertool[smb]
# Everything
pipx install exchangertool[all]
Using with sudo
pipx installs to your user directory (e.g. ~/.local/bin). For root:
# Option 1: Full path
sudo "$(which exchanger)" serve --port 80
# Option 2: System-wide install
sudo pip install exchangertool
# Option 3: Allow low ports without sudo (Linux)
sudo setcap 'cap_net_bind_service=+ep' "$(which exchanger)"
🚀 Usage
Serve (default)
exchanger # serve current directory on port 80
exchanger serve -d /payloads -p 8080 # serve specific dir on custom port
exchanger serve --auth admin:s3cret # require authentication
exchanger serve --one-shot # exit after first download
exchanger serve -o # obfuscated commands to stdout
exchanger serve -c # copy first command to clipboard
exchanger serve -q # show QR code of download URL
exchanger serve --proxy socks5://127.0.0.1:1080 # proxy-aware commands
exchanger serve --log requests.log # log all requests
Receive (listen for uploads)
exchanger receive # listen for target to POST files
exchanger receive --encode base64 # auto-decode base64 uploads
exchanger receive --one-shot # exit after first upload
exchanger receive --auth user:pass # require auth for uploads
Push (send to target)
exchanger push payload.bin 10.0.0.1:8080 # push file to target
exchanger push payload.bin 10.0.0.1:8080 --encode base64 # base64-encode
SMB (optional)
exchanger serve --protocol smb -d /share -p 445
exchanger serve --protocol smb --auth admin:pass
🛠️ Help menu
usage: exchanger [-h] {serve,receive,push} ...
Serve files or listen to receive (target POSTs to host). Default port 80.
positional arguments:
{serve,receive,push} command (default: serve)
serve serve current directory; others can send/receive
receive listen for target to POST file to you
push push a file to a listening target
common options (serve/receive):
--protocol {http,smb} protocol (default: http)
-p, --port PORT port (default: 80)
-d, --dir DIR directory to serve/save (default: .)
--bind ADDR address to bind (default: 0.0.0.0)
-o, --obfuscate obfuscated commands to stdout
--one-shot exit after first transfer
--auth USER:PASS HTTP Basic auth
--log FILE log requests to file
--proxy PROXY_URL proxy for target commands
-c, --clipboard copy first command to clipboard
-q, --qr show QR code of download URL
receive-only:
--encode base64 decode uploads on the server
push:
exchanger push FILE TARGET [--encode base64]
📋 Generated Target Commands
When you start the server, exchanger prints ready-to-paste commands organized by platform:
| Category | Linux (GTFOBins) | Windows (LOLBAS) |
|---|---|---|
| Download | curl, wget, /dev/tcp |
curl, wget, certutil, iwr, bitsadmin |
| Download LOLBins | python3, perl, ruby, php, nc, socat, openssl, lwp-download, tftp |
DownloadFile, Start-BitsTransfer, mshta, regsvr32, msiexec, hh.exe, esentutl, expand, findstr, replace, cscript |
| In-Memory | curl | bash, wget | bash |
iwr | iex, WebClient.DownloadString |
| In-Memory LOLBins | python exec(), perl eval(), ruby eval(), php eval() |
mshta vbscript, rundll32 javascript, powershell -enc, cscript //e:jscript, Reflection.Assembly.Load |
| Upload | curl -X POST |
curl -X POST |
| Upload LOLBins | nc, python requests, openssl s_client, socat, bash /dev/tcp |
WebClient.UploadFile, WebClient.UploadData, iwr -Method POST |
| Checksum | sha256sum |
Get-FileHash |
| DNS Exfil | xxd | nslookup, base64 | dig |
PowerShell + nslookup |
| Chunked | split + curl loop |
PowerShell byte chunking |
| WebDAV | — | net use, copy |
All commands respect --auth, --proxy, and -o (obfuscation) flags.
🔒 Obfuscation Techniques (-o)
When -o is passed, all target commands are obfuscated and written to stdout (for piping/redirection).
PowerShell obfuscation:
- Quote interruption (
i''ex,i""wr) - Random case (
iNvOkE-wEbReQuEsT) - Backtick insertion (
i`e`x) - Format string iex (
("{0}{1}{2}" -f 'i','e','x')) - Get-Command wildcard (
& (gcm i*e*-E*n)) -EncodedCommand(base64 UTF-16LE full command wrap)[scriptblock]::Create()wrappingSet-Aliasfor cmdlet renaming- URL string concatenation and base64 encoding
$True/$Falseboolean substitution- WebClient variable name randomization
Bash obfuscation:
- Base64 wrap (
echo ... | base64 -d | bash,eval $(...),source <(...)) - Variable expansion (
_var=curl; $_var ...) - Double variable indirection (
a=curl; b=a; ${!b} ...) - Hex command names (
$'\x63\x75\x72\x6c') - Printf command names (
$(printf '\x63\x75\x72\x6c')) - Reverse pipe (
echo '...reversed...' | rev | bash) - IFS substitution (
curl${IFS}-s${IFS}http://...) - Quote tricks (
cu''rl,wg''et)
🧪 Testing
CI runs the test suite on Python 3.10–3.13 with mypy type checking on every push/PR.
pip install -e ".[dev]"
pytest tests/ -v
mypy exchanger/ --ignore-missing-imports
Coverage report: pytest tests/ --cov=exchanger --cov-report=term-missing
🤝 Contributing
Contributions, bug reports, and feature requests are always welcome! Feel free to check out the issues page.
📝 License
This project is licensed under the MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file exchangertool-0.3.0.tar.gz.
File metadata
- Download URL: exchangertool-0.3.0.tar.gz
- Upload date:
- Size: 35.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72d2590d654fc92800bdc27d110cf39b0a98a7cbb570afb83ba869f2f06a8be1
|
|
| MD5 |
96d718f05c501950b9e86ae8c204bf9d
|
|
| BLAKE2b-256 |
150a144f5092eaf25119e2891f072d5de932572cadacebd7f31e9fe27cccfcd9
|
Provenance
The following attestation bundles were made for exchangertool-0.3.0.tar.gz:
Publisher:
publish.yml on didntchooseaname/exchanger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exchangertool-0.3.0.tar.gz -
Subject digest:
72d2590d654fc92800bdc27d110cf39b0a98a7cbb570afb83ba869f2f06a8be1 - Sigstore transparency entry: 1156222460
- Sigstore integration time:
-
Permalink:
didntchooseaname/exchanger@8b9d29be8634af333e9b4a9dc75cf939cae56568 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/didntchooseaname
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8b9d29be8634af333e9b4a9dc75cf939cae56568 -
Trigger Event:
release
-
Statement type:
File details
Details for the file exchangertool-0.3.0-py3-none-any.whl.
File metadata
- Download URL: exchangertool-0.3.0-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d09ed1b8118ec641dee8ff4161336bc67301fa43ba43681bbcf4548845031bcd
|
|
| MD5 |
02c5a22e76bc8eadc6c8e9a6b0d54612
|
|
| BLAKE2b-256 |
6dedf8c70d02badf48e0c2bb9bab28ef5743797ac5123fd0418e7cc7326b3022
|
Provenance
The following attestation bundles were made for exchangertool-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on didntchooseaname/exchanger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exchangertool-0.3.0-py3-none-any.whl -
Subject digest:
d09ed1b8118ec641dee8ff4161336bc67301fa43ba43681bbcf4548845031bcd - Sigstore transparency entry: 1156222464
- Sigstore integration time:
-
Permalink:
didntchooseaname/exchanger@8b9d29be8634af333e9b4a9dc75cf939cae56568 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/didntchooseaname
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8b9d29be8634af333e9b4a9dc75cf939cae56568 -
Trigger Event:
release
-
Statement type: