修改现有的.NET程序集
有没有一种方法可以修改现有的 .NET 程序集而无需借助第 3 方工具? 我知道 PostSharp 使这成为可能,但我发现 PostSharp 的开发人员基本上不得不重写功能,这是非常浪费的整个 System.Reflection 命名空间的一部分,以便使现有程序集可修改。
System.Reflection.Emit
只允许创建新的动态程序集。 然而,这里使用的所有构建器类都继承自基本反射类(例如,TypeBuilder
继承自System.Type
)。 不幸的是,似乎没有办法将现有的动态加载类型强制到类型构建器中。 至少,没有官方支持的方式。
那么不支持怎么办? 有谁知道允许将现有程序集或类型加载到此类构建器类中的后门?
请注意,我不是寻找修改当前程序集的方法(这甚至可能是一个不合理的请求),而只是修改从光盘加载的现有程序集。 恐怕没有这样的事情,但我还是想问一下。
在最坏的情况下,人们必须求助于 ildasm.exe
来反汇编代码,然后使用 ilasm.exe
来重新组装,但没有工具链(请阅读:IL reader)包含在 .NET 中以处理 IL 数据(或者有吗?)。
/编辑:
我没有具体的用例。 我只是对通用解决方案感兴趣,因为修补现有程序集是一项非常常见的任务。 以混淆器、分析器或 AOP 库为例(是的,后者可以以不同的方式实现)。 正如我所说,被迫重写 System.Reflection 中现有基础设施的大部分似乎非常浪费。
@Wedge:
你是对的。 但是,这里没有具体的用例。 我修改了原来的问题以反映这一点。 我的兴趣是由另一个问题引发的,提问者想知道如何在每个方法的末尾注入指令 pop
和 ret
以防止 Lutz Roeder 的 Reflector重新设计(VB 或 C#)源代码。
现在,这个场景可以通过多种工具来实现,例如上面提到的PostSharp和Reflexil Reflector 的插件,它又使用 Cecil 库。
总而言之,我只是对 .NET 框架不满意。
@Joel:
是的,我知道这个限制。 无论如何,感谢您指出这一点,因为它很重要。
@marxidad:
这似乎是唯一可行的方法。 但是,这意味着您仍然必须使用构建器类重新创建完整的程序集,对吧? 也就是说,您必须手动遍历整个组件。
嗯,我会调查一下。
Is there a way to modify existing .NET assemblies without resorting to 3rd party tools? I know that PostSharp makes this possible but I find it incredibly wasteful that the developler of PostSharp basically had to rewrite the functionality of the whole System.Reflection
namespace in order to make existing assemblies modifiable.
System.Reflection.Emit
only allows the creation of new, dynamic assemblies. However, all the builder classes used here inherit from the basic reflection classes (e.g. TypeBuilder
inherits from System.Type
). Unfortunately, there doesn't seem to be a way to coerce an existing, dynamically loaded type into a type builder. At least, there's no official, supported way.
So what about unsupported? Does anyone know of backdoors that allow to load existing assemblies or types into such builder classes?
Mind, I am not searching for ways to modify the current assembly (this may even be an unreasonable request) but just to modify existing assemblies loaded from disc. I fear there's no such thing but I'd like to ask anyway.
In the worst case, one would have to resort to ildasm.exe
to disassemble the code and then to ilasm.exe
for reassembly but there's no toolchain (read: IL reader) contained in .NET to work with IL data (or is there?).
/EDIT:
I've got no specific use case. I'm just interested in a general-purpose solution because patching existing assemblies is a quite common task. Take obfuscators for example, or profilers, or AOP libraries (yes, the latter can be implemented differently). As I've said, it seems incredibly wasteful to be forced to rewrite large parts of the already existing infrastructure in System.Reflection
.
@Wedge:
You're right. However, there's no specific use case here. I've modified the original question to reflect this. My interest was sparked by another question where the asker wanted to know how he could inject the instructions pop
and ret
at the end of every method in order to keep Lutz Roeder's Reflector from reengineering the (VB or C#) source code.
Now, this scenario can be realized with a number of tools, e.g. PostSharp mentioned above and the Reflexil plugin for Reflector, that, in turn, uses the Cecil library.
All in all, I'm just not satisfied with the .NET framework.
@Joel:
Yes, I'm aware of this limitation. Thanks anyway for pointing it out, since it's important.
@marxidad:
This seems like the only feasible approach. However, this would mean that you'd still have to recreate the complete assembly using the builder classes, right? I.e. you'd have to walk over the whole assembly manually.
Hmm, I'll look into that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用 IronRuby 加载程序集,并混合您可以梦想的所有功能
You could load the assembly using IronRuby, and mixin all the functionality you can dream of
Mono.Cecil 还允许您从给定程序集中删除强名称并将其另存为未签名的程序集。 从程序集中删除强名称后,您只需修改目标方法的 IL 并像使用任何其他程序集一样使用该程序集。 以下是使用 Cecil 删除强名称的链接:
http://groups.google.com/group/mono-cecil/browse_thread/thread/3cc4ac0038c99380/b8ee62b03b56715d?lnk=gst&q=strong+named#b8ee62b03b56715d
一旦您删除了强名称后,您几乎可以对程序集执行任何您想要的操作。 享受!
Mono.Cecil also allows you to remove the strong name from a given assembly and save it back as an unsigned assembly. Once you remove the strong name from the assembly, you can just modify the IL of your target method and use the assembly as you would any other assembly. Here's the link for removing the strong name with Cecil:
http://groups.google.com/group/mono-cecil/browse_thread/thread/3cc4ac0038c99380/b8ee62b03b56715d?lnk=gst&q=strong+named#b8ee62b03b56715d
Once you've removed the strong name, you can pretty much do whatever you want with the assembly. Enjoy!
您可以使用 MethodInfo.GetMethodBody().GetILAsByteArray(),对其进行修改,然后将其插回到 MethodBuilder.CreateMethodBody() 中。
You can use MethodInfo.GetMethodBody().GetILAsByteArray(), modify that, and then plug it back into MethodBuilder.CreateMethodBody().
如果您可以提供更具体的用例,那将会有所帮助,可能有比这更好的方法来解决您的问题。
在 .NET 3.5 中,可以向现有框架类添加扩展方法,也许这就足够了?
It would help if you could provide a more specific use case, there are probably better ways to fix your problem than this.
In .NET 3.5 it's possible to add extension methods to existing framework classes, perhaps that is enough?
重要的一点是:如果程序集是签名的,则任何更改都将失败,并且最终会导致失败。
One important point: if the assembly is signed, any changes will fail and you'll end up with a dud.
.NET Framework 程序集已签名,正如 Joel Coehoorn 所说,您会得到一个哑弹。
.NET Framework assemblies are signed and just as Joel Coehoorn said you'll get a dud.