使用非托管 C++ .dll 从 C# .exe 调用函数
Posted
技术标签:
【中文标题】使用非托管 C++ .dll 从 C# .exe 调用函数【英文标题】:Call a function from C# .exe with unmanaged C++ .dll 【发布时间】:2011-05-23 20:16:17 【问题描述】:所以,我有一个用 C# 制作的可执行文件,我没有它的源代码,但我用 IDA 反汇编了它,它给了我很多面向对象的程序集。
我已经创建了一个 .exe 文件,它将一个 .dll 注入另一个 .exe,我已经将这个新的 C++ DLL 注入到 C# .exe 中,没有问题,调用了 DLLMain 等等...
但是当我将这个 DLL 注入到一个用 C++ 制作的普通 .exe 文件中时,我可以调用 .exe 中的一个函数,它的内存地址可以在 IDA 上使用。
问题是,面向对象的程序集在其函数中没有地址,即使函数名被反汇编。
那么,有什么方法可以用我在 C# .exe 文件上注入的 DLL 调用这个函数?
如果可能,有没有办法可以使用在 C# .exe 文件中声明的命名空间及其所有函数和变量,甚至是私有的?
反汇编代码示例:
.namespace MyCSharpApp
.class public auto ansi Test extends [mscorlib]System.Object
.field public value class [Microsoft.Xna.Framework]Microsoft.Xna.Framework.Vector2 pos
.field public int32 foo
....
【问题讨论】:
即使可以获取地址也没有多大意义——代码是 MSIL,而不是本地代码。需要启动 CLR(我不知道这会如何发生)。 @pst:由于应用程序是 .NET,因此 CLR 将启动并运行。但是,要调用的特定函数可能尚未经过 JIT 处理,因此您的担忧是有效的。 【参考方案1】:您正在尝试做一些棘手的事情,我不太清楚它是什么。根据您的描述,您至少有四件事:
托管 EXE 托管 DLL 非托管 EXE 非托管 DLL您可以控制其中的一些(即源代码),而有些则不能。
您想使用您称为“注入”的过程来更改您不可以控制的模块,从而调用您可以控制的模块。为此,您使用的工具要求您在进程的地址空间中有一个非托管入口点。
如果您想通过非托管模块获得所需的功能,那么您需要做的就是编写一个新的混合模式模块(显然您可以控制它)来调用您无法控制的托管 DLL。现在您有效地拥有了一个非托管 DLL(用于导出目的),并且它被托管的问题已经消失了。
要从新的非托管包装模块调用托管代码,您可以使用这篇介绍性文章中描述的技术:
An Overview of Managed/Unmanaged Code Interoperability基本上,您需要一个 C++/CLI 项目,该项目引用您的黑盒托管 DLL 并调用它并导出一个非托管入口点,您可以为注入“获取地址”。搜索会发现更多想法。
最后,您能否使用此方法在托管 DLL(您无法控制)中调用 private
方法?不,不是直接的。但是,它是一个托管 DLL,因此它必须有 一些 public
入口点才能对任何人有用,您可以调用它们。如果这还不够,您可以使用 C++/CLI 中的反射来调用私有方法并访问私有成员。
【讨论】:
【参考方案2】:您需要使用非托管托管/调试 API。如果您可以注入托管 DLL,这会容易得多,您只需使用反射即可。
【讨论】:
我尝试注入一个托管 DLL,它编译得很好,但是,我无法在 DllMain 上启动我的线程,因为它在运行时给我一个错误:"Attempt to use MSIL code from this assembly during native code initialization"
(甚至虽然我在初始化时没有使用 MSIL 代码),但我必须使用 DllMain,因为目标 .exe 不会调用我的 DLL 中的任何方法,这意味着在 .exe 完全加载之前我无法执行任何操作。
@Flavio:将 DllMain 放入一个没有/clr
编译的文件中,并将所有内容链接在一起。以上是关于使用非托管 C++ .dll 从 C# .exe 调用函数的主要内容,如果未能解决你的问题,请参考以下文章
从 C# 调用 C++ dll。 “无法封送'返回值':托管/非托管类型组合无效。”
使用 C# 访问非托管 C++ DLL 时出现 AccessViolationException
C# Windows 窗体无法在 Windows10 上加载非托管 C++ DLL