理解了如何通过调试事件输出当前进程中寄存器信息,那么实现加载DLL模块也会变得很容易实现,加载DLL模块主要使用LOAD_DLL_DEBUG_EVENT这个通知事件,该事件可检测进程加载的模块信息,一旦有新模块被加载或装入那么则会触发一个通知事件,利用该方法并配合磁盘路径获取函数则可很容易的实现进程模块加载的监控。

获取加载的动态链接库DLL的详细信息,具体实现细节如下:

  • 首先,代码通过GetFileSize函数获取目标DLL文件的大小,如果大小为0,则立即退出函数。
  • 然后,代码调用CreateFileMappingMapViewOfFile函数创建了一个内存映射对象,该映射对象可以让代码访问DLL文件的内容。
  • 随后,代码调用GetMappedFileName函数获取该内存映射对象关联的DLL文件的路径,其中需要使用QueryDosDevice查询函数来确认磁盘符号对应的真实文件名称, 如果找到对应的真实文件名称,则可以更新原始路径为真实路径,这里用到了字符串操作函数_tcslen、 _tcsnicmp以及_tcsncpy等。
  • 最后,再调用UnmapViewOfFileCloseHandle函数清理资源,并将相关的信息输出到控制台上,包括基址、名称、大小和路径等信息。

有了这段获取DLL完整路径的程序片段,那么实现这个功能将变得很容易,我们看看一下OnDllLoaded中是如何针对DLL进程处理的,实现代码片段如下所示;

void OnDllLoaded(const LOAD_DLL_DEBUG_INFO* pDebug)
{
//printf("基址: 0x%-8X --> ", pDebug->lpBaseOfDll); BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH + 1];
HANDLE hFileMap; // 获取文件大小
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(pDebug->hFile, &dwFileSizeHi); //printf("长度: %9d --> ", dwFileSizeLo); if (dwFileSizeLo == 0 && dwFileSizeHi == 0)
{
return;
}
// 创建内存映射
hFileMap = CreateFileMapping(pDebug->hFile, 0, PAGE_READONLY, 0, 1, 0); if (hFileMap)
{
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
// 获取当前映射名称
if (GetMappedFileName(GetCurrentProcess(), pMem, pszFilename, MAX_PATH))
{
TCHAR szTemp[4096] = { 0 }; // 得到当前所有磁盘字符串
if (GetLogicalDriveStrings(4096 - 1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
BOOL bFound = FALSE;
TCHAR* p = szTemp;
do
{
*szDrive = *p;
if (QueryDosDevice(szDrive, szName, 4096))
{
UINT uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0;
if (bFound)
{
TCHAR szTempFile[MAX_PATH];
_stprintf(szTempFile, TEXT("%s%s"), szDrive, pszFilename + uNameLen);
_tcsncpy(pszFilename, szTempFile, MAX_PATH);
}
}
}
while (*p++);
} while (!bFound && *p);
}
}
bSuccess = TRUE;
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
} printf("基址: 0x%08X \t 相对名称: %-30s \t 大小: %-9d \t 路径: %s \n",
pDebug->lpBaseOfDll, GetBaseName(pszFilename), dwFileSizeLo, pszFilename);
}

上述程序被运行后,则可输出被加载进程的所有模块信息,其中包括了模块基址,相对名称,模块大小,模块完整路径等,输出效果如下图所示;

