From af5b8bfc03a0f7e09cea768fe8a4c092a925eaf8 Mon Sep 17 00:00:00 2001 From: JerryLinLinLin <61572787+JerryLinLinLin@users.noreply.github.com> Date: Thu, 1 Oct 2026 20:52:38 -0500 Subject: [PATCH 1/3] Bundle skills only inside complete plugin packages --- .github/workflows/hyper-v-control.yml | 6 +++-- README.md | 2 +- docs/build.md | 2 +- docs/releases.md | 11 ++++---- plugins/rizin-re-toolkit/README.md | 2 +- scripts/package_bundle.py | 38 ++++++++++++++++++++++----- scripts/test-plugin-packaging.py | 28 ++++++++++++++++++++ 7 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 scripts/test-plugin-packaging.py diff --git a/.github/workflows/hyper-v-control.yml b/.github/workflows/hyper-v-control.yml index 14c03d8..63163c9 100644 --- a/.github/workflows/hyper-v-control.yml +++ b/.github/workflows/hyper-v-control.yml @@ -1,9 +1,9 @@ name: Hyper-V Control on: push: - paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] + paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/package_bundle.py', 'scripts/test-plugin-packaging.py', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] pull_request: - paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] + paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/package_bundle.py', 'scripts/test-plugin-packaging.py', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] workflow_dispatch: permissions: contents: read @@ -29,6 +29,8 @@ jobs: dotnet run --project tests/HyperVControl.Tests -c Release -- smoke $PWD if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } ./scripts/test-release-isolation.ps1 + python scripts/test-plugin-packaging.py + exit $LASTEXITCODE - uses: actions/upload-artifact@v4 with: name: hyper-v-control-win-x64 diff --git a/README.md b/README.md index 7e1ecb1..4bb91f8 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ The catalog is [.agents/plugins/marketplace.json](.agents/plugins/marketplace.js | Component | Release | What to download | | --- | --- | --- | | Hyper-V Control | [0.1.0](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/hyper-v-control-v0.1.0) | Namespaced Windows x64 EXE or complete plugin ZIP | -| Rizin RE Toolkit plugin/skill | [0.4.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) | Plugin ZIP or skill; includes the isolated, paginated runtime installer | +| Rizin RE Toolkit | [0.4.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) | Complete plugin ZIP with its skill and isolated, paginated runtime installer | | Rizin portable runtime | [0.3.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-v0.3.1) | Existing runtime bundle and its unchanged `SHA256SUMS` | Use the [release organization guide](docs/releases.md) for tag/asset naming, per-plugin checksum pins, independent runtime versions and publication steps. Installers do not use the repository-wide Latest release to select a plugin. Existing Rizin URLs remain compatible. diff --git a/docs/build.md b/docs/build.md index 39d5fcb..a70f0d4 100644 --- a/docs/build.md +++ b/docs/build.md @@ -43,7 +43,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-bundle.ps1 - This creates a runtime ZIP, plugin ZIP, standalone skill package, and SHA256SUMS. The command reproduces the currently locked runtime version. For a new CLI release, increment the bundle version in the lock file and tag the tested source commit with a new `rizin-v` tag. Other marketplace plugins can use their own tag prefixes. -Plugin/skill releases are now independent of the CLI bundle version. The runtime ZIP uses `bundle.lock.json` and the requested runtime version; plugin/skill filenames use the version in `plugins/rizin-re-toolkit/plugin.json`. +Plugin releases are independent of the CLI bundle version. The runtime ZIP uses `bundle.lock.json` and the requested runtime version; the complete plugin ZIP uses the version in `plugins/rizin-re-toolkit/plugin.json`. Skills are included inside the plugin ZIP, with no separate skill archive. For a skill-only or metadata update, package without rebuilding or republishing the runtime: diff --git a/docs/releases.md b/docs/releases.md index 12e9096..2eb180d 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -7,7 +7,7 @@ This repository is a marketplace of independently versioned plugins. A GitHub Re | Stream | Version and tag | Downloads | Installation | | --- | --- | --- | --- | | Hyper-V Control | [0.1.0](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/hyper-v-control-v0.1.0) | C# EXE and complete Windows x64 plugin ZIP | `%LOCALAPPDATA%\Programs\HyperVControl\0.1.0` or the ZIP's `bin` directory | -| Rizin RE Toolkit plugin/skill | [0.4.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) | Plugin ZIP and `.skill` | Codex plugin/skill directory | +| Rizin RE Toolkit | [0.4.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) | Complete plugin ZIP, including its skill | Codex plugin directory | | Rizin portable runtime | [0.3.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-v0.3.1) | Rizin 0.9.1 Windows x64 runtime bundle | `%LOCALAPPDATA%\Programs\Rizin\rizin-v0.3.1` | | Capstone Binary Patching | Plugin `0.1.0`, marketplace source | Skill/scripts; dependencies installed by uv | Its uv-managed environment; no repository binary release required | | Frida Use | Plugin `1.0.0`, marketplace source | Skill/scripts/references; Frida installed separately | The selected analysis environment; no repository binary release required | @@ -23,12 +23,13 @@ The marketplace's source of truth for plugin identity/version remains `plugins/< | Standalone executable | `--v.exe` | `hyper-v-control-win-x64-v0.1.0.exe` | | Complete plugin ZIP | `-plugin-v[-].zip` | `hyper-v-control-plugin-v0.1.0-win-x64.zip` | | Multi-file runtime ZIP, when needed | `-runtime--v.zip` | Use when an EXE requires adjacent runtime files | -| Optional skill archive | `-v.skill` | `rizin-re-toolkit-v0.4.1.skill` | | Checksums | `-v-SHA256SUMS.txt` | `hyper-v-control-v0.1.0-SHA256SUMS.txt` | | Asset inventory | `-v-release.json` | `hyper-v-control-v0.1.0-release.json` | Use .NET-style runtime identifiers such as `win-x64`, `win-arm64`, `linux-x64`, and `osx-arm64`. A filename should stay unambiguous when copied into a shared Downloads directory. An installed executable may have a stable local name such as `HyperVControl.exe`; the installer maps the namespaced download to that name inside the plugin's own versioned directory. +Skills belong inside the complete plugin ZIP and are installed with the plugin. Do not publish a redundant standalone `.skill` download for a new plugin release. Historical standalone skill assets remain available at their original release URLs. + For a genuinely independent runtime version, use a separate `-runtime-v` stream and pin the relationship from the consuming plugin. A plugin may update documentation without rebuilding a large, unchanged runtime. Existing Rizin runtime tags (`rizin-v0.3.1`) and asset names are legacy compatibility contracts and are not renamed. ## Download and upgrade isolation @@ -37,7 +38,7 @@ For a genuinely independent runtime version, use a separate `-runtim - Prefer an exact release tag, platform, asset filename and SHA-256 pin in the consuming plugin. Hyper-V's `runtime.json` contains all four; its installer rejects a mismatched plugin, tag, platform or asset URL before downloading. - When latest-in-stream discovery is necessary, filter both tag family and asset name, skip drafts/prereleases, paginate until the stream is found, and verify the selected asset checksum. Rizin's installer follows this path and retains its legacy `SHA256SUMS` lookup. - Keep install directories separate and versioned. Reuse a matching verified installation; do not overwrite a different checksum in place or alter a global PATH implicitly. Rizin's user PATH change remains opt-in; Hyper-V uses an absolute executable path. -- Keep old tags/assets immutable. Fix a published build with a new patch version. Draft assets may be replaced before publication; published assets are never replaced by this workflow. +- Keep published runtime binaries and plugin ZIPs immutable. Fix their contents with a new patch version. Release notes and inventories may be corrected, and redundant ancillary downloads may be removed with their checksum entries; these editorial changes must preserve the executable/ZIP hashes and existing runtime URLs. - Publish independent plugin releases with `--latest=false`. The global GitHub Latest badge is not a plugin index. This preserves existing legacy behavior; the table above is the entrypoint for choosing a component. ## Packaging and publication @@ -57,9 +58,9 @@ hyper-v-control-v0.1.0-release.json hyper-v-control-v0.1.0-SHA256SUMS.txt ``` -The ZIP contains the EXE, manifests, English skill/documentation, launcher, installer, and licenses. The EXE-only download is for direct stdio MCP configuration. Local convenience aliases (`HyperVControl.exe`, `SHA256SUMS`) are not additional public Hyper-V assets. The inventory records primary asset names, roles, platforms, sizes and hashes; the checksum file also covers the inventory and does not hash itself. +The ZIP contains the EXE, manifests, skill, documentation, launcher, installer, and licenses. The EXE-only download is for direct stdio MCP configuration. Local convenience aliases (`HyperVControl.exe`, `SHA256SUMS`) are not additional public Hyper-V assets. The inventory records primary asset names, roles, platforms, sizes and hashes; the checksum file also covers the inventory and does not hash itself. -Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its release retains a `SHA256SUMS` compatibility asset and additionally publishes the namespaced checksum filename. The existing `rizin-v0.3.1` release is left untouched. Future Rizin runtime releases retain the existing runtime asset family and `SHA256SUMS` while older installers are supported. +Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its download page provides the complete plugin ZIP, namespaced asset inventory and namespaced checksum file. The existing `rizin-v0.3.1` runtime release is left untouched. Future Rizin runtime releases retain the existing runtime asset family and legacy `SHA256SUMS` while older runtime installers are supported; plugin-only releases do not need that compatibility alias. ## Validation diff --git a/plugins/rizin-re-toolkit/README.md b/plugins/rizin-re-toolkit/README.md index 4b862ad..45d4f26 100644 --- a/plugins/rizin-re-toolkit/README.md +++ b/plugins/rizin-re-toolkit/README.md @@ -21,7 +21,7 @@ Install **Rizin RE Toolkit** from **Jerry's Plugin Marketplace** in Codex. The [ The skill automatically applies to ordinary RE requests, including tasks phrased with Ghidra, IDA Pro/Hex-Rays, Binary Ninja, Cutter, radare2, or related tool names. Equivalent work uses the Rizin CLI; Ghidra decompilation uses bundled `pdg`, while general/IDA-style PE analysis starts with Rizin triage and `pdz`. The skill reports the actual engine used and checks native-project or unsupported-tool requirements before substituting workflows. -Download the independent [plugin and skill packages](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) if needed. The runtime continues to use the verified `rizin-v0.3.1` release. If the former `rizin-windows-re` plugin is installed, refresh the marketplace, install the new plugin, and remove the old installation to avoid duplicate skills. +Download the [complete plugin ZIP](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) if needed; its skill is included and needs no separate download. The runtime continues to use the verified `rizin-v0.3.1` release. If the former `rizin-windows-re` plugin is installed, refresh the marketplace, install the new plugin, and remove the old installation to avoid duplicate skills. The [PowerShell installer](skills/rizin-re-toolkit/scripts/install.ps1) supports a user-level install, an explicit destination, a fixed release tag, and optional user PATH registration. It verifies SHA-256 before running the extracted CLI. The large runtime is a separate release asset. diff --git a/scripts/package_bundle.py b/scripts/package_bundle.py index d13b541..de72943 100644 --- a/scripts/package_bundle.py +++ b/scripts/package_bundle.py @@ -1,4 +1,4 @@ -"""Package the runtime and independently versioned plugin/skill artifacts.""" +"""Package the runtime and complete plugin archives, including their skills.""" import argparse import hashlib import json @@ -10,6 +10,11 @@ ROOT = Path(__file__).resolve().parents[1] +def sha256(path): + with path.open('rb') as stream: + return hashlib.file_digest(stream, 'sha256').hexdigest() + + def archive(source, output, include_root=False): with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED, compresslevel=6) as result: for file in sorted(source.rglob('*')): @@ -52,10 +57,7 @@ def main(): if manifest['bundleVersion'] != args.version: raise RuntimeError('Runtime and requested versions disagree') packages.append((runtime, f'rizin-windows-x64-bundle-v{args.version}.zip', True)) - packages.extend([ - (plugin, f'rizin-re-toolkit-plugin-v{plugin_version}.zip', False), - (plugin / 'skills/rizin-re-toolkit', f'rizin-re-toolkit-v{plugin_version}.skill', True), - ]) + packages.append((plugin, f'rizin-re-toolkit-plugin-v{plugin_version}.zip', False)) output.mkdir(parents=True, exist_ok=True) artifacts = [] for folder, name, root in packages: @@ -71,8 +73,30 @@ def main(): evidence = output / 'verification.json' if evidence.is_file(): artifacts.append(evidence) - sums = ''.join(f'{hashlib.file_digest(file.open("rb"), "sha256").hexdigest()} {file.name}\n' for file in artifacts) - (output / 'SHA256SUMS').write_text(sums, encoding='ascii') + if args.plugin_only: + tag = f'rizin-re-toolkit-v{plugin_version}' + # A reused build directory may still contain the former duplicate export. + (output / f'{tag}.skill').unlink(missing_ok=True) + runtime_version = json.loads((ROOT / 'bundle.lock.json').read_text(encoding='utf-8-sig'))['bundleVersion'] + inventory = { + 'schemaVersion': 1, + 'repository': 'JerryLinLinLin/jerry-plugin-marketplace', + 'plugin': 'rizin-re-toolkit', 'version': plugin_version, 'tag': tag, + 'runtimeTag': f'rizin-v{runtime_version}', + 'assets': [ + {'name': file.name, 'kind': 'plugin', 'sha256': sha256(file), 'size': file.stat().st_size} + for file in artifacts + ], + } + inventory_path = output / f'{tag}-release.json' + inventory_path.write_text(json.dumps(inventory, indent=2) + '\n', encoding='utf-8') + artifacts.append(inventory_path) + checksum_name = f'{tag}-SHA256SUMS.txt' + else: + # Existing runtime installers require this legacy filename. + checksum_name = 'SHA256SUMS' + sums = ''.join(f'{sha256(file)} {file.name}\n' for file in artifacts) + (output / checksum_name).write_text(sums, encoding='ascii') if __name__ == '__main__': diff --git a/scripts/test-plugin-packaging.py b/scripts/test-plugin-packaging.py new file mode 100644 index 0000000..b677b39 --- /dev/null +++ b/scripts/test-plugin-packaging.py @@ -0,0 +1,28 @@ +"""Verify complete plugin ZIPs without redundant standalone skill downloads.""" +import hashlib +import json +from pathlib import Path +import subprocess +import sys +import uuid +import zipfile + +root = Path(__file__).resolve().parents[1] +version = json.loads((root / 'plugins/rizin-re-toolkit/plugin.json').read_text(encoding='utf-8-sig'))['version'] +tag = f'rizin-re-toolkit-v{version}' +output = root / 'build' / f'plugin-packaging-test-{uuid.uuid4().hex}' +output.mkdir(parents=True) +(output / f'{tag}.skill').write_bytes(b'obsolete standalone export') +subprocess.run([sys.executable, str(root / 'scripts/package_bundle.py'), '--plugin-only', '--version', version, '--output', str(output)], check=True) +zip_name = f'rizin-re-toolkit-plugin-v{version}.zip' +expected = {zip_name, f'{tag}-release.json', f'{tag}-SHA256SUMS.txt'} +assert {p.name for p in output.iterdir()} == expected, 'Only the plugin ZIP, inventory and checksum file should be published' +with zipfile.ZipFile(output / zip_name) as archive: + assert 'skills/rizin-re-toolkit/SKILL.md' in archive.namelist(), 'Skill must remain bundled in the plugin' + assert 'plugin.json' in archive.namelist(), 'Plugin manifest is required' +inventory = json.loads((output / f'{tag}-release.json').read_text()) +assert len(inventory['assets']) == 1 and inventory['assets'][0]['name'] == zip_name +for line in (output / f'{tag}-SHA256SUMS.txt').read_text().splitlines(): + digest, name = line.split(' ', 1) + assert hashlib.sha256((output / name).read_bytes()).hexdigest() == digest +print('PASS: plugin includes its skill; no standalone skill asset; inventory and checksums match') From 60458d9d1b465df16a05f98b4e483932536ce1ab Mon Sep 17 00:00:00 2001 From: JerryLinLinLin <61572787+JerryLinLinLin@users.noreply.github.com> Date: Thu, 1 Oct 2026 20:55:07 -0500 Subject: [PATCH 2/3] Preserve existing checksum URLs during release cleanup --- docs/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.md b/docs/releases.md index 2eb180d..4319092 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -60,7 +60,7 @@ hyper-v-control-v0.1.0-SHA256SUMS.txt The ZIP contains the EXE, manifests, skill, documentation, launcher, installer, and licenses. The EXE-only download is for direct stdio MCP configuration. Local convenience aliases (`HyperVControl.exe`, `SHA256SUMS`) are not additional public Hyper-V assets. The inventory records primary asset names, roles, platforms, sizes and hashes; the checksum file also covers the inventory and does not hash itself. -Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its download page provides the complete plugin ZIP, namespaced asset inventory and namespaced checksum file. The existing `rizin-v0.3.1` runtime release is left untouched. Future Rizin runtime releases retain the existing runtime asset family and legacy `SHA256SUMS` while older runtime installers are supported; plugin-only releases do not need that compatibility alias. +Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its installation package is the complete plugin ZIP. The release also provides a namespaced asset inventory/checksum file and retains its existing `SHA256SUMS` URL for compatibility. The existing `rizin-v0.3.1` runtime release is left untouched. Future Rizin runtime releases retain the existing runtime asset family and legacy `SHA256SUMS` while older runtime installers are supported; new plugin-only releases use the namespaced checksum filename. ## Validation From 028e70b885aa5306644e939cce42550da2346c6f Mon Sep 17 00:00:00 2001 From: JerryLinLinLin <61572787+JerryLinLinLin@users.noreply.github.com> Date: Thu, 1 Oct 2026 21:15:28 -0500 Subject: [PATCH 3/3] Simplify marketplace documentation and maintenance --- .github/workflows/hyper-v-control.yml | 37 ----- .github/workflows/marketplace.yml | 65 +++++++++ CONTRIBUTING.md | 54 +++++++ README.md | 74 +++------- bundle.lock.json | 8 +- docs/build.md | 8 +- docs/releases.md | 28 +++- .../.codex-plugin/plugin.json | 25 +++- plugins/capstone-binary-patching/README.md | 68 +++------ plugins/frida-use/.codex-plugin/plugin.json | 2 +- plugins/frida-use/README.md | 4 +- plugins/frida-use/plugin.json | 2 +- .../hyper-v-control/.codex-plugin/plugin.json | 29 +++- plugins/hyper-v-control/README.md | 45 +++--- plugins/rizin-re-toolkit/README.md | 48 +++---- scripts/build_bundle.py | 8 +- scripts/check-marketplace.py | 133 ++++++++++++++++++ scripts/ci-plan.py | 46 ++++++ 18 files changed, 462 insertions(+), 222 deletions(-) delete mode 100644 .github/workflows/hyper-v-control.yml create mode 100644 .github/workflows/marketplace.yml create mode 100644 CONTRIBUTING.md create mode 100644 scripts/check-marketplace.py create mode 100644 scripts/ci-plan.py diff --git a/.github/workflows/hyper-v-control.yml b/.github/workflows/hyper-v-control.yml deleted file mode 100644 index 63163c9..0000000 --- a/.github/workflows/hyper-v-control.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Hyper-V Control -on: - push: - paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/package_bundle.py', 'scripts/test-plugin-packaging.py', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] - pull_request: - paths: ['src/HyperVControl/**', 'tests/HyperVControl.Tests/**', 'plugins/hyper-v-control/**', 'plugins/rizin-re-toolkit/**', 'scripts/build-hyperv-control.ps1', 'scripts/package_bundle.py', 'scripts/test-plugin-packaging.py', 'scripts/test-installer.ps1', 'scripts/test-release-isolation.ps1', '.github/workflows/hyper-v-control.yml'] - workflow_dispatch: -permissions: - contents: read -jobs: - windows: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '10.0.401' - - name: Build self-contained EXE and plugin - shell: pwsh - run: ./scripts/build-hyperv-control.ps1 - - name: Verify pinned runtime reproducibility - shell: pwsh - run: git diff --exit-code -- plugins/hyper-v-control/runtime.json - - name: Unit and stdio protocol validation - shell: pwsh - run: | - dotnet run --project tests/HyperVControl.Tests -c Release -- unit $PWD - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - dotnet run --project tests/HyperVControl.Tests -c Release -- smoke $PWD - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - ./scripts/test-release-isolation.ps1 - python scripts/test-plugin-packaging.py - exit $LASTEXITCODE - - uses: actions/upload-artifact@v4 - with: - name: hyper-v-control-win-x64 - path: build/hyperv-control/release/ diff --git a/.github/workflows/marketplace.yml b/.github/workflows/marketplace.yml new file mode 100644 index 0000000..3cc7602 --- /dev/null +++ b/.github/workflows/marketplace.yml @@ -0,0 +1,65 @@ +name: Marketplace CI +on: + pull_request: + branches: [main] + workflow_dispatch: +concurrency: + group: marketplace-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true +permissions: + contents: read +jobs: + catalog: + runs-on: ubuntu-latest + outputs: + windows: ${{ steps.plan.outputs.windows }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Check marketplace contracts + run: python scripts/check-marketplace.py + - name: Validate complete plugin packaging + run: python scripts/test-plugin-packaging.py + - name: Select component validation + id: plan + run: python scripts/ci-plan.py + windows: + needs: catalog + if: needs.catalog.outputs.windows == 'true' + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.0.401' + cache: true + cache-dependency-path: src/HyperVControl/packages.lock.json + - name: Build self-contained EXE and plugin + shell: pwsh + run: ./scripts/build-hyperv-control.ps1 + - name: Verify pinned runtime reproducibility + shell: pwsh + run: git diff --exit-code -- plugins/hyper-v-control/runtime.json + - name: Unit and stdio protocol validation + shell: pwsh + run: | + dotnet run --project tests/HyperVControl.Tests -c Release -- unit $PWD + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + dotnet run --project tests/HyperVControl.Tests -c Release -- smoke $PWD + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + ./scripts/test-release-isolation.ps1 + exit $LASTEXITCODE + - uses: actions/upload-artifact@v4 + if: github.event_name == 'workflow_dispatch' + with: + name: hyper-v-control-win-x64 + if-no-files-found: error + path: | + build/hyperv-control/release/hyper-v-control-win-x64-v*.exe + build/hyperv-control/release/hyper-v-control-plugin-v*-win-x64.zip + build/hyperv-control/release/hyper-v-control-v*-release.json + build/hyperv-control/release/hyper-v-control-v*-SHA256SUMS.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b9219ce --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,54 @@ +# Maintaining and extending the marketplace + +Each plugin is an independent product. Keep its installed files self-contained, its dependencies explicit, and its releases separate. Shared code belongs at the repository level only when multiple plugins actually use it. + +## Repository map + +| Location | Responsibility | +| --- | --- | +| `.agents/plugins/marketplace.json` | Discovery catalog: plugin IDs, locations, and categories | +| `plugins//` | Installable package: manifest, skill, user documentation, helpers, and licenses | +| `src//` | Native application or MCP implementation; currently Hyper-V Control | +| `tests/.Tests/` | Native protocol and behavior validation | +| `scripts/` | Maintainer builds, packaging, and repository checks; never an installed plugin dependency | +| `docs/` | Build/release procedures and recorded validation evidence | +| `sources/`, `patches/`, `bundle.lock.json` | Pinned Rizin upstream sources, compatibility patches, and build dependencies | +| `build/` | Ignored generated files, downloads, binaries, and local experiment output | + +The older `build-bundle`, `package-bundle`, and `verify-bundle` scripts belong to the Rizin runtime. Hyper-V uses `build-hyperv-control.ps1`. New component-specific tooling should use explicit names or its own subdirectory; do not add unrelated behavior to the Rizin builders. + +Within Hyper-V Control, `HyperVTools*` exposes the MCP contract, `Services/` owns host/guest operations and resource lifetimes, and `Extracted/` contains adapted RaivenX functionality. Keep protocol handling out of the extracted layer. Changes to VM state, credentials, elevation, or debugger lifetime need behavior tests at their corresponding boundary. + +## Sources of truth + +- Edit `plugins//plugin.json` for plugin identity, version, and interface metadata. Run `python scripts/check-marketplace.py --sync` to generate `.codex-plugin/plugin.json`; do not maintain the compatibility copy independently. +- Compiled downloads use the plugin's `runtime.json` for the exact artifact and hash. Rizin's independently versioned runtime and build inputs are in `bundle.lock.json`. Keep dependency versions in metadata and lockfiles. +- Hyper-V's project, CLI, and protocol versions must match its plugin manifest. The repository checker rejects partial updates; the build verifies the executable version and runtime hash. +- README files explain purpose, setup, and usage. Keep current version numbers, release dates, and changelogs out of them. The [download catalog](docs/releases.md#release-index) is the maintained entrypoint for current releases. +- Skills explain how an agent should choose tools and interpret results. Put detailed task procedures in their `references/` directory and scripts needed at runtime inside the plugin. +- Record experiments in validation reports. Imported Frida material under `references/legacy/` and `docs/migration/` is historical evidence, not the maintained entrypoint; preserve its provenance and licenses. + +Links inside distributed plugin documentation must resolve inside that plugin or use an absolute repository/web URL. A relative link to `../../docs/` works in a checkout but breaks when the plugin ZIP is extracted. + +## Add a plugin + +1. Choose a stable lowercase ID and create `plugins//` with `plugin.json`, `README.md`, `LICENSE`, and `skills//SKILL.md`. Keep plugin content in English. Add only the references, assets, and helpers that the installed plugin needs. +2. Add a local catalog entry pointing to `./plugins/`, then run the manifest sync/check command. New catalog plugins are discovered by the checker automatically. +3. If it needs a native executable, put its source and tests under `src/` and `tests/`. Give it a dedicated builder, verified installer, and versioned installation directory. A source-only skill/CLI plugin does not need an MCP server or binary release. +4. Add component-specific validation to the existing PR workflow. Keep expensive job selection in `scripts/ci-plan.py`; extend it for the component's actual inputs. Do not introduce a second push or tag workflow for the same checks. +5. Test an extracted package in a fresh directory. It must work without the repository checkout, another plugin, or a developer's absolute paths. Follow the [release guide](docs/releases.md) for publication and asset naming. + +## Check a change + +```powershell +python scripts/check-marketplace.py +python scripts/test-plugin-packaging.py +``` + +These fast checks validate the catalog, compatibility manifests, bundled skill paths, runtime pins, README policy, entrypoint links, and Rizin plugin packaging. They do not install plugin dependencies or operate a VM. + +The single PR workflow runs these checks for all changes. It runs Windows build/protocol/installer checks only when their inputs change. Pure documentation changes avoid native builds, newer commits cancel obsolete runs, and merging or tagging does not repeat CI. Use a manual workflow run when downloadable build artifacts are needed. + +For behavior changes, also run the affected component's documented tests: [Hyper-V Control](plugins/hyper-v-control/README.md#development-and-validation), [Rizin](docs/build.md), [Frida](scripts/frida-use-experiments/README.md), or [Capstone](plugins/capstone-binary-patching/README.md#validation-and-boundaries). Live tests must have a defined target, restoration plan, and recorded limits; CI never discovers and operates on a developer's VMs automatically. + +Before removing a release, check both runtime installers and build lockfiles for references. Preserve active dependencies first. Published primary EXEs and ZIPs are immutable; publish changed bytes under a new version. Documentation-only edits do not require rebuilding an unchanged runtime. diff --git a/README.md b/README.md index 4bb91f8..a453aaa 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,41 @@ # Jerry's Plugin Marketplace -A personal Codex plugin monorepo. Each plugin has its own identity, version, installation directory and release stream. +**Windows reverse engineering and automation for AI agents.** -| Plugin | What it provides | -| --- | --- | -| [Rizin RE Toolkit](plugins/rizin-re-toolkit) | A portable Windows x64 Rizin CLI, RetDec/Ghidra/jsdec decompilers, YARA, FLIRT, and a skill for native binary and memory-dump analysis. | -| [Capstone Binary Patching](plugins/capstone-binary-patching) | A uv-managed Capstone/LIEF CLI and skill for binary patches, instruction diffs, patch porting, verification and rollback, with native Windows experiments. | -| [Frida Use](plugins/frida-use) | Windows-focused live instrumentation, Python/JavaScript debugging, API tracing, malware analysis, reverse engineering, and reversible runtime patching. | -| [Hyper-V Control](plugins/hyper-v-control) | A compiled C# stdio MCP EXE and skill for VM lifecycle, checkpoints, Basic/Enhanced computer use, guest files/UI, and user/kernel debugging. | +A collection of focused plugins for understanding software, investigating live behavior, making verifiable changes, and running repeatable experiments. Each plugin combines specialist tools with guidance that helps your agent choose a useful workflow and interpret the results. -## Add to Codex +## The plugins -```powershell -codex plugin marketplace add JerryLinLinLin/jerry-plugin-marketplace --ref main -``` - -Open the plugin directory, select **Jerry's Plugin Marketplace**, and install **Rizin RE Toolkit**, **Capstone Binary Patching**, **Frida Use**, or **Hyper-V Control** as needed. A normal marketplace clone does not need the build-source submodules. Rizin and Hyper-V Control download their own verified runtimes from separate release streams. Frida Use bundles its own skill, scripts, and references; install the Frida runtime in your analysis environment as described in its README. +### [Rizin RE Toolkit](plugins/rizin-re-toolkit) -**Hyper-V Control:** plugin/skill ID `hyper-v-control`, invocation `$hyper-v-control`, version `0.1.0`. Its C# stdio MCP is distributed as a self-contained Windows x64 EXE. A complete plugin ZIP includes the EXE; for a marketplace source installation, run [its installer](plugins/hyper-v-control/scripts/install.ps1) before reconnecting the MCP. See [setup and validation](plugins/hyper-v-control/README.md). +Explore native executables and memory dumps without starting from scratch. Disassembly, multiple decompilers, signatures, and pattern matching help you understand unfamiliar code and cross-check what you find. A good starting point for binary triage, program analysis, and investigating captured memory. -**Capstone Binary Patching** is a separate skill-and-CLI plugin for patching work; see its -[setup and experiments](plugins/capstone-binary-patching). Its Python dependencies are managed by uv, -and it requires no MCP server or account connection. +### [Frida Use](plugins/frida-use) -**Frida Use:** plugin/skill ID `frida-use`, invocation `$frida-use`, version `1.0.0`. Its full source is vendored under `plugins/frida-use`; it has no dependency on the former standalone project. See its [research notes](plugins/frida-use/skills/frida-use/references/research-sources.md). Maintainer experiments and results live separately in [scripts/frida-use-experiments](scripts/frida-use-experiments) and [docs/frida-use-validation.md](docs/frida-use-validation.md). +See what a program actually does while it runs. Trace API calls, inspect arguments and return values, and try reversible changes to live behavior. Use it to investigate a suspicious call, follow a runtime-only code path, or test a hypothesis from static analysis. -**Rizin RE Toolkit:** plugin/skill ID `rizin-re-toolkit`, invocation `$rizin-re-toolkit`. Automatic skill selection is enabled. Native RE requests mentioning Ghidra, IDA/Hex-Rays, Binary Ninja, Cutter, radare2, and related tools route to the toolkit's equivalent CLI workflow by default. Ghidra requests use its bundled `pdg` engine. Native application projects, tool-specific development, and unsupported debugging workflows receive a capability check rather than a claim of compatibility. +### [Capstone Binary Patching](plugins/capstone-binary-patching) -**Upgrading from Rizin Windows RE:** refresh the marketplace (`codex plugin marketplace upgrade my-plugin-marketplace`), install **Rizin RE Toolkit**, and remove the old **Rizin Windows RE** installation if present. The old ID `rizin-windows-re` has been replaced; an installed copy is not automatically renamed. The marketplace ID remains `my-plugin-marketplace`. +Turn a proposed binary change into a precise, verifiable patch. Compare bytes and instructions, construct patches, check the result, and roll changes back. Useful when you need to explain exactly what changed, port a patch between versions, or preserve the original file for comparison. -The catalog is [.agents/plugins/marketplace.json](.agents/plugins/marketplace.json), following the [official OpenAI plugin marketplace format](https://developers.openai.com/plugins/build/plugins). Plugin paths are relative to the repository root. +### [Hyper-V Control](plugins/hyper-v-control) -## Releases and downloads +Give your agent control of a Windows VM lab: manage VM lifecycles and checkpoints, interact with guest desktops, transfer files, and debug applications or the Windows kernel. Checkpoints make experiments repeatable, while desktop interaction and debugging let you investigate the same VM from several angles. -| Component | Release | What to download | -| --- | --- | --- | -| Hyper-V Control | [0.1.0](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/hyper-v-control-v0.1.0) | Namespaced Windows x64 EXE or complete plugin ZIP | -| Rizin RE Toolkit | [0.4.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) | Complete plugin ZIP with its skill and isolated, paginated runtime installer | -| Rizin portable runtime | [0.3.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-v0.3.1) | Existing runtime bundle and its unchanged `SHA256SUMS` | +Use any plugin on its own, or combine them: understand a binary with Rizin, inspect its behavior with Frida, verify a patch with Capstone, and use Hyper-V to repeat the experiment from a known state. -Use the [release organization guide](docs/releases.md) for tag/asset naming, per-plugin checksum pins, independent runtime versions and publication steps. Installers do not use the repository-wide Latest release to select a plugin. Existing Rizin URLs remain compatible. - -## Portable Rizin download - -Get `rizin-windows-x64-bundle-v0.3.1.zip` and `SHA256SUMS` from the [Rizin release](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-v0.3.1). Verify SHA-256, extract the complete `rizin` directory, and run: +## Get started ```powershell -& 'C:\path\to\rizin\bin\rizin.exe' -v +codex plugin marketplace add JerryLinLinLin/jerry-plugin-marketplace --ref main ``` -Windows 10 (1903+) or Windows 11 x64 is required. Runtime DLLs are included beside the executables; no administrator installation or system PATH change is needed. Move the whole folder together. Paths containing spaces are supported. - -For a user-level install, run the plugin's [download helper](plugins/rizin-re-toolkit/skills/rizin-re-toolkit/scripts/install.ps1). It selects a stable Rizin asset, verifies its checksum, and extracts to `%LOCALAPPDATA%\Programs\Rizin\`. `-AddToUserPath` optionally adds its `bin` directory to the user's PATH. - -## Add another plugin - -Write all plugin content in English, including documentation, skill instructions, -metadata, script comments, and bundled references. Summarize sources in English -and use English link labels even when the original source is in another language. - -1. Create `plugins//plugin.json` and `skills//SKILL.md` within that folder. Keep referenced assets and scripts inside the plugin. -2. Add its entry to `.agents/plugins/marketplace.json`, using `source.path: ./plugins/`, a category, and installation/authentication policies. -3. Bump the plugin's semantic version when shipping changes. Follow [the release conventions](docs/releases.md) for component tags, namespaced assets and isolated runtime installation. Keep large binaries in GitHub Releases. -4. Validate the manifest and skill, then test discovery with Codex. - -Rizin includes a portable Agent Plugins manifest and a `.codex-plugin/plugin.json` compatibility manifest. It is a CLI-and-skill plugin and needs no MCP server or account connection. - -## Build and verification +In Codex, open **Jerry's Plugin Marketplace** and install the plugins you need. Each plugin includes its skill. Follow the linked setup guides above for runtime requirements, then describe the task to your agent. -This is a plugin monorepo. Hyper-V Control's C# source is under `src/HyperVControl`, its protocol/live validation harness under `tests/HyperVControl.Tests`, and its distributable plugin under `plugins/hyper-v-control`. Build its self-contained EXE and plugin ZIP with `scripts/build-hyperv-control.ps1`; see [Hyper-V Control](plugins/hyper-v-control/README.md) for runtime setup and [feature extraction](plugins/hyper-v-control/docs/extraction.md). +## Downloads -See [the build guide](docs/build.md), [component lock file](bundle.lock.json), and [release validation](docs/validation-v0.3.1.md). Build sources are pinned under `sources/`; Windows compatibility patches live under `patches/`. Generated files stay in the ignored `build/` directory. +The [download catalog](docs/releases.md#release-index) lists prebuilt Windows packages: a standalone EXE or complete plugin for Hyper-V Control, and a complete plugin plus portable runtime for Rizin RE Toolkit. -## License +Frida Use and Capstone Binary Patching are available through the marketplace. Install only what you need; plugins have independent setup and releases. -Marketplace code and skill: [MIT](LICENSE). Runtime components retain their upstream licenses. The bundle includes component notices and source revision information; MIT does not replace upstream terms. +[Contributing](CONTRIBUTING.md) · [Release guide](docs/releases.md) · [MIT license](LICENSE). Bundled third-party components retain their own licenses. diff --git a/bundle.lock.json b/bundle.lock.json index 77e148b..b5d4bc9 100644 --- a/bundle.lock.json +++ b/bundle.lock.json @@ -41,7 +41,7 @@ "retdec": { "version": "5.0", "commit": "8272d0355794f8b8a63d8611b1dea50b4f2d87c3", - "sdk": "Verified v0.1.0 bundle SDK, same upstream revision" + "sdk": "Verified RetDec SDK asset from rizin-v0.3.1, same upstream revision" }, "yara": { "version": "4.5.8", @@ -59,9 +59,9 @@ "sha256": "45ffa004e26653eaee8d262b8e6eeae09402a7d319c1f20a2ba794bd6af1cc28" }, "retdecSdk": { - "file": "rizin-windows-x64-bundle-v0.1.0.zip", - "url": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/download/v0.1.0/rizin-windows-x64-bundle-v0.1.0.zip", - "sha256": "66be7b2708e773b16e6318c68ec8aa25b7ba331b5eed1b444942f0a31b8c50ba" + "file": "rizin-retdec-sdk-win-x64-v0.3.1.zip", + "url": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/download/rizin-v0.3.1/rizin-retdec-sdk-win-x64-v0.3.1.zip", + "sha256": "bdd8b176be07b3146d91f5b487ebbeaede2f1149953572d3dc741d4aab90919b" }, "openssl3": { "file": "openssl-3.5.9.zip", diff --git a/docs/build.md b/docs/build.md index a70f0d4..44420ae 100644 --- a/docs/build.md +++ b/docs/build.md @@ -17,7 +17,7 @@ The build verifies source revisions, applies patches once, hash-checks downloads YARA is checked out sparsely before materializing files, excluding its antivirus-sensitive fuzz corpus. No antivirus exclusion or protection change is needed. Avoid recursively checking out that separate Meson dependency's test corpus. -RetDec's upstream SDK revision is unchanged. The hash-locked SDK from release v0.1.0 is reused while core_retdec.dll is rebuilt for Rizin 0.9.1. VS 2026 is needed to link that SDK. OpenSSL 1.1.1w remains its ABI dependency; YARA uses OpenSSL 3.5.9 LTS. +RetDec's upstream SDK revision is unchanged. The hash-locked `rizin-retdec-sdk-win-x64-v0.3.1.zip` asset contains the headers, libraries, CMake files, support data, and licenses needed to rebuild core_retdec.dll for Rizin 0.9.1. These files were preserved byte-for-byte from the former v0.1.0 bundle; `sdk-provenance.json` records their origin. The SDK is downloaded from the retained `rizin-v0.3.1` release into `build/retdec-sdk`, so a clean build does not depend on deleted releases. VS 2026 is needed to link that SDK. OpenSSL 1.1.1w remains its ABI dependency; YARA uses OpenSSL 3.5.9 LTS. ## Verification @@ -41,17 +41,17 @@ After packaging, extract the archive into a new path with spaces and Unicode and powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-bundle.ps1 -Version 0.3.1 ``` -This creates a runtime ZIP, plugin ZIP, standalone skill package, and SHA256SUMS. The command reproduces the currently locked runtime version. For a new CLI release, increment the bundle version in the lock file and tag the tested source commit with a new `rizin-v` tag. Other marketplace plugins can use their own tag prefixes. +This creates a runtime ZIP, complete plugin ZIP, runtime manifest, and SHA256SUMS. The command reproduces the currently locked runtime version. For a new CLI release, increment the bundle version in the lock file and tag the tested source commit with a new `rizin-v` tag. Other marketplace plugins can use their own tag prefixes. Plugin releases are independent of the CLI bundle version. The runtime ZIP uses `bundle.lock.json` and the requested runtime version; the complete plugin ZIP uses the version in `plugins/rizin-re-toolkit/plugin.json`. Skills are included inside the plugin ZIP, with no separate skill archive. For a skill-only or metadata update, package without rebuilding or republishing the runtime: ```powershell -powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-bundle.ps1 -PluginOnly -Version 0.4.0 -OutputDir build\plugin-release-0.4.0 +powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-bundle.ps1 -PluginOnly -Version 0.4.1 -OutputDir build\plugin-release-0.4.1 ``` -Publish those files under `rizin-re-toolkit-v0.4.0`. The CLI installer searches release assets for the runtime prefix, so a newer plugin-only release is not mistaken for a runtime download. The native runtime remains at `rizin-v0.3.1` until a separate CLI release is built and tested. Earlier validation reports retain their original plugin IDs and versions as historical evidence. +This reproduces the current plugin version locally; do not overwrite its published ZIP. For a new release, bump the plugin version and publish under the matching `rizin-re-toolkit-v` tag. The CLI installer searches release assets for the runtime prefix, so a newer plugin-only release is not mistaken for a runtime download. The native runtime remains at `rizin-v0.3.1` until a separate CLI release is built and tested. Earlier validation reports retain their original plugin IDs and versions as historical evidence. Validate discovery without changing user configuration: diff --git a/docs/releases.md b/docs/releases.md index 4319092..247f5e6 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -19,7 +19,7 @@ The marketplace's source of truth for plugin identity/version remains `plugins/< | Item | Pattern | Hyper-V example | | --- | --- | --- | | Git tag | `-v` | `hyper-v-control-v0.1.0` | -| Release title | ` — ` | `Hyper-V Control 0.1.0 — Windows x64 MCP and Plugin` | +| Release title | ` ` | `Hyper-V Control 0.1.0` | | Standalone executable | `--v.exe` | `hyper-v-control-win-x64-v0.1.0.exe` | | Complete plugin ZIP | `-plugin-v[-].zip` | `hyper-v-control-plugin-v0.1.0-win-x64.zip` | | Multi-file runtime ZIP, when needed | `-runtime--v.zip` | Use when an EXE requires adjacent runtime files | @@ -28,7 +28,7 @@ The marketplace's source of truth for plugin identity/version remains `plugins/< Use .NET-style runtime identifiers such as `win-x64`, `win-arm64`, `linux-x64`, and `osx-arm64`. A filename should stay unambiguous when copied into a shared Downloads directory. An installed executable may have a stable local name such as `HyperVControl.exe`; the installer maps the namespaced download to that name inside the plugin's own versioned directory. -Skills belong inside the complete plugin ZIP and are installed with the plugin. Do not publish a redundant standalone `.skill` download for a new plugin release. Historical standalone skill assets remain available at their original release URLs. +Skills belong inside the complete plugin ZIP and are installed with the plugin. Do not publish a redundant standalone `.skill` download. For a genuinely independent runtime version, use a separate `-runtime-v` stream and pin the relationship from the consuming plugin. A plugin may update documentation without rebuilding a large, unchanged runtime. Existing Rizin runtime tags (`rizin-v0.3.1`) and asset names are legacy compatibility contracts and are not renamed. @@ -39,7 +39,27 @@ For a genuinely independent runtime version, use a separate `-runtim - When latest-in-stream discovery is necessary, filter both tag family and asset name, skip drafts/prereleases, paginate until the stream is found, and verify the selected asset checksum. Rizin's installer follows this path and retains its legacy `SHA256SUMS` lookup. - Keep install directories separate and versioned. Reuse a matching verified installation; do not overwrite a different checksum in place or alter a global PATH implicitly. Rizin's user PATH change remains opt-in; Hyper-V uses an absolute executable path. - Keep published runtime binaries and plugin ZIPs immutable. Fix their contents with a new patch version. Release notes and inventories may be corrected, and redundant ancillary downloads may be removed with their checksum entries; these editorial changes must preserve the executable/ZIP hashes and existing runtime URLs. -- Publish independent plugin releases with `--latest=false`. The global GitHub Latest badge is not a plugin index. This preserves existing legacy behavior; the table above is the entrypoint for choosing a component. +- Publish independent plugin releases with `--latest=false`. The global GitHub Latest badge is not a plugin index and may change when obsolete releases are removed. The table above is the entrypoint for choosing a component. + +## Release retention + +Keep the current release for each component and any runtime release that an active plugin still requires. Remove superseded releases and their assets; keep Git tags and source history. Compare versions within their own stream: Rizin RE Toolkit 0.4.1 still uses the Rizin 0.3.1 runtime, so both remain current. The retired `v0.1.0`, `rizin-v0.3.0`, and `rizin-re-toolkit-v0.4.0` releases are no longer part of the download catalog. + +The retained Rizin runtime release contains only its runtime, build SDK, and integrity/provenance files. Its obsolete plugin and standalone skill downloads have been removed. The RetDec SDK is a separate maintainer asset pinned in `bundle.lock.json`; its original files and licenses are preserved, allowing the v0.1.0 release to be retired without breaking clean builds. + +## Release notes + +Use a short product/version title, a one-sentence introduction, and at most four bullets describing changes that matter to users. Link directly to the primary downloads and setup guide. Keep implementation details, asset inventories, installation paths, and test logs in the documentation or attached metadata. + +Keep repository and plugin READMEs evergreen: describe purpose, setup, and usage without repeating current versions, release dates, revision tables, or versioned download URLs. Link to the download catalog. Plugin versions and dependency pins belong in manifests/lockfiles; version-specific changes and measured results belong in release notes and validation reports. + +## CI without duplicate runs + +Automatic validation runs only for pull requests targeting `main`. The fast catalog/packaging checks cover every plugin; `scripts/ci-plan.py` selects Windows validation only when its implementation, installer, or build inputs change. Branch pushes, merge commits, and tags do not launch another copy. Markdown-only changes skip the native build. Updating a PR cancels its obsolete run, and NuGet packages are cached between runs. + +PR validation builds the executable and plugin, checks the pinned executable hash, and runs protocol, installer-isolation, and packaging tests. Large build artifacts are uploaded only for an explicit `workflow_dispatch` run, which publishes no GitHub Release by itself. Use that manual action when a downloadable build is needed; ordinary PRs do not need a second run after merging. + +See [the maintenance guide](../CONTRIBUTING.md) for repository ownership, adding plugins, and local checks. ## Packaging and publication @@ -60,7 +80,7 @@ hyper-v-control-v0.1.0-SHA256SUMS.txt The ZIP contains the EXE, manifests, skill, documentation, launcher, installer, and licenses. The EXE-only download is for direct stdio MCP configuration. Local convenience aliases (`HyperVControl.exe`, `SHA256SUMS`) are not additional public Hyper-V assets. The inventory records primary asset names, roles, platforms, sizes and hashes; the checksum file also covers the inventory and does not hash itself. -Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its installation package is the complete plugin ZIP. The release also provides a namespaced asset inventory/checksum file and retains its existing `SHA256SUMS` URL for compatibility. The existing `rizin-v0.3.1` runtime release is left untouched. Future Rizin runtime releases retain the existing runtime asset family and legacy `SHA256SUMS` while older runtime installers are supported; new plugin-only releases use the namespaced checksum filename. +Rizin RE Toolkit 0.4.1 is an installer-only maintenance release; its runtime remains 0.3.1. Its installation package is the complete plugin ZIP. The release also provides a namespaced asset inventory/checksum file and retains its existing `SHA256SUMS` URL for compatibility. The `rizin-v0.3.1` runtime ZIP and its checksum entry remain unchanged. Future Rizin runtime releases retain the existing runtime asset family and legacy `SHA256SUMS` while older runtime installers are supported; new plugin-only releases use the namespaced checksum filename. ## Validation diff --git a/plugins/capstone-binary-patching/.codex-plugin/plugin.json b/plugins/capstone-binary-patching/.codex-plugin/plugin.json index 0448854..174a566 100644 --- a/plugins/capstone-binary-patching/.codex-plugin/plugin.json +++ b/plugins/capstone-binary-patching/.codex-plugin/plugin.json @@ -2,11 +2,22 @@ "name": "capstone-binary-patching", "version": "0.1.0", "description": "Instruction-aware binary patching, diffs and rollback through a uv-managed Capstone CLI and focused workflows.", - "author": {"name": "JerryLinLinLin", "url": "https://github.com/JerryLinLinLin"}, + "author": { + "name": "JerryLinLinLin", + "url": "https://github.com/JerryLinLinLin" + }, "homepage": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace", "repository": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace", "license": "MIT", - "keywords": ["capstone", "binary-patching", "binary-diff", "keystone", "lief", "firmware", "uv"], + "keywords": [ + "capstone", + "binary-patching", + "binary-diff", + "keystone", + "lief", + "firmware", + "uv" + ], "skills": "./skills/", "interface": { "displayName": "Capstone Binary Patching", @@ -14,8 +25,14 @@ "longDescription": "A skill and CLI for native binary patch construction, instruction-aware diffs, patch porting and rollback. Uses uv-managed Capstone and LIEF with optional Keystone assembly. Includes PE, ELF, Mach-O, firmware and analysis-copy workflows, hash-bound patch plans, and reproducible native Windows experiments. No MCP server or account connection.", "developerName": "JerryLinLinLin", "category": "Security", - "capabilities": ["Read", "Write", "Execute"], + "capabilities": [ + "Read", + "Write", + "Execute" + ], "websiteURL": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace", - "defaultPrompt": ["Use Capstone Binary Patching to create and validate a reversible binary patch."] + "defaultPrompt": [ + "Use Capstone Binary Patching to create and validate a reversible binary patch." + ] } } diff --git a/plugins/capstone-binary-patching/README.md b/plugins/capstone-binary-patching/README.md index 479a1fc..1482ca4 100644 --- a/plugins/capstone-binary-patching/README.md +++ b/plugins/capstone-binary-patching/README.md @@ -1,71 +1,41 @@ # Capstone Binary Patching -Skill + CLI plugin for constructing, comparing, validating and reversing native binary patches. -Version **0.1.0**. Plugin and skill ID: **`capstone-binary-patching`**. -Invoke as **`$capstone-binary-patching`**; automatic discovery is enabled. -No MCP server, account connection or bundled Python runtime. +Create precise native binary patches and verify exactly what changed. The plugin combines instruction analysis with a CLI for planning, applying, checking, and reversing edits while preserving the original input. -Capstone decodes instructions; optional Keystone assembles them; LIEF parses executable mappings. -The bundled CLI produces hash-bound plans and writes equal-length edits to new files. -It covers PE, linked ELF, thin Mach-O and explicitly mapped raw inputs. General decompilation -remains with the existing RE tools. Python, dependencies and execution are managed with **uv**. +## What it helps with -The [skill](skills/capstone-binary-patching/SKILL.md) and its English workflow references cover: +- Compare bytes and instructions before and after a change. +- Build instruction, branch, NOP, and data patches, including multi-part edits. +- Port patches between versions and check address mappings across PE, ELF, Mach-O, and raw inputs. +- Verify patched bytes and restore the original file with exact rollback. -- Instruction, branch, NOP and data patches; multi-hunk plans and exact rollback. -- Byte diffs, matched-function instruction diffs and cross-version patch porting. -- PE/ELF/Mach-O addresses, ASLR, ARM/Thumb/AArch64/MIPS firmware constraints. -- Longer patches and trampolines, analysis-only deobfuscation copies, CPU validation and delta delivery. -- [English and Chinese primary-source research](skills/capstone-binary-patching/references/sources.md). +Capstone decodes instructions, LIEF interprets executable mappings, and optional Keystone support assembles replacements. The [agent workflow](skills/capstone-binary-patching/SKILL.md) explains when additional analysis or platform testing is needed. -## Install and run +## Install and use -The marketplace catalog includes **Capstone Binary Patching**. Publishing/installing this checkout -is separate from editing it; refresh the marketplace after this version is actually published. -For local CLI use, follow the [uv setup guide](skills/capstone-binary-patching/references/setup.md): +Install **Capstone Binary Patching** from **Jerry's Plugin Marketplace** and follow the [setup guide](skills/capstone-binary-patching/references/setup.md). Python and dependencies are managed with **uv**; no MCP server or account connection is required. + +Invoke `$capstone-binary-patching`, or ask your agent to inspect a proposed patch. For direct CLI use: ```powershell -$patchCli = 'C:\absolute\path\to\capstone-binary-patching\skills\capstone-binary-patching\scripts\patchkit.py' -uv python install 3.13 +$patchCli = 'C:\path\to\capstone-binary-patching\skills\capstone-binary-patching\scripts\patchkit.py' uv run --managed-python --locked $patchCli doctor uv run --managed-python --locked $patchCli --help uv run --managed-python --locked $patchCli info '.\original.exe' ``` -Core packages are pinned to Capstone 5.0.9 and LIEF 1.0.0, with a script lockfile. -Assembly adds `--with keystone-engine==0.9.2`. See [patching](skills/capstone-binary-patching/references/patching.md) -for the spec schema and plan/apply/verify/revert commands. All writes use new, nonexisting paths. +Dependency versions are managed by the script metadata and lockfile. See the [patching guide](skills/capstone-binary-patching/references/patching.md) for assembly setup and the plan, apply, verify, and revert workflow. + +## Validation and boundaries -## Reproduce the actual experiments +Patches are written to new files. Successful decoding does not prove equivalent behavior: validate each change on its intended platform. The CLI does not attach to processes, execute inputs, grow files, relocate instructions, or repair executable signatures. -From the repository root, on Windows with existing MSVC x64 build tools and uv: +The [experiment harness](experiments/run_experiments.py) builds a controlled Windows fixture and checks its behavior before patching, after patching, and after rollback. To run it from the repository root with MSVC x64 tools and uv: ```powershell -$env:UV_CACHE_DIR = Join-Path (Get-Location) 'build\capstone-uv-cache' uv run --managed-python --locked '.\plugins\capstone-binary-patching\experiments\run_experiments.py' --out '.\build\capstone-experiments\my-run' ``` -Choose a new output directory each time. The harness compiles the readable [fixture.c](experiments/fixture.c), -executes the EXE, invokes the real CLI to locate/assemble/plan/apply/verify a patch, executes the patched -EXE, reverts it, and executes the restored EXE. It compares stdout, exit codes and whole-file hashes. -It builds its tiny Kernel32 import library locally and needs no CRT headers or downloaded binary fixture. - -It also exercises CLI refusal paths, emulates seven instruction modes using Unicorn 2.1.4, -checks a conditional branch with three inputs, mixes code/data edits, and tests constructed ELF/Mach-O -mappings. `--emulation-only` omits the native Windows compilation step on other hosts; it is not an -OS loader test. The harness never executes arbitrary user-provided samples. - -Evidence includes `summary.json`, `transcript.jsonl` with actual arguments/stdout/stderr/exit codes, -EXEs, raw fixtures, specs and plans. Generated files remain under ignored `build/`. -See the [validation report](../../docs/validation-capstone-binary-patching-v0.1.0.md) for the recorded run -and the limits of that evidence. These are end-to-end experiments, not mocked unit tests. - -## Boundaries - -The CLI does not recover CFGs, prove semantic equivalence, relocate stolen instructions, grow files, -attach to processes, repair signatures/checksums or execute inputs. Advanced references explain -when to use additional tools. A decodable patch still needs behavior validation on its intended platform. -Base CLI is designed for Windows/Linux/macOS Python environments; native validation here is Windows x64. +Choose a fresh output directory. The harness records commands, output, exit codes, and hashes; it also checks instruction emulation and format mappings. See the [reference guides](skills/capstone-binary-patching/references) for platform limits and advanced workflows. -Plugin code and instructions are [MIT](LICENSE). Dependencies keep their upstream licenses and are -downloaded by uv rather than redistributed inside this plugin. +Plugin code and instructions are [MIT](LICENSE). Dependencies retain their upstream licenses. diff --git a/plugins/frida-use/.codex-plugin/plugin.json b/plugins/frida-use/.codex-plugin/plugin.json index a6a791a..7e632d5 100644 --- a/plugins/frida-use/.codex-plugin/plugin.json +++ b/plugins/frida-use/.codex-plugin/plugin.json @@ -23,7 +23,7 @@ "interface": { "displayName": "Frida Use", "shortDescription": "Windows debugging and instrumentation with Frida.", - "longDescription": "Windows-focused Frida workflows for debugging Python controllers, injected JavaScript and native targets; API tracing, malware analysis, reverse engineering, and reversible runtime patching. Includes executable helpers, practical examples, and Chinese/English research notes.", + "longDescription": "Windows-focused Frida workflows for debugging Python controllers, injected JavaScript and native targets; API tracing, malware analysis, reverse engineering, and reversible runtime patching. Includes executable helpers, practical examples, and focused reference guides.", "developerName": "JerryLinLinLin", "category": "Security", "capabilities": [ diff --git a/plugins/frida-use/README.md b/plugins/frida-use/README.md index 04af638..4a37ac6 100644 --- a/plugins/frida-use/README.md +++ b/plugins/frida-use/README.md @@ -50,9 +50,9 @@ The default agent observes file opens and records at most 200 events. Select a c The runner writes UTF-8 `events.jsonl` and binary attachments with SHA-256 hashes. Capture duration defaults to 30 seconds. It records dropped events, truncation, JavaScript errors, available Windows exit codes, and Frida crash information. `--kill-on-exit` applies only to a process spawned by the runner. Attach mode detaches on exit. -## Version scope +## Scope -Documentation reviewed on **2026-10-01**, using **Frida 17.19.0 / frida-tools 14.10.4** as reference versions. The two packages have independent version numbers. Check the installed versions and release notes when using a different release. +Frida and frida-tools have independent release cycles. Use the [setup guide](skills/frida-use/references/setup.md) to check your installed environment and the upstream release notes for compatibility changes. Windows user-mode x86/x64 is the main focus. Check ARM64, remote server/Gadget, Barebone, managed runtimes, and third-party GUI capabilities separately. ## License diff --git a/plugins/frida-use/plugin.json b/plugins/frida-use/plugin.json index f3e2146..dc467a9 100644 --- a/plugins/frida-use/plugin.json +++ b/plugins/frida-use/plugin.json @@ -26,7 +26,7 @@ "interface": { "displayName": "Frida Use", "shortDescription": "Windows debugging and instrumentation with Frida.", - "longDescription": "Windows-focused Frida workflows for debugging Python controllers, injected JavaScript and native targets; API tracing, malware analysis, reverse engineering, and reversible runtime patching. Includes executable helpers, practical examples, and Chinese/English research notes.", + "longDescription": "Windows-focused Frida workflows for debugging Python controllers, injected JavaScript and native targets; API tracing, malware analysis, reverse engineering, and reversible runtime patching. Includes executable helpers, practical examples, and focused reference guides.", "developerName": "JerryLinLinLin", "category": "Security", "capabilities": [ diff --git a/plugins/hyper-v-control/.codex-plugin/plugin.json b/plugins/hyper-v-control/.codex-plugin/plugin.json index 0ea1f53..4facdc9 100644 --- a/plugins/hyper-v-control/.codex-plugin/plugin.json +++ b/plugins/hyper-v-control/.codex-plugin/plugin.json @@ -1,15 +1,38 @@ { "name": "hyper-v-control", "version": "0.1.0", - "description": "Hyper-V lifecycle, graphical guest control, and Windows debugging with a compiled C# stdio MCP.", + "description": "Control Hyper-V VMs, graphical consoles, guest automation and user/kernel debugging through a native C# stdio MCP server.", + "author": { + "name": "JerryLinLinLin", + "url": "https://github.com/JerryLinLinLin" + }, + "repository": "https://github.com/JerryLinLinLin/jerry-plugin-marketplace", + "license": "MIT", + "keywords": [ + "hyper-v", + "windows", + "virtual-machine", + "debugger", + "windbg", + "mcp" + ], "skills": "./skills/", "mcpServers": "./.mcp.json", "interface": { "displayName": "Hyper-V Control", "shortDescription": "VM lifecycle, computer use, and Windows debugging.", + "longDescription": "A compiled Windows x64 C# MCP server over stdio. Manage VM lifecycle and checkpoints, operate Basic and Enhanced consoles, transfer files, automate guest UI with winapp, and debug user processes or a guest kernel with current WinDbg engines.", "developerName": "JerryLinLinLin", "category": "Developer Tools", - "capabilities": ["Read", "Write", "Execute"], - "logo": "./assets/icon.svg" + "capabilities": [ + "Read", + "Write", + "Execute" + ], + "logo": "./assets/icon.svg", + "brandColor": "#1674D1", + "defaultPrompt": [ + "Use Hyper-V Control to inspect my VMs and choose the right management, automation, or debugging workflow." + ] } } diff --git a/plugins/hyper-v-control/README.md b/plugins/hyper-v-control/README.md index eec40da..5ba8a71 100644 --- a/plugins/hyper-v-control/README.md +++ b/plugins/hyper-v-control/README.md @@ -1,46 +1,47 @@ # Hyper-V Control -A Windows x64 C# MCP server over standard input/output for Hyper-V lifecycle, checkpoints, graphical guest control, file transfer and user/kernel debugging. The distributed `HyperVControl.exe` is self-contained: end users need neither Python nor a .NET SDK/runtime installation. +Manage a Hyper-V lab from your AI agent. Create and restore experiments, interact with guest desktops, move files, and investigate Windows applications or the kernel through one MCP connection. -## Run +## What it helps with -Get the [Windows x64 EXE](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/download/hyper-v-control-v0.1.0/hyper-v-control-win-x64-v0.1.0.exe) or [complete plugin ZIP](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/download/hyper-v-control-v0.1.0/hyper-v-control-plugin-v0.1.0-win-x64.zip) from [release 0.1.0](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/hyper-v-control-v0.1.0). The release includes a namespaced checksum file and machine-readable asset inventory. It shares no release tag or installation directory with Rizin. +- **VM management:** create, configure, start, stop, clone, import, and export virtual machines; manage disks and networking. +- **Repeatable experiments:** inspect checkpoint trees, save a known state, and restore it after testing. +- **Desktop interaction:** use Basic or Enhanced Session, capture screenshots, send mouse and keyboard input, and work with guest UI Automation. +- **Guest automation:** run commands and processes, transfer files and folders, and manage reusable credentials. +- **Debugging:** use persistent application and kernel debugger sessions, including KDNET and named-pipe connections. -Extract the prebuilt plugin ZIP and install this plugin from the marketplace/local plugin directory. It contains `bin/HyperVControl.exe`, manifests, launcher and `$hyper-v-control` skill. A source-only marketplace installation can run `scripts/install.ps1` after the matching release has been published; downloads are pinned by SHA-256 in `runtime.json`. +## Install and connect -For any stdio MCP client: +Requires a Windows x64 host with Hyper-V. The distributed executable is self-contained and needs no separate .NET or Python installation. + +Install **Hyper-V Control** from **Jerry's Plugin Marketplace**, or get a complete plugin ZIP from the [download catalog](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/blob/main/docs/releases.md#release-index). The ZIP includes the executable and skill. For a marketplace installation, run the plugin's `scripts/install.ps1` to download its verified runtime, then reconnect the MCP. + +For another stdio MCP client, point its configuration at the executable's absolute path. This example uses the stable filename inside the extracted plugin: ```json { "mcpServers": { "hyper-v-control": { - "command": "C:\\Tools\\HyperVControl\\hyper-v-control-win-x64-v0.1.0.exe", + "command": "C:\\Tools\\hyper-v-control\\bin\\HyperVControl.exe", "args": ["--elevate"] } } } ``` -`--elevate` keeps the parent connected to the MCP client and opens a same-user elevated worker over a protected named pipe. The client itself need not be elevated. With UAC enabled, Windows may request consent; cancellation exits without operating on VMs. With sufficient existing privileges, the EXE can run without this option. Alternate-user UAC credentials are intentionally rejected by the same-user boundary. See the [permission model](skills/hyper-v-control/references/runtime.md). +The standalone EXE is also available from the download catalog; use its downloaded filename in your configuration. -## Capabilities +## Permissions and guest setup -- VM inventory, create/configure/remove, power states, import/export/clone, virtual switches and adapters, VHD/ISO operations, Secure Boot. -- Checkpoint tree/current-parent discovery, create, restore, rename and delete. -- Basic and Enhanced Session consoles using Hyper-V RDP ActiveX; native framebuffer screenshots in Basic, guarded screen capture in Enhanced; keyboard/chords/text, pointer/buttons/scroll/drag, Enhanced clipboard. -- Credential Manager profiles; PowerShell Direct commands and processes with exit codes, timeouts and separate output streams; bidirectional files and folders, directory listing and bounded binary reads. -- Microsoft's winapp guest UI Automation through an interactive scheduled task. -- KDNET and two-phase named-pipe KDCOM configuration with checked `bcdedit` results. -- Persistent KD/CDB sessions: commands, break, poll, detach; symbols, memory, registers, stacks, breakpoints, stepping and dump analysis through normal debugger commands. -- Persistent in-guest CDB workers over PowerShell Direct, without guest networking or a second MCP server. +With `--elevate`, Windows requests administrator approval once when needed. Subsequent operations use the same elevated worker until the MCP session ends. The MCP client can stay unelevated. UAC cancellation exits without operating on VMs; alternate-user elevation is unsupported. See the [permission model](skills/hyper-v-control/references/runtime.md). -Use `hyperv_capabilities` to inspect the actual environment. Windows guests need credentials for PowerShell Direct; semantic UI also needs an unlocked interactive desktop. Basic console can control boot and non-Windows guests without PowerShell Direct. Enhanced requires guest support and host policy. Host management is local; the graphical guest sessions are remote through Hyper-V, not through an HTTP MCP listener. +Run `hyperv_capabilities` to inspect the host and available integrations. Windows guest automation needs credentials for PowerShell Direct. UI Automation needs an unlocked interactive guest desktop; Enhanced Session needs guest support and host policy. Basic Session can interact with boot screens and guests without PowerShell Direct. -Current Microsoft WinDbg is preferred. Set `HYPERV_CONTROL_DEBUGGER_DIR` to the complete `amd64` directory to select an engine explicitly. Modern MSIX packages are discovered ahead of legacy Windows Kits. The EXE returns the path and version used. Downloading the MCP EXE does not implicitly install WinDbg or alter Secure Boot, BitLocker, firewall or UAC policy. +Install Microsoft WinDbg separately for debugging. Its modern debugger engine is preferred; `HYPERV_CONTROL_DEBUGGER_DIR` can select an explicit debugger directory. See the [agent workflow](skills/hyper-v-control/SKILL.md) for task-specific setup and checkpoint guidance. -## Build and validate +## Development and validation -From the repository root with .NET 10 SDK: +Build and test from the repository root using the SDK specified by the [release guide](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/blob/main/docs/releases.md): ```powershell ./scripts/build-hyperv-control.ps1 @@ -48,6 +49,4 @@ dotnet run --project tests/HyperVControl.Tests -c Release -- unit . dotnet run --project tests/HyperVControl.Tests -c Release -- smoke . ``` -The build creates the namespaced EXE, complete plugin ZIP, `hyper-v-control-v0.1.0-release.json` and `hyper-v-control-v0.1.0-SHA256SUMS.txt` under `build/hyperv-control/release`. Local `HyperVControl.exe` and `SHA256SUMS` aliases are for development only. Source lives under `src/HyperVControl`, independent of the Rizin plugin. Runtime binaries/build caches remain outside Git. The [extraction inventory](docs/extraction.md) maps RaivenX and reference-MCP features to their implementations. The [validation report](docs/validation.md) distinguishes measured results from untested environments. - -See [source/runtime notices](THIRD-PARTY-NOTICES.md). Release publication is separate from building local artifacts. +[Feature inventory](docs/extraction.md) · [Validation and known limits](docs/validation.md) · [Third-party notices](THIRD-PARTY-NOTICES.md) diff --git a/plugins/rizin-re-toolkit/README.md b/plugins/rizin-re-toolkit/README.md index 45d4f26..a02ec2b 100644 --- a/plugins/rizin-re-toolkit/README.md +++ b/plugins/rizin-re-toolkit/README.md @@ -1,31 +1,25 @@ # Rizin RE Toolkit -A portable Windows x64 CLI and Codex skill serving as the default entrypoint for native binary and memory-dump analysis. Plugin/skill version: **0.4.1**. Plugin ID and skill invocation: `rizin-re-toolkit` / `$rizin-re-toolkit`. +Understand native executables and memory dumps with a portable Windows analysis toolkit. Rizin brings disassembly, multiple decompilers, YARA matching, and FLIRT signatures into a workflow your agent can use from the command line. -Download the runtime ZIP and SHA256SUMS from [release rizin-v0.3.1](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-v0.3.1), verify the archive hash, and extract the whole rizin folder. Run `rizin\bin\rizin.exe -v` by absolute path, or add its bin directory to the current process PATH. Non-system runtime DLLs are included. Windows 10 (1903+) or Windows 11 x64 is required; administrator installation is unnecessary. +## What it helps with -| Component | Version / upstream revision | Command | -| --- | --- | --- | -| Rizin | 0.9.1 | rizin and companion tools | -| rz-ghidra | Current upstream 64ea54a, adapted for Rizin 0.9.1 | pdg, pdgj | -| jsdec | Current upstream 9fc6098 | pdd, pddj | -| rz-retdec | Current upstream 4ac6b29, RetDec 5.0 | pdz, pdzj | -| rz-libyara | Current upstream 451e349, YARA 4.5.8 | yaral, yaraMj | -| sigdb | Current upstream 4addbed | Fl, Fa, Fs | +- Triage unfamiliar binaries and find relevant functions, strings, imports, and cross-references. +- Compare Ghidra, RetDec, and jsdec output when one decompiler leaves questions open. +- Investigate captured memory, loaded modules, and code at meaningful addresses. +- Identify known code and patterns with signatures and YARA rules. -Versions were checked on October 1, 2026. Exact revisions, dependency hashes, and patch hashes are in the runtime's bundle-manifest.json and the repository's bundle.lock.json. +## Install -## Agent setup +Install **Rizin RE Toolkit** from **Jerry's Plugin Marketplace** in Codex. The included skill guides runtime setup and analysis; invoke it as `$rizin-re-toolkit` or describe a relevant task. -Install **Rizin RE Toolkit** from **Jerry's Plugin Marketplace** in Codex. The [skill](skills/rizin-re-toolkit/SKILL.md) teaches the agent to download the CLI, run noninteractive analysis, compare decompilers, and investigate memory dumps. +The [PowerShell installer](skills/rizin-re-toolkit/scripts/install.ps1) downloads and verifies the runtime into a user-writable directory. It supports a custom destination and optional user PATH registration. -The skill automatically applies to ordinary RE requests, including tasks phrased with Ghidra, IDA Pro/Hex-Rays, Binary Ninja, Cutter, radare2, or related tool names. Equivalent work uses the Rizin CLI; Ghidra decompilation uses bundled `pdg`, while general/IDA-style PE analysis starts with Rizin triage and `pdz`. The skill reports the actual engine used and checks native-project or unsupported-tool requirements before substituting workflows. +For manual installation, use the [download catalog](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/blob/main/docs/releases.md#release-index), verify the archive checksum, and extract the complete `rizin` folder. Run `rizin\bin\rizin.exe` by absolute path. Keep the folder together when moving it; required runtime libraries and support data are included. -Download the [complete plugin ZIP](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/releases/tag/rizin-re-toolkit-v0.4.1) if needed; its skill is included and needs no separate download. The runtime continues to use the verified `rizin-v0.3.1` release. If the former `rizin-windows-re` plugin is installed, refresh the marketplace, install the new plugin, and remove the old installation to avoid duplicate skills. +## Use -The [PowerShell installer](skills/rizin-re-toolkit/scripts/install.ps1) supports a user-level install, an explicit destination, a fixed release tag, and optional user PATH registration. It verifies SHA-256 before running the extracted CLI. The large runtime is a separate release asset. - -## Examples +Ask your agent to explain a binary's behavior, compare decompiler output, or investigate a memory dump. For direct CLI use: ```powershell rizin -q -N -e scr.color=0 -c iI sample.exe @@ -33,20 +27,12 @@ rizin -A -q -N -e scr.color=0 -c 'pdz @ main' sample.exe rizin -q -N -e scr.color=0 -c iI -c omlj -c il sample.dmp ``` -Use a real function/address instead of assuming a main symbol exists. For dumps, inspect captured mappings and analyze a bounded function before decompilation. The [dump workflow](skills/rizin-re-toolkit/references/memory-dumps.md) covers MDMP, DMP64, ELF core, raw memory, ASLR, and address translation. - -## Portability and changes +Use a real function or address in place of `main`. Dump analysis depends on the memory actually captured; see the [memory-dump guide](skills/rizin-re-toolkit/references/memory-dumps.md). -- Ghidra SLEIGH and RetDec support data resolve relative to the executable's installation. Move the entire folder together. -- Each CLI activates UTF-8 through its application manifest, supporting Unicode paths without changing system locale settings. -- Windows linking and Rizin 0.9.1 adapters are maintained as source patches. -- The current Ghidra upstream PE import-slot fix is included. -- jsdec reads the supported JSON color-palette command. -- RetDec leaves unknown return types unspecified instead of forcing void and discarding calculations. -- VC++ runtime DLLs ship beside the executables. YARA uses OpenSSL 3.5.9; the unchanged upstream RetDec SDK requires legacy OpenSSL 1.1.1w, included separately. +This plugin uses Rizin and its bundled analysis engines. Tool-specific project files and live debugging requests may need another tool; the agent checks capabilities before choosing a workflow. -The runtime includes licenses/ and THIRD-PARTY.md. The plugin/skill is MIT; redistributed components retain their own licenses. +## More information -## Installer maintenance in 0.4.1 +[Agent workflow](skills/rizin-re-toolkit/SKILL.md) · [Build guide](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/blob/main/docs/build.md) · [Releases and component versions](https://github.com/JerryLinLinLin/jerry-plugin-marketplace/blob/main/docs/releases.md) -Runtime discovery now checks the Rizin tag family and asset name together and paginates past unrelated plugin releases. Drafts and prereleases are skipped. Hyper-V Control uses an exact tagged EXE and a separate installation directory. The Rizin 0.3.1 runtime assets and existing download URLs are unchanged. +Plugin code and instructions use the MIT license. Runtime components retain their own licenses, included with the bundle. diff --git a/scripts/build_bundle.py b/scripts/build_bundle.py index fa7abe9..860c2e0 100644 --- a/scripts/build_bundle.py +++ b/scripts/build_bundle.py @@ -83,7 +83,7 @@ def prepare(): if not PREFIX.exists(): extract_zip(inputs['rizin'], BUILD / 'upstream') shutil.copytree(BUILD / 'upstream/rizin-win-installer-clang_cl-64', PREFIX) - for key, directory in [('retdecSdk', 'previous'), ('openssl3', 'openssl-3.5.9'), ('openssl11', 'openssl-1.1.1w')]: + for key, directory in [('retdecSdk', 'retdec-sdk'), ('openssl3', 'openssl-3.5.9'), ('openssl11', 'openssl-1.1.1w')]: destination = BUILD / directory if not destination.exists(): extract_zip(inputs[key], destination) @@ -111,7 +111,7 @@ def cmake(name, source, options): '-DZLIB_USE_STATIC_LIBS=ON', '-DBUILD_CUTTER_PLUGIN=OFF']) openssl11 = BUILD / 'openssl-1.1.1w/openssl-1.1/x64' cmake('rz-retdec', ROOT / 'sources/rz-retdec', [ - f'-DCMAKE_PREFIX_PATH={PREFIX.as_posix()};{(BUILD / "previous/rizin").as_posix()};{openssl11.as_posix()}', + f'-DCMAKE_PREFIX_PATH={PREFIX.as_posix()};{(BUILD / "retdec-sdk/rizin").as_posix()};{openssl11.as_posix()}', f'-DCMAKE_INSTALL_PREFIX={PREFIX.as_posix()}', f'-DOPENSSL_ROOT_DIR={openssl11.as_posix()}', '-DBUILD_BUNDLED_RETDEC=OFF', '-DBUILD_CUTTER_PLUGIN=OFF', '-DRZ_RETDEC_DOC=OFF']) os.environ['CMAKE_PREFIX_PATH'] = str(PREFIX) + ';' + str(BUILD / 'openssl-3.5.9/x64') @@ -134,7 +134,7 @@ def cmake(name, source, options): crt = next(redist.glob('Microsoft.VC*.CRT')) for path in crt.glob('*.dll'): shutil.copy2(path, PREFIX / 'bin' / path.name) - copy_tree(BUILD / 'previous/rizin/lib/rizin/plugins/support', PREFIX / 'lib/rizin/plugins/support') + copy_tree(BUILD / 'retdec-sdk/rizin/lib/rizin/plugins/support', PREFIX / 'lib/rizin/plugins/support') copy_tree(ROOT / 'sources/sigdb', PREFIX / 'share/sigdb') @@ -173,7 +173,7 @@ def assemble(): (BUILD / 'openssl-1.1.1w/openssl-1.1/LICENSE', 'openssl-1.1.1w/LICENSE'), (BUILD / 'deps/zlib-1.3.2/LICENSE', 'zlib/LICENSE'), ] - for path in (BUILD / 'previous/rizin/share/retdec').glob('LICENSE*'): + for path in (BUILD / 'retdec-sdk/rizin/share/retdec').glob('LICENSE*'): notices.append((path, 'retdec/' + path.name)) for source, relative in notices: dest = licenses / relative diff --git a/scripts/check-marketplace.py b/scripts/check-marketplace.py new file mode 100644 index 0000000..1cf20d3 --- /dev/null +++ b/scripts/check-marketplace.py @@ -0,0 +1,133 @@ +"""Check marketplace contracts without installing or running plugin dependencies.""" +import argparse +import json +from pathlib import Path +import re +import sys +from urllib.parse import unquote, urlsplit +import xml.etree.ElementTree as ET + +ROOT = Path(__file__).resolve().parents[1] +SEMVER = re.compile(r"\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?") + + +def read_json(path): + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def compatibility_manifest(manifest): + result = {key: value for key, value in manifest.items() if key not in ("$schema", "extensions")} + result.update(manifest.get("extensions", {}).get("com.openai", {})) + return result + + +def check(sync=False): + errors = [] + + def require(condition, message): + if not condition: + errors.append(message) + + catalog = read_json(ROOT / ".agents/plugins/marketplace.json") + names = [entry["name"] for entry in catalog["plugins"]] + require(len(names) == len(set(names)), "Marketplace plugin names must be unique") + folders = {path.name for path in (ROOT / "plugins").iterdir() if path.is_dir()} + require(set(names) == folders, "Marketplace entries must match the directories under plugins/") + documents = [ROOT / path for path in ("README.md", "CONTRIBUTING.md", "docs/build.md", "docs/releases.md")] + readmes = [ROOT / "README.md"] + + for entry in catalog["plugins"]: + name = entry["name"] + require(bool(re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", name)), f"Invalid plugin ID: {name}") + require(entry["source"] == {"source": "local", "path": f"./plugins/{name}"}, f"{name}: inconsistent catalog path") + plugin = ROOT / "plugins" / name + require(plugin.is_dir(), f"{name}: plugin directory is missing") + if not plugin.is_dir(): + continue + manifest = read_json(plugin / "plugin.json") + require(manifest["name"] == name, f"{name}: manifest identity mismatch") + require(bool(SEMVER.fullmatch(manifest["version"])), f"{name}: invalid semantic version") + expected = compatibility_manifest(manifest) + compat_path = plugin / ".codex-plugin/plugin.json" + if sync: + compat_path.parent.mkdir(parents=True, exist_ok=True) + compat_path.write_text(json.dumps(expected, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") + require(compat_path.is_file() and read_json(compat_path) == expected, + f"{name}: compatibility manifest drift; run python scripts/check-marketplace.py --sync") + extension = manifest["extensions"]["com.openai"] + require(entry["category"] == extension["interface"]["category"], f"{name}: category mismatch") + for field, relative in (("skills", extension["skills"]), ("logo", extension["interface"].get("logo")), + ("mcpServers", extension.get("mcpServers"))): + if relative: + target = (plugin / relative).resolve() + require(target.is_relative_to(plugin.resolve()) and target.exists(), f"{name}: invalid {field} path") + skills = list((plugin / extension["skills"]).glob("*/SKILL.md")) + require(bool(skills), f"{name}: no bundled skill") + for skill in skills: + text = skill.read_text(encoding="utf-8-sig") + frontmatter = re.match(r"\A---\r?\n(.*?)\r?\n---", text, re.DOTALL) + require(frontmatter is not None, f"{skill.relative_to(ROOT)}: missing frontmatter") + if frontmatter: + skill_name = re.search(r"^name:\s*['\"]?([a-z0-9-]+)['\"]?\s*$", frontmatter[1], re.MULTILINE) + require(skill_name is not None and skill_name[1] == skill.parent.name, + f"{skill.relative_to(ROOT)}: skill name must match its directory") + require(bool(re.search(r"^description:\s*\S", frontmatter[1], re.MULTILINE)), f"{name}: missing skill description") + documents.extend(skills) + documents.append(plugin / "README.md") + readmes.append(plugin / "README.md") + require((plugin / "LICENSE").is_file(), f"{name}: missing license") + runtime_path = plugin / "runtime.json" + if runtime_path.exists(): + runtime = read_json(runtime_path) + require(runtime["plugin"] == name, f"{name}: runtime belongs to another plugin") + require(bool(re.fullmatch(r"[a-fA-F0-9]{64}", runtime["sha256"])), f"{name}: invalid runtime SHA-256") + expected_url = f'{manifest["repository"]}/releases/download/{runtime["tag"]}/{runtime["asset"]}' + require(runtime["url"] == expected_url, f"{name}: runtime URL must match its exact tag and asset") + if (plugin / "mcp.json").exists() and (plugin / ".mcp.json").exists(): + portable = read_json(plugin / "mcp.json")["mcpServers"] + compatible = read_json(plugin / ".mcp.json")["mcpServers"] + normalized = {key: {field: value for field, value in server.items() if not (field == "type" and value == "stdio")} + for key, server in portable.items()} + require(normalized == compatible, f"{name}: MCP configurations disagree") + + # Existing native version literals remain part of the published binary identity. + # Catch partial version bumps without rewriting an already released executable. + hyperv_version = read_json(ROOT / "plugins/hyper-v-control/plugin.json")["version"] + project = ET.parse(ROOT / "src/HyperVControl/HyperVControl.csproj") + require(project.findtext(".//Version") == hyperv_version, "Hyper-V project and plugin versions disagree") + program = (ROOT / "src/HyperVControl/Program.cs").read_text(encoding="utf-8-sig") + for literal in re.findall(r'(?:Hyper-V Control |Version = ")(\d+\.\d+\.\d+)', program): + require(literal == hyperv_version, "Hyper-V CLI/protocol version disagrees with its plugin") + + for readme in readmes: + content = readme.read_text(encoding="utf-8-sig") + require(not re.search(r"\bv?\d+\.\d+\.\d+\b|\b20\d{2}-\d{2}-\d{2}\b|/releases/(?:tag|download)/", content), + f"{readme.relative_to(ROOT)}: keep versions, release dates, and versioned downloads out of READMEs") + + for document in documents: + content = document.read_text(encoding="utf-8-sig") + for link in re.findall(r"\[[^\]\n]+\]\(([^)\n]+)\)", content): + url = urlsplit(link.strip("<>")) + if url.scheme or url.netloc or not url.path: + continue + target = (document.parent / unquote(url.path)).resolve() + require(target.is_relative_to(ROOT) and target.exists(), f"{document.relative_to(ROOT)}: broken local link {link}") + if document.is_relative_to(ROOT / "plugins"): + plugin = ROOT / "plugins" / document.relative_to(ROOT / "plugins").parts[0] + require(target.is_relative_to(plugin), f"{document.relative_to(ROOT)}: link outside plugin package; use a repository URL for {link}") + + for error in errors: + print(f"ERROR: {error}", file=sys.stderr) + if not errors: + print(f"PASS: {len(names)} plugins; catalog, manifests, runtime pins, README policy, and entrypoint links") + return bool(errors) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--sync", action="store_true", help="Regenerate compatibility manifests from each canonical plugin.json before checking") + args = parser.parse_args() + try: + sys.exit(check(args.sync)) + except (OSError, ValueError, KeyError, TypeError) as error: + sys.exit(f"ERROR: {error}") diff --git a/scripts/ci-plan.py b/scripts/ci-plan.py new file mode 100644 index 0000000..083349a --- /dev/null +++ b/scripts/ci-plan.py @@ -0,0 +1,46 @@ +"""Select expensive Windows validation from the PR's changed paths.""" +import argparse +import json +import os +from pathlib import Path +import subprocess + +ROOT = Path(__file__).resolve().parents[1] +WINDOWS_PREFIXES = ("src/HyperVControl/", "tests/HyperVControl.Tests/", "plugins/hyper-v-control/", ".github/workflows/") +WINDOWS_FILES = { + ".gitattributes", "HyperVControl.slnx", "scripts/ci-plan.py", + "scripts/build-hyperv-control.ps1", "scripts/test-installer.ps1", "scripts/test-release-isolation.ps1", + "plugins/rizin-re-toolkit/skills/rizin-re-toolkit/scripts/install.ps1", +} + + +def windows_required(paths): + return any(not path.lower().endswith(".md") and + (path in WINDOWS_FILES or path.startswith(WINDOWS_PREFIXES)) for path in paths) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--base", help="Base Git revision for a local check") + parser.add_argument("--head", default="HEAD", help="Head Git revision for a local check") + args = parser.parse_args() + base, head = args.base, args.head + if not base: + if os.environ.get("GITHUB_EVENT_NAME") == "workflow_dispatch": + required = True + else: + event = json.loads(Path(os.environ["GITHUB_EVENT_PATH"]).read_text()) + base, head = event["pull_request"]["base"]["sha"], event["pull_request"]["head"]["sha"] + if base: + changed = subprocess.check_output(["git", "diff", "--name-only", "-z", base, head, "--"], cwd=ROOT) + paths = changed.decode("utf-8").rstrip("\0").split("\0") if changed else [] + required = windows_required(paths) + result = {"windows": str(required).lower()} + print(json.dumps(result)) + if os.environ.get("GITHUB_OUTPUT"): + with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output: + output.write(f'windows={result["windows"]}\n') + + +if __name__ == "__main__": + main()