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. Windows 系统安装 git基础小白的简单操作包含基本输入命令

    首先  去官网下载git应用 https://git-scm.com/downloads  点击前往 安装的操作也比较简单,一直点击下一步 安装完成之后   在空白桌面点击是否有   Git  Gui ...

  2. 双非本科字节跳动Android面试题分享(已拿offer)

    基本情况 本人系非985非211普通本科生一枚,有实习有项目经历但成绩普通,在面试前刷了很多面经.面试题,这里也把自己的分享下,做个回报好了,顺便攒攒人品,一到这种时候人就迷信起来了. 面试是以视频面 ...

  3. 终于有人把Android技术面试知识体系整理出来了,这些学习手册让你的面试稳如泰山

    前言 年年寒冬,年年也挡不住一个安卓程序员追求大厂的决心.想要进入大厂,我们需要掌握哪些知识点呢?这里,我为大家梳理了一个整体的知识架构.整体包括Java.Android.算法.计算机基础等等,相应的 ...

  4. .NetCore+Envoy+Id4+Dapr+EFCore 构建微服务之Envoy

    .NetCore比较流行的微服务应该时是用Ocelot的方式构建微服务,纯配置化,开发量也比较小.但是做过一些项目之后发现这个方式不是很适合,首先它比较笨重,其次不支持gRpc和webSocket通信 ...

  5. Spring Security中实现微信网页授权

    微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用 ...

  6. Linux中配置ftp传输

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  7. SpringBoot-静态资源加载-源码

    目录 静态资源映射规则 什么是webjars 呢? 第二种静态资源映射规则 参考链接 静态资源映射规则 SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfigur ...

  8. Solon 1.5.24 发布

    本次版本主要变化: 修复 solon.extend.sessionstate.jwt 在特定场景下会无限次解析的问题 优化 solon.extend.cors 对头信息的处理 插件 solon.boo ...

  9. 一次BC站点渗透实录

    初探 打开首页 简单信息收集: IP地址:美国加利福尼亚洛杉矶 无CDN 中间件:Nginx 80端口直接突破,故未进行端口扫描 渗透思路 一般这种BC站点,有几种思路可以切入: 1)通过SQL注入查 ...

  10. CVE-2020-17523:Apache Shiro身份认证绕过漏洞分析

    0x01 Apache Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 0x02 漏洞简介 2021年2月1日,Apache Shiro官 ...