THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Description
A .NET ReadyToRun image published for a non-Windows target cannot be loaded at
all: PE.__init__ raises archinfo.arch.ArchNotFound: Can't find architecture info for architecture 0xfd1d with '' bits and unsure endness.
# cle/backends/pe/pe.py
machine_type = self._pe.FILE_HEADER.Machine
self.set_arch(archinfo.arch_from_id(pefile.MACHINE_TYPE.get(machine_type, hex(machine_type))))
0xfd1d is not a machine type. The .NET ReadyToRun compiler alters Machine by
an operating-system-specific constant when the image targets an OS other than
Windows, so that the Windows loader refuses a file that is not for it. Every one
of these images in the corpus is the AMD64 case:
0xfd1d ^ 0x7b79 = 0x8664 (IMAGE_FILE_MACHINE_AMD64)
0x7b79 is what the images observed here use; the .NET sources are the authority
on the constant for each target OS.
The rest of the header is an ordinary PE32+ image with .text, .data and
.reloc, an IMAGE_COR20_HEADER whose ManagedNativeHeader points at an RTR\0
signature, and native AMD64 code in .text — which is the whole point of
ReadyToRun. Nothing else about the image needs special handling.
Reproduction
$ dotnet new console -o r2rdemo && cd r2rdemo
$ dotnet publish -r linux-x64 -p:PublishReadyToRun=true --self-contained
then on the published r2rdemo binary:
import cle
cle.Loader("bin/Release/net*/linux-x64/publish/r2rdemo") # ArchNotFound: 0xfd1d
Confirming what the file is, without cle:
import struct
data = open("r2rdemo", "rb").read()
pe = struct.unpack_from("<I", data, 0x3c)[0]
machine = struct.unpack_from("<H", data, pe + 4)[0]
print(hex(machine), hex(machine ^ 0x7b79)) # 0xfd1d 0x8664
The IMAGE_COR20_HEADER's ManagedNativeHeader begins with RTR\0 on every one
of these.
Scale
Across a sweep of a large binary corpus, every PE object whose catalogued
architecture is cil and whose Machine is 0xfd1d fails this way — the
architecture is never resolved, so no analysis runs at all. They are the only
ArchNotFound failures in the whole PE population.
Options
This is a judgement call about how much .NET-specific knowledge belongs in the PE
backend, so this is an issue rather than a pull request:
- Gate on the image actually being ReadyToRun and undo the override there. The
IMAGE_COR20_HEADER is already parsed for is_dotnet; its
ManagedNativeHeader begins with RTR\0 exactly when this applies. With
that established, Machine ^ c for each OS-override constant the .NET
toolchain defines resolves to a real IMAGE_FILE_MACHINE_*. This cannot
accidentally rescue a corrupt Machine field on an unrelated image.
- Undo the override on any unrecognised
Machine, without the ReadyToRun
check. Simpler, and looser.
- Leave the architecture alone and only improve the error, so a caller can tell
an unsupported machine from a mangled one.
There is a second question either of the first two raises. PE.__init__ sets
self.os = "windows" unconditionally, and one of these images is not a Windows
binary — the override is there to say so. With the architecture resolved, angr
would build a SimWindows for a Linux program. Whether the backend should read
the override back into self.os is the same maintainer call.
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Description
A .NET ReadyToRun image published for a non-Windows target cannot be loaded at
all:
PE.__init__raisesarchinfo.arch.ArchNotFound: Can't find architecture info for architecture 0xfd1d with '' bits and unsure endness.0xfd1dis not a machine type. The .NET ReadyToRun compiler altersMachinebyan operating-system-specific constant when the image targets an OS other than
Windows, so that the Windows loader refuses a file that is not for it. Every one
of these images in the corpus is the AMD64 case:
0x7b79is what the images observed here use; the .NET sources are the authorityon the constant for each target OS.
The rest of the header is an ordinary PE32+ image with
.text,.dataand.reloc, anIMAGE_COR20_HEADERwhoseManagedNativeHeaderpoints at anRTR\0signature, and native AMD64 code in
.text— which is the whole point ofReadyToRun. Nothing else about the image needs special handling.
Reproduction
then on the published
r2rdemobinary:Confirming what the file is, without cle:
The
IMAGE_COR20_HEADER'sManagedNativeHeaderbegins withRTR\0on every oneof these.
Scale
Across a sweep of a large binary corpus, every PE object whose catalogued
architecture is
ciland whoseMachineis0xfd1dfails this way — thearchitecture is never resolved, so no analysis runs at all. They are the only
ArchNotFoundfailures in the whole PE population.Options
This is a judgement call about how much .NET-specific knowledge belongs in the PE
backend, so this is an issue rather than a pull request:
IMAGE_COR20_HEADERis already parsed foris_dotnet; itsManagedNativeHeaderbegins withRTR\0exactly when this applies. Withthat established,
Machine ^ cfor each OS-override constant the .NETtoolchain defines resolves to a real
IMAGE_FILE_MACHINE_*. This cannotaccidentally rescue a corrupt
Machinefield on an unrelated image.Machine, without the ReadyToRuncheck. Simpler, and looser.
an unsupported machine from a mangled one.
There is a second question either of the first two raises.
PE.__init__setsself.os = "windows"unconditionally, and one of these images is not a Windowsbinary — the override is there to say so. With the architecture resolved, angr
would build a
SimWindowsfor a Linux program. Whether the backend should readthe override back into
self.osis the same maintainer call.