10.2 调试事件获取DLL装载的更多相关文章

  1. SOS 调试扩展 (SOS.dll)

    http://blog.csdn.net/cslie/article/details/2158780 SOS 调试扩展 (SOS.dll) 提供公共语言运行时(CLR)内部环境的有关信息,帮助你在Wi ...

  2. Visual Studio 原生开发的10个调试技巧(二)

    原文:Visual Studio 原生开发的10个调试技巧(二) 我以前关于 Visual Studio 调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识.以下的列表中你可以看到写原 ...

  3. java:javaScript(定义方式,循环语句,函数与参数,事件机制,控制台记录,event事件获取键盘ascii,confirm和prompt,事件和内置对象,获取input,点击更换背景色)

    1. 定义JS的两种方式: <!DOCTYPE> <html> <head> <meta charset="UTF-8"></ ...

  4. 获取DLL的文件路径以及调用DLL的文件路径

    如何在DLL中,获取DLL本身的路径以及调用DLL的文件的路径呢?主要通过GetModuleFileName(HMODULEhModule,LPTSTR lpFilename,DWORD nSize) ...

  5. delphi R3下 跨进程获取DLL信息 NtQueryInformationProcess

    unit APIUnit; { GetProcessModuleHandle API Unit Ring3调用NtQueryInformationProcess实现跨进程获取DLL句柄 } inter ...

  6. SQLServer中使用扩展事件获取Session级别的等待信息以及SQLServer 2016中Session级别等待信息的增强

    本文出处:http://www.cnblogs.com/wy123/p/6835939.html 什么是等待 简单说明一下什么是等待:当应用程序对SQL Server发起一个Session请求的时候, ...

  7. XML序列化 判断是否是手机 字符操作普通帮助类 验证数据帮助类 IO帮助类 c# Lambda操作类封装 C# -- 使用反射(Reflect)获取dll文件中的类型并调用方法 C# -- 文件的压缩与解压(GZipStream)

    XML序列化   #region 序列化 /// <summary> /// XML序列化 /// </summary> /// <param name="ob ...

  8. 10个调试Java的技巧

    调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...

  9. select的onchange事件获取不了option的value

    一,select的onchange事件获取不了option的value是当你使用JQ($("#xxx").val())方法的获取的值一直提示undefined 二,解决方法: va ...

  10. Delphi的TService 服务路径获取 Dll中获取文件路径

    研究delphi服务的路径,试了好几个方法 ,都没取出来,最后发现,要采用取DLL路径的方法 //一.获取Dll自身路径 //1)方法一: Function GetDllPath(sDllName:s ...

随机推荐

  1. Prometheus--PromQL

    官方文档:https://prometheus.io/docs/introduction/overview/  中文文档:https://prometheus.fuckcloudnative.io/ ...

  2. Mongodb--索引(转载)

    原文转载自:https://www.cnblogs.com/wyy1234/p/11032163.html 1 mongoDB索引的管理 本节介绍mongoDB中的索引,熟悉mysql/sqlserv ...

  3. 使用jasypt加密配置的时候,报错:DecryptionException: Unable to decrypt

    前几天分享了一篇<Spring Boot 2.x基础教程:加密配置中的敏感信息> ,然后看到群里有小伙伴反应跟着这篇文章出现了这个异常com.ulisesbocchio.jasyptspr ...

  4. POJ - 3180 The Cow Prom ( korasaju 算法模板)

    The Cow Prom POJ - 3180 题意: 奶牛圆舞:N头牛,M条有向绳子,能组成几个歌舞团(团内奶牛数 n >= 2)?要求顺时针逆时针都能带动舞团内所有牛. 分析: 所谓能带动, ...

  5. 关于“Github上传以及Clone时发生的 Failed to connect to github.com port 443: Timed out 问题解法记录

    本文是记录关于如何解决 "Github上传以及Clone时发生的 Failed to connect to github.com port 443: Timed out 错误" 看 ...

  6. AtCoder Beginner Contest 175 (AB水,C数学,D思维+前缀和处理+进价思考,E方阵+条件DP,F新回文字符串处理 GJ)

    补题链接:Here A - Rainy Season 如果不是 RSR 型的话直接计算 R 的数量即可 B - Making Triangle 给定 \(N\) 根长度分别为 \(L_i\) 的棍子, ...

  7. vant下拉加载更多,上拉刷新

    https://www.bilibili.com/video/BV1zq4y1p7ga?p=218 List 组件通过 loading 和 finished 两个变量控制加载状态,当组件滚动到底部时, ...

  8. 淘宝flexible.js源码分析

    下面三种情况都会刷新页面,都会触发load事件. 1.a标签的超链接. 2.F5或者刷新按钮(强制刷新) 3.前进后退按钮 但是火狐中,有个特点,有个"往返缓存",这个缓存中不仅保 ...

  9. Vue3.0 + Element Plus整合实战

    mall-vue3-manage 基于vue3.0 + Element Plus. 整合最新的 Echarts5 强劲的渲染引擎.富文本编辑器 Wangeditor 的后端管理项目. 版本 vue 3 ...

  10. mysql批量替换字段

    一.需求将数据库内指定的数据进行批量修改,可使用replace函数如IP:端口号,只改端口号的部分,将所有192.168.1.1:8001的数据8001的端口号修改为3001replace函数的用法如 ...