通过内联汇编实现DLL自卸载,即在DLL的函数内部FreeLibrary自己

理论上DLL模块内部代码是不能自己卸载自己的,因为一旦DLL被FreeLibrary后,当前运行自身代码空间就为非法内存了。

但在某些特殊场合,需要实现这种功能。

例如,DLL导出某纯虚接口指针IExample*,存在一个IExample::Delete方法用于销毁当前对象。希望在销毁所有对象实例后,自动卸载DLL。

class IExample

{

public:

    void Delete() = 0;

}

 

void CExample::Delete()

{

    delete this;

    // 希望在这里自动卸载DLL

}

 

但是实现Delete函数的代码位于DLL模块中,直接调用FreeLibrary将导致FreeLibirary函数执行后返回到已经被卸载的代码空间,造成内存访问错误。那么是不是就没有办法解决这个问题了呢?正规的方法行不通时,可以考虑一些旁门左道的做法。

 

第一种方法:

利用现在很常见的远程进程代码注入技术,这里实际上是注入自身进程。先利用VirtualAlloc分配一块代码内存,将然后将卸载代码复制到内存中,再已该地址作为入口创建一个线程,这种方式确定就是比较麻烦,而且分配的临时内存也存在难以释放的问题。

 

第二种方法:

不分配内存,直接创建一个以FreeLibrary函数为入口的线程,hModule为参数,让它完成调用FreeLibrary

::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FreeLib

在Visual Studio (VS) 中,使用内联汇编实现函数传参和调用通常涉及到以下步骤: 1. **声明**: 首先,你需要在C++代码中声明一个函数,该函数将作为内联汇编的目标。例如,如果你想通过汇编调用`MessageBox`,你可以先声明一个函数模板: ```cpp template <typename Func> void CallViaInlineAssembly(Func systemFunction); ``` 2. **内联汇编代码**: 编写内联汇编部分,这里会涉及传递参数、跳转到系统函数地址以及接收返回值(如果有)。对于`MessageBox`这样的函数,可能会包括`stdcall`调用约定和必要的参数传递: ```cpp #define MessageBox InlineAsmCall<decltype(&MessageBoxW)>("invoke MessageBoxW", \ "argptr [esp+4]", "argptr [esp+8]", "argptr [esp+0x10]", "ret") ``` 这里假设`MessageBoxW`是64位系统下的宽字符版本。 3. **内联函数实现**: 实现`CallViaInlineAssembly`函数,将上述汇编代码嵌入其中,以实际执行调用: ```cpp template <typename Func> inline void CallViaInlineAssembly(Func systemFunction) { __asm { // ...插入上面提到的MessageBox宏 jmp MessageBox } } void MyFunction() { CallViaInlineAssembly(MessageBoxW); // 调用MessageBoxW } ``` 4. **注意点**: - 汇编代码需要与目标平台兼容,并且对参数和返回值的处理取决于具体的系统API和调用约定。 - 调试内联汇编可能会变得复杂,因为它们不会显示在正常调试环境中。 - 如果有错误处理需求,可能需要额外的机制来捕获异常。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值