C# 调用dll以及内置dll到exe内部

     包含以下几块,如果没你需要的东西,可以继续赶路了

     1: C# 对的dll的两种调用

     2: dll包含到exe中

     3:dll的函数原型获取

    最近听闻人到中年的比尔盖茨收购了github并免费了私有的代码仓库,不由的给他点了一波赞,然后嘛就顺手把一个小项目用C#重写了一下,毕竟自从net开源了mono和.net core后,以后做gui也可以用C#这种快速预言了。哈哈,不用整天纠结在C++(QT)的各种内存泄漏等问题了。

    额外吐槽一下C#反编译的问题,就你麻麻的没有加密,反编译出来就是源码。。。几个意思啊

    现在开始正题, Part 1: C# call dll (这里的库没有广泛测试,各位DIY一下)。

         Method 1: DLLimport

        

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern void FreeLibrary(IntPtr hModule);

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpFileName);


//static load dll
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "MemPreAlloc")]

public static extern int MemPreAlloc(byte[] plaintext, int plaintext_length, byte[] ciphertext, int ciphertext_length);

然后就这么简单。。哈哈

          Method 2: 动态导入

          有时需要动态调用dll中的函数,比如我,为了避免神奇的乙方多次搞丢dll的问题,需要把dll内嵌到exe的资源区段中,需要的时候释放出来(这个是改日聊内容)。

           这里需要用到 IntPtr GetProcAddress(IntPtr hModule, string lpFileName)函数获取对应函数的地址,然后再使用C#的delegate委托方法调用。。其实感觉委托就是C语言中的函数申明。。。(C#高手放过不专业的描述)

          实现逻辑如下:

           1: 声明待导出函数的原型(C#变量对应问题,请自行百度)

           2:打开dll (LoadLibrary)

           3:  获取函数地址,通过Marshal.GetDelegateForFunctionPointer 函数对函数进行类型转换到目标的委托方法

            4: 自己调用了。。 

上代码:

//1:委托函数的类型声明,感觉等同于C语言函数指针的声明
delegate int _DeleGateMemPreAlloc(byte[] plaintext, int plaintext_length, byte[]);
/:委托函数的实例化
_DeleGateMemPreAlloc MemPreAlloc;

//委托函数的赋值

DllInvoke dllInvoke = new DllInvoke(SECUREDLL);//这个类看下边哈。。。包含打开dll,获取函数
MemPreAlloc = (_DeleGateMemPreAlloc)dllInvoke.Invoke("MemPreAlloc", typeof(_DeleGateMemPreAlloc));

          这里有两个大坑导致 C# 不能导出dll中的函数地址,没经验没办法,记录下来给大家分享:

            1: 调用目标程序的类型需要和dll一致,如x86,x64必须一致,至于x64能不能call x86,你们自己测试吧,理论应该可以的

            2:LoadLibrary 功能不能和调用函数在同一个文件中。。原因母鸡,解决方法就是对LoadLibrary 进行一层包装,说白了定时定义一个类包起来。。。上代码不BB DllInvoke.cs: 然后就德芙巧克力一样的丝滑了。。。

           

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace DMT_AES_TOOL
{
    public class DllInvoke
    {
        #region Win API
        [DllImport("kernel32.dll")]
        private extern static IntPtr LoadLibrary(string path);

        [DllImport("kernel32.dll")]
        private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);

        [DllImport("kernel32.dll")]
        private extern static bool FreeLibrary(IntPtr lib);
        #endregion

        private IntPtr hLib;
        public DllInvoke(String DLLPath)
        {
            hLib = LoadLibrary(DLLPath);
        }

        ~DllInvoke()
        {
            FreeLibrary(hLib);
        }

        //将要执行的函数转换为委托
        public Delegate Invoke(string APIName, Type t)
        {
            IntPtr api = GetProcAddress(hLib, APIName);
            if (api == IntPtr.Zero)
                throw new ArgumentNullException("找不到img资源入口");
            else
                return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
        }
    }
}

  

          最后贴一个内置dll文件到exe内,并悄悄释放,然后调用的实现。

         1: 我这里dll改名成test.img, 然后在C#工程中添加一个资源文件Resource1.resx

2: 释放dll资源到临时文件,这里直接上代码 LoadResource.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DMT_AES_TOOL
{
    class LoadResource
    {
        LoadResource()
        {
            
        }
        public static string Load()
        {

            
            string tempFile = Path.GetTempFileName();//临时文件准尉
            
            byte[] byDll = Resource1.test;//看这里看这里。我之前的文件是test.img这里直接就能获取到目标的byte[]数据了
            
            File.WriteAllBytes(tempFile, byDll);//释放了dll到临时文件
//          Clipboard.SetDataObject(tempFile, true);
//            MessageBox.Show("temp resource file -> " + tempFile + " size ->" + byDll.GetLength(0).ToString());

            return tempFile;//文件释放出来给DllInvoke导出函数哈哈哈
        }
        ~LoadResource()
        {
            
        }

    }
}

    最后获取扒拉一下dll中函数名字的获取和原型的获取

    名字比较简单: dll export  viewer

    原型获取,就需要动用大名鼎鼎的IDA了,这里安利一下看雪学院,工具都可以下载,也建议多看看。  

    打开dll,然后找找目标函数,然后双击进入,按一下F5 。。。不上图了。。自己看吧

猜你喜欢

转载自blog.csdn.net/godvmxi/article/details/86572103