Split the Exe kind into NativeExe / ManagedExe

The detector already used the CLR data-directory RVA to split DLLs into
NativeDll / ManagedDll; EXEs were a single undifferentiated Exe kind.
Apply the same CLR check to EXEs so callers can tell a protected .NET
executable from a native one without unpacking. Routing is unchanged:
both EXE kinds go to the EXE pipeline.

- CLI per-file lines and the run log now print NativeExe / ManagedExe
  (the kind comes from the same Debug formatting as the DLL variants).
- The web API's detect()/unpack_file() kind strings become
  'native-exe' / 'managed-exe'; the web UI gains matching labels, and
  the trap-retry guard (DLL-probe recovery) keys off both EXE kinds.

Golden corpus unchanged (35/35 byte-identical); kind is classification
only and never affects output bytes.
This commit is contained in:
2026-08-16 05:47:16 +08:00
parent fe4f904409
commit dc6e72a8bb
5 changed files with 34 additions and 31 deletions
+9 -8
View File
@@ -48,17 +48,18 @@ src/
Detection is content-based (`unpacker::detect`), never extension-based: the
key table is derived from the file header and checked against the format
magic, then the PE characteristics classify the input as EXE, native DLL, or
managed DLL.
magic, then the PE characteristics classify the input as EXE or DLL and the
CLR data directory splits each into native vs managed (`NativeExe` /
`ManagedExe` / `NativeDll` / `ManagedDll`).
`unpack_auto` then dispatches:
- `Exe` → the EXE pipeline (handles both PE32+ and PE32). Managed EXEs take
the same path: their import-string table is null (imports are the CLR
bootstrap stub), the entry point comes from the protected header (the
config block stores 0 for managed images), and the COR20 header, BSJB
metadata stream, and CLR resources are restored verbatim from the protected
file, mirroring the managed-DLL restore.
- `NativeExe` / `ManagedExe` → the EXE pipeline (handles both PE32+ and
PE32). Managed EXEs take the same path: their import-string table is null
(imports are the CLR bootstrap stub), the entry point comes from the
protected header (the config block stores 0 for managed images), and the
COR20 header, BSJB metadata stream, and CLR resources are restored verbatim
from the protected file, mirroring the managed-DLL restore.
- `NativeDll` / `ManagedDll` → the DLL pipeline first; on failure, the EXE
pipeline as a fallback. Two DLL layouts exist in the wild: an older layout
the DLL pipeline parses, and a newer one that protects DLLs with the