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
+7 -4
View File
@@ -24,7 +24,8 @@ pub struct UnpackResult {
#[wasm_bindgen]
impl UnpackResult {
/// Detected module kind: `"exe"`, `"native-dll"`, or `"managed-dll"`.
/// Detected module kind: `"native-exe"`, `"managed-exe"`, `"native-dll"`,
/// or `"managed-dll"`.
#[wasm_bindgen(getter)]
pub fn kind(&self) -> String {
self.kind.clone()
@@ -102,7 +103,8 @@ impl MetadataResult {
fn kind_str(kind: senbei::unpacker::Kind) -> &'static str {
match kind {
senbei::unpacker::Kind::Exe => "exe",
senbei::unpacker::Kind::NativeExe => "native-exe",
senbei::unpacker::Kind::ManagedExe => "managed-exe",
senbei::unpacker::Kind::NativeDll => "native-dll",
senbei::unpacker::Kind::ManagedDll => "managed-dll",
}
@@ -110,8 +112,9 @@ fn kind_str(kind: senbei::unpacker::Kind) -> &'static str {
/// Classify a file's bytes without unpacking.
///
/// Returns `"exe"`, `"native-dll"`, `"managed-dll"`, `"metadata"` (an il2cpp
/// `global-metadata.dat`), or `undefined` for anything unrecognized.
/// Returns `"native-exe"`, `"managed-exe"`, `"native-dll"`, `"managed-dll"`,
/// `"metadata"` (an il2cpp `global-metadata.dat`), or `undefined` for
/// anything unrecognized.
#[wasm_bindgen]
pub fn detect(input: &[u8]) -> Option<String> {
if senbei::metadata::is_metadata(input) {