DLL延时加载技术与资源释放

0x00 前言

诸如调用非Windows的第三方库,我们或许会使用到dll文件,而这个时候原本程序运行需要相应的dll文件才能加载启动。通过DLL延时加载技术,使用延时加载的方式编译链接可执行的文件,可以先运行程序,再在依赖的DLL正式被调用时加载DLL。通常可通过资源文件写入dll,在释放完资源后,正式调用DLL时加载执行,避免丢失缺少DLL文件,从而单exe落地文件,避免麻烦。

0x01 介绍

在使用Visual Studio的场景下,如果使用DLL延时加载,只需要对项目的链接选项进行手动设置即可。

具体步骤如下:

属性—>链接器—>输入—>延迟加载的DLL—>输入:dll名称

DLL延迟加载技术的原理,其实就是在导入表中去掉xxx.dll这一项,等到DLL被正式调用的时候,才会加载DLL文件。这样,程序在正式调用DLL之前,都是可以正常执行的。

具体利用场景可以结合资源释放,在需要单exe的条件下,通过释放DLL资源,再延迟加载DLL,从而达到更方便的使用效果。

而资源释放,其实就是把一些需要额外加载的图片、文本、DLL作为资源的形式插入到主程序内,在必要的时候进行释放,使我们的主程序只有一个exe文件,降低落地计算机磁盘前期直接被发现的风险。

简单点来理解资源释放的原理,其实就是从资源中获取文件,写入到指定文件位置。

我们可以通过右键项目增加资源文件,如果文件类型不确定,可以增加自定义类型的资源文件。

0x02 编码实现

首先类似自定义的DLL,这里就写了一个小demo,起名为hello_world.dll:

Dolman.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <iostream>
#include <cstring>
using namespace std; BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
} extern "C" __declspec(dllexport) int hello()
{
int a = 666;
return a;
}

生成即自定义DLL。

再者,主程序,设置资源放入自定义dll,并设置延时加载hello_world.dll。

say_hello.cpp

// say_hello.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// #include <iostream>
#include<windows.h>
#include "resource.h" BOOL FreeMyResource(UINT uiResouceName, char* lpszResourceType, char* lpszSaveFileName); void GetCurrentPath(char* lpszCurrentPath, DWORD dwSize); void FreeRes_ShowError(char* pszText); // CDelayLoadDll_TestDlg 消息处理程序 void FreeRes_ShowError(char* pszText)
{
char szErr[MAX_PATH] = { 0 };
::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK);
} // 释放资源
BOOL FreeMyResource(UINT uiResouceName, char* lpszResourceType, char* lpszSaveFileName)
{
HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
if (NULL == hRsrc)
{
FreeRes_ShowError("FindResource");
return FALSE;
}
DWORD dwSize = ::SizeofResource(NULL, hRsrc);
if (0 >= dwSize)
{
FreeRes_ShowError("SizeofResource");
return FALSE;
}
HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
{
FreeRes_ShowError("LoadResource");
return FALSE;
}
LPVOID lpVoid = ::LockResource(hGlobal);
if (NULL == lpVoid)
{
FreeRes_ShowError("LockResource");
return FALSE;
} FILE* fp = NULL;
fopen_s(&fp, lpszSaveFileName, "wb+");
if (NULL == fp)
{
FreeRes_ShowError("LockResource");
return FALSE;
}
fwrite(lpVoid, sizeof(char), dwSize, fp);
fclose(fp); return TRUE;
} // 获取当前目录
void GetCurrentPath(char* lpszCurrentPath, DWORD dwSize)
{
::GetModuleFileName(NULL, lpszCurrentPath, dwSize);
char* p = ::strrchr(lpszCurrentPath, '\\');
p[0] = '\0';
} int main()
{
typedef int (*_pHello)();
//std::cout << "Hello World!\n";
// 释放DLL
// 获取当前目录
char szCurrentPath[MAX_PATH] = { 0 };
GetCurrentPath(szCurrentPath, MAX_PATH);
// 构造路径
::lstrcat(szCurrentPath, "\\hello_world.dll");
FreeMyResource(IDR_TEST1, "test", szCurrentPath);
HINSTANCE hDll = LoadLibrary("hello_world.dll");
_pHello hello = (_pHello)GetProcAddress(hDll, "hello");
int nHello = hello();
std::cout << nHello << std::endl;
}

编译即可。

0x03 实测

打包生成主程序后,拿到另一台机器运行测试。单exe运行后,释放dll资源到当前目录(可指定别的目录,如temp临时目录下),调用导出函数成功,输出666.

0x04 关于报错

Tips:

关于如果Visual Studio 2019 出现const char *“ 类型的实参与 “LPCWSTR“ 类型的形参不兼容这类错误。

解决方法:

右击项目文件 — 单击属性 — 配置属性 — 高级 — 高级属性 — 字符集

使用 Unicode 字符集”改为“使用多字节字符集

关于如果Visual Studio 2019 出现4996类错误。

解决方法:

右击项目文件 — 单击属性 — 配置属性 — c/c++ — 语言 — 符合模式

修改符合模式为否。

0x05 参考

https://www.cnblogs.com/predator-wang/p/4956615.html

https://www.write-bug.com/article/1601.html

