如果 exe 没有清单,如何通过反射加载 exe?
Posted
技术标签:
【中文标题】如果 exe 没有清单,如何通过反射加载 exe?【英文标题】:How to load exe with reflection if exe does not have a manifest? 【发布时间】:2021-10-02 09:05:21 【问题描述】:我有一个可执行文件的转储(运行时:v2.0.50727)。它运行良好,没有任何错误。我可以将它加载到 DnSpy 进行调试或加载到 ILSpy。它们都表示所有引用都已成功解决。
但是,我无法使用此代码加载它:
try
var second_module = System.Reflection.Assembly.LoadFrom("myprog.bin");
catch (Exception e)
Console.WriteLine(e.ToString());
它给了我以下错误:
System.BadImageFormatException: Could not load file or assembly 'file:///myprog.bin' or one of its dependencies. The module was expected to contain an assembly manifest.
File name: 'file:///myprog.bin'
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
at System.Reflection.Assembly.LoadFrom(String assemblyFile)
at myproggg.Program.Main(String[] args) in c:\Sources\My\myproggg\Program.cs:line 11
=== Pre-bind state information ===
LOG: Where-ref bind. Location = myprog.bin
LOG: Appbase = file:///c:/Sources/My/myproggg/bin/x86/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: c:\Sources\My\myproggg\bin\x86\Debug\myproggg.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Attempting download of new URL file:///c:/Sources/My/MPCExtractor/examples/MP/myprog.bin.
ERR: Failed to complete setup of assembly (hr = 0x80131018). Probing terminated.
我尝试执行以下步骤:
将编译选项从“Any CPU”更改为“x86”。没有区别。
将框架更改为 2.0 和 4.5。无论我使用什么框架,它都会向我询问清单。
以上都没有帮到我。
我还能做些什么来加载这个转储的可执行文件?
【问题讨论】:
试试System.Reflection.Assembly.Load(byte[] rawAssembly);
重载。
谢谢你的魔法!但是为什么这种方法有效呢?
【参考方案1】:
您创建的.bin
文件可追溯到 .NET 2.0 运行时使用的 COFF。您也可以使用dumpbin 来获取.bin
文件。文档说明
Microsoft COFF 二进制文件转储程序 (DUMPBIN.EXE) 显示有关通用对象文件格式 (COFF) 二进制文件的信息。
因此,要正确加载它,您需要使用Assembly.Load(byte[], ...)。该文档声明其参数接受原始的COFF 字节数组:
一个字节数组,它是一个基于 COFF 的图像,包含一个发出的程序集。
以上来源的这部分也可能与您有关
考虑 C++ 可执行文件可能会抛出 BadImageFormatException。这很可能是由 C++ 编译器从可执行文件中剥离重定位地址或
.reloc
部分引起的。要为 C++ 可执行文件保留.reloc
地址,请在链接时指定/fixed:no
。
【讨论】:
其实我没有使用dumpbin。在执行开始之前,我已经将进程转储为挂起状态,重建它以修复虚拟大小并且......忘记恢复重定位。最后,你击中了钉子。谢谢。 很公平。这仍然基于该运行时版本追溯到 COFF。很高兴你没有被困住!以上是关于如果 exe 没有清单,如何通过反射加载 exe?的主要内容,如果未能解决你的问题,请参考以下文章