> 文章列表 > 使用C#调用其它exe中的函数

使用C#调用其它exe中的函数

使用C#调用其它exe中的函数

需求:

目前想改造一个带有窗口的exe文件,将其使用WPF来实现。
这个exe文件中最重要的一段内容就是一个函数(int f(int a,int b)),使用这个f函数来实现其核心的计算功能。

问题:

当前,没有exe文件的源码,因此无法使用C#简单地重写这个f函数。但我们可以考虑在C#代码中直接调用这个函数来进行计算。

困难:

exe没有导出这个f函数,因此在C#中无法直接使用DllImport来进行PInvoke调用。

方法:

1、在C#中通过Windows Api中的LoadLibrary把这个exe文件加载到内存。
2、使用IDA找到f函数在这个exe文件中的偏移量。
3、在C#中通过f函数的地址直接调用。

C语言演示代码:

#include <iostream>int f(int a,int b)
{return a + b;
}int main()
{std::cout << "Hello World! C++\\n";
}

这里有一个f函数,还有一个main函数,其中我们要关心的计算函数为f。main是启动函数,我们不用关心。
这里f函数,并未导出。也就是说,在程序的函数导出表中,不存在f函数。其它程序无法使用常用的方式来调用它。

IDA查看函数位置

在这里插入图片描述

C#演示代码

internal class Program
{//定义委托,对应于C语言中的函数原型//int f(int a,int b)public delegate int F(int a, int b);static void Main(string[] args){IntPtr hLib = LoadLibrary("C:\\\\Users\\\\Zmrbak\\\\source\\\\repos\\\\ConsoleApplication1\\\\Debug\\\\ConsoleApplication1.exe");if (hLib == IntPtr.Zero){Console.WriteLine("加载exe文件失败!");return;}//函数地址var offset = hLib + 0x12380;int a = 10;int b = 20;var a1 = (F)Marshal.GetDelegateForFunctionPointer(offset, typeof(F));if (a1 != null){//调用函数var c = a1(a, b);Console.WriteLine(c);}}[DllImport("kernel32.dll", SetLastError = true)]private static extern IntPtr LoadLibrary(string lpFileName);
}

在C#的启动函数main中,首先将这个exe文件加载到内存,这会得到一个加载的地址。
接下来通过偏移量 0x12380,计算出这个函数在内存中的实际位置。
然后,通过这个地址来调用。
这里需要注意,调用的时候,需要用到委托(delegate ),它可以将一个函数地址转换成一个函数,从而按照C#的标准来调用。

执行结果:

30C:\\Users\\Zmrbak\\source\\repos\\ConsoleApplication1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.exe (进程 14816)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

后记

另外,你还可以看到,程序运行的时候,只调用了C语言编写的f函数,C语言编写的main函数并未调用。从而达到了我们的目的,完成了我们的需求。