[GH-ISSUE #2352] [Feature] Inventory and extract ordinary .NET single-file bundles #777

Closed
opened 2026-10-15 18:28:15 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @matbrgz on GitHub (Oct 12, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2352

Type: Feature Domain: Reverse Engineering Status: Proposed Ecosystem: REA

Analyst question and current scope

docs/managed-code-analysis.md explicitly states that the current lane does not unpack .NET single-file hosts. The artifact graph therefore cannot expose embedded assemblies/configuration as independently identified children through the ordinary archive workflow.

Acceptance criteria

  • Specify supported bundle header versions and establish the bundle marker/header from bytes rather than filename or native-PE guesses.
  • Map entry names/types/offsets and supported standard compression into the existing artifact reader and content-addressed inventory.
  • Preserve the host and embedded-byte identities; report unsupported entry types/versions and enforce compressed/expanded bounds before allocation.
  • Use exclusively owned extraction paths; test traversal, overlapping/truncated entries, stable-file changes, cancellation, cleanup and CLI/MCP workflows.

Scope is ordinary documented bundle inspection/extraction. Loading assemblies, launching the host or defeating protection is excluded. Related decompilation work #2299 should consume identified extracted assemblies.

Priority: P2. The current surface was checked at upstream 1c3791430, and open/closed issues were searched before filing. Proposed file-analysis features need their own spec/plan/tasks under docs/specs/. If implementation requires a new provider or expands execution authority, obtain the maintainer scope decision required by CONTRIBUTING.md before integration; this proposal itself does not authorize that expansion.

Originally created by @matbrgz on GitHub (Oct 12, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2352 [![Type: Feature](https://img.shields.io/badge/type-feature-blue.svg?style=flat-square)](https://github.com/morluto/rea) [![Domain: Reverse Engineering](https://img.shields.io/badge/domain-reverse_engineering-blueviolet.svg?style=flat-square)](https://github.com/morluto/rea) [![Status: Proposed](https://img.shields.io/badge/status-proposed-blue.svg?style=flat-square)](https://github.com/morluto/rea) [![Ecosystem: REA](https://img.shields.io/badge/ecosystem-morluto%2Frea-8A2BE2.svg?style=flat-square)](https://github.com/morluto/rea) ## Analyst question and current scope docs/managed-code-analysis.md explicitly states that the current lane does not unpack .NET single-file hosts. The artifact graph therefore cannot expose embedded assemblies/configuration as independently identified children through the ordinary archive workflow. ## Acceptance criteria - [ ] Specify supported bundle header versions and establish the bundle marker/header from bytes rather than filename or native-PE guesses. - [ ] Map entry names/types/offsets and supported standard compression into the existing artifact reader and content-addressed inventory. - [ ] Preserve the host and embedded-byte identities; report unsupported entry types/versions and enforce compressed/expanded bounds before allocation. - [ ] Use exclusively owned extraction paths; test traversal, overlapping/truncated entries, stable-file changes, cancellation, cleanup and CLI/MCP workflows. ## Source and related work - https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md Scope is ordinary documented bundle inspection/extraction. Loading assemblies, launching the host or defeating protection is excluded. Related decompilation work #2299 should consume identified extracted assemblies. Priority: P2. The current surface was checked at upstream 1c3791430, and open/closed issues were searched before filing. Proposed file-analysis features need their own spec/plan/tasks under docs/specs/. If implementation requires a new provider or expands execution authority, obtain the maintainer scope decision required by CONTRIBUTING.md before integration; this proposal itself does not authorize that expansion.
Author
Owner

@Zhong-fan commented on GitHub (Oct 14, 2026):

I'm taking this issue. If anyone has already started an implementation, please let me know so we can avoid duplicate work.

I plan to reuse the existing artifact reader, content-addressed inventory, and extraction workflows for offline inspection and extraction of ordinary .NET single-file bundles. I'll first define the supported header versions and compression formats, preserve host and embedded-file identities, and cover truncation, overlapping entries, path traversal, resource limits, cancellation, and cleanup.

I've checked basic feasibility with a source-built .NET 8 single-file bundle: the recovered embedded DLL is byte-identical to the build output. This is a format-level probe so far, not completed REA integration.

I'll keep the change focused and include reproducible source-owned fixtures, CLI/MCP verification, and format-support documentation for ongoing maintenance. The scope is offline inspection and extraction only; it will not load assemblies or execute the bundled host.

<!-- gh-comment-id:6157772126 --> @Zhong-fan commented on GitHub (Oct 14, 2026): I'm taking this issue. If anyone has already started an implementation, please let me know so we can avoid duplicate work. I plan to reuse the existing artifact reader, content-addressed inventory, and extraction workflows for offline inspection and extraction of ordinary .NET single-file bundles. I'll first define the supported header versions and compression formats, preserve host and embedded-file identities, and cover truncation, overlapping entries, path traversal, resource limits, cancellation, and cleanup. I've checked basic feasibility with a source-built .NET 8 single-file bundle: the recovered embedded DLL is byte-identical to the build output. This is a format-level probe so far, not completed REA integration. I'll keep the change focused and include reproducible source-owned fixtures, CLI/MCP verification, and format-support documentation for ongoing maintenance. The scope is offline inspection and extraction only; it will not load assemblies or execute the bundled host.
Author
Owner

@matbrgz commented on GitHub (Oct 14, 2026):

Go ahead.

<!-- gh-comment-id:6157818218 --> @matbrgz commented on GitHub (Oct 14, 2026): Go ahead.
bsakaguchi 2026-10-31 00:29:33 +00:00
Author
Owner

@379061296 commented on GitHub (Oct 26, 2026):

Here is a real-world .NET 10 bundle as a test vector, since the feasibility check above used a source-built .NET 8 one.

  • ScriptGraphicHelper.exe, 38,600,977 bytes, SHA-256 608ef7c14741e405a6fef3d701a0f3d8b4e4349992d09f85b1a684941647d187. Avalonia desktop application, TargetFrameworkAttribute says .NETCoreApp,Version=v10.0.
  • The 32-byte bundle signature (8b 12 02 b9 6a 61 20 38 … b3 6a ae) is at file offset 0x7f1b78. The file ends with …Helper.deps.json, so the deps.json entry sits at the very end of the bundle.
  • 106 PE images pass MZ+PE\0\0 header validation at their e_lfanew, spread from 0x835178 to 0x1f20000+; the first at offset 0 is the apphost.
  • The application assembly is at file offset 0x14b2000: 2 sections, .text raw 8,627,200 and .rsrc raw 38,400, section-table-derived length 8,666,112; CLI header at file offset 512; metadata RVA 8,397,676 with size 237,488. It resolves to ScriptGraphicHelper 3.1.0.0 with 210 TypeDef, 2515 MethodDef, 1723 MemberRef, 39 AssemblyRef, MVID 1ed6b7e9-f60a-40e9-be7b-9e47be1d6e8a.
  • Current behaviour on the host: inspect_managed_artifact reports not-managed ("The PE has no CLI data directory"), which is accurate for the outer image, but nothing indicates that roughly a hundred managed images are embedded. I recovered the assembly by locating the BSJB metadata root and walking back to the containing PE\0\0 header, then carving from the section table.
  • Not established by this observation: whether the other ~100 entries are stored uncompressed or deflated inside the bundle. The app assembly bytes carved this way are a valid PE with intact metadata, which is consistent with that one entry being stored uncompressed.

Happy to re-run checks against a build or a different sample if that is useful.

<!-- gh-comment-id:6426282321 --> @379061296 commented on GitHub (Oct 26, 2026): Here is a real-world .NET 10 bundle as a test vector, since the feasibility check above used a source-built .NET 8 one. - `ScriptGraphicHelper.exe`, 38,600,977 bytes, SHA-256 `608ef7c14741e405a6fef3d701a0f3d8b4e4349992d09f85b1a684941647d187`. Avalonia desktop application, `TargetFrameworkAttribute` says `.NETCoreApp,Version=v10.0`. - The 32-byte bundle signature (`8b 12 02 b9 6a 61 20 38 … b3 6a ae`) is at file offset `0x7f1b78`. The file ends with `…Helper.deps.json`, so the `deps.json` entry sits at the very end of the bundle. - 106 PE images pass MZ+`PE\0\0` header validation at their `e_lfanew`, spread from `0x835178` to `0x1f20000+`; the first at offset `0` is the apphost. - The application assembly is at file offset `0x14b2000`: 2 sections, `.text` raw 8,627,200 and `.rsrc` raw 38,400, section-table-derived length 8,666,112; CLI header at file offset 512; metadata RVA 8,397,676 with size 237,488. It resolves to `ScriptGraphicHelper 3.1.0.0` with 210 `TypeDef`, 2515 `MethodDef`, 1723 `MemberRef`, 39 `AssemblyRef`, MVID `1ed6b7e9-f60a-40e9-be7b-9e47be1d6e8a`. - Current behaviour on the host: `inspect_managed_artifact` reports `not-managed` ("The PE has no CLI data directory"), which is accurate for the outer image, but nothing indicates that roughly a hundred managed images are embedded. I recovered the assembly by locating the `BSJB` metadata root and walking back to the containing `PE\0\0` header, then carving from the section table. - Not established by this observation: whether the other ~100 entries are stored uncompressed or deflated inside the bundle. The app assembly bytes carved this way are a valid PE with intact metadata, which is consistent with that one entry being stored uncompressed. Happy to re-run checks against a build or a different sample if that is useful.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#777
No description provided.