DLL延时加载技术与资源释放的更多相关文章

  1. [整理]DLL延时加载 && 设置进程私有环境变量

    DLL延时加载鉴于静态和动态加载之间,即无需在代码中显示加载但它内队依然是动态加载的方式只是系统帮处理了.这样做好处是: 1. 可以加快启动时间(因为它是动态加载在需要的时间加载), 2. 减小编写L ...

  2. JAVA的单例模式与延时加载

    延迟加载(lazy load)是(也称为懒加载),也叫延迟实例化,延迟初始化等,主要表达的思想就是:把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建.延迟加载机制是为了避免一些无谓的性能开 ...

  3. Image Lazy Load:那些延时加载图片的开源插件(jQuery)

    图片延时加载技术对大流量的网站来说是十分实用的.目前图片在网站中大量使用,如果不加处理的话会对服务器和带宽造成级大压力,通过只渲染当前用户可见区域的图片,可以极大地减少网站的请求数,降低网络带宽资源. ...

  4. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  5. 011.Delphi插件之QPlugins,延时加载服务

    这个DEMO是是把DLL插件的相关信息做成了一个配置文件,主程序加载这个配置文件,从而起到延时加载的作用 主程序代码如下 unit Frm_Main; interface uses Winapi.Wi ...

  6. MyBatis入门(五)---延时加载、缓存

    一.创建数据库 1.1.建立数据库 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.7.9-log : Database - mybatis ****** ...

  7. Android 高仿腾讯旗下app的 皮肤加载技术

    http://www.cnblogs.com/punkisnotdead/p/4968851.html 以前写的这篇文章 可以高仿出 知乎 新浪微博等 绝大多数app的换肤技术,但是遗漏了腾讯的效果, ...

  8. 图片延时加载jquery.inview.js用法详解

    我们在网站上总能见到这样的效果,若是有图片,图片都是先用loading加载一小段时间,然后紧接着出来要显示的图片,即效果如下: v2_loading.gif,几秒钟时间过渡到v2_pic_01_s.j ...

  9. FaceBook页面加载技术

    1. 技术背景 FaceBook页面加载技术 试想这样一个场景,一个经常访问的网站,每次打开它的页面都要要花费6 秒:同时另外一个网站提供了相似的服务,但响应时间只需3 秒,那么你会如何选择呢?数据表 ...

随机推荐

  1. 最全总结 JavaScript Array 方法详解

    JavaScript Array 指南.png Array API 大全 (公众号: 前端自学社区).png 前言 我们在日常开发中,与接口打交道最多了,前端通过访问后端接口,然后将接口数据二次处理渲 ...

  2. 揭秘阿里云 RTS SDK 是如何实现直播降低延迟和卡顿

    作者:予涛 途坦 这个夏天,没什么能够比一场酣畅淋漓的奥运比赛来的过瘾.但是,在视频平台直播观看比赛也有痛点:"卡顿" 和 "延时".受限于不同地域.复杂的网络 ...

  3. 【笔记】初探KNN算法(1)

    KNN算法(1) 全称是K Nearest Neighbors k近邻算法: 思想简单 需要的数学知识很少 效果不错 可以解释机器学习算法使用过程中的很多细节问题 更加完整的刻画机器学习应用的流程 其 ...

  4. JavaWeb——CSS总结

    CSS 记得大一下学期那会参加基地后就开始跟师兄师姐接触前端了,利用业余时间在站看各种视频.由于初次认知并且时间也能不固定集中,也存在跳跃式学习等等原因,这就导致了好多知识点要么漏掉要么没记全,只能懂 ...

  5. MySQL JOIN的使用

    JOIN的使用 JOIN 理论 MySQL 七种 JOIN 的 SQL 编写 环境搭建 # 创建部门表 CREATE TABLE tbl_dept ( id INT NOT NULL AUTO_INC ...

  6. NOIP 模拟 $17\; \rm 时间机器$

    题解 \(by\;zj\varphi\) 一道贪心的题目 我们先将节点和电阻按左边界排序,相同的按右边界排序 对于每一个节点,我们发现,选取左边界小于等于它的电阻中右边界大于它且最接近的它的一定是最优 ...

  7. java小白困惑的那些事

    刚接触java时,有些技术盲区,查了很多资料也得不到答案,面试时也得遮遮掩掩,这里就列举一些,当年踩过的那些坑 1.http -> https一个网站或接口,从http改到https是否需要额外 ...

  8. 关于yii2学习笔记:gii的使用

    yii2中的gii无疑是非常强大的代码生成工具,以下是我学习使用gii的一些技巧,跟大家分享一下. 以User为例,在数据库中,创建user表. /*Navicat MySQL Data Transf ...

  9. FastReport.net 绿色破解版winform中使用

    FastReport 是非常有名的报表库,曾经在delphi中经常看到 现在FastReport.net 是.net平台下的实现.它的价格对于个人开发者来说确实非常非常贵 出于学习的目的(0<& ...

  10. WPF 中的style 样式

    WPF相较于以前学的WinForm,WPF在UI设计与动画方面的炫丽是最吸引我来学习的.在WPF中XMAL代码的引入使得代码的编写能够前后端分离,为获得更好的界面,也使得我们不得不分出一半的时间花在前 ...