3.4 DLL注入:全局消息钩子注入

微软技术分享 微软技术分享 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

SetWindowHookEx 是Windows系统的一个函数,可用于让一个应用程序安装全局钩子,但读者需要格外注意该方法安装的钩子会由操作系统注入到所有可执行进程内,虽然该注入方式可以用于绕过游戏保护实现注入,但由于其属于全局注入所以所有的进程都会受到影响,而如果想要解决这个问题,则需要在DllMain()也就是动态链接库开头位置进行判断,如果是我们所需操作的进程则执行该DLL模块内的功能,如果不是则自动跳过不执行任何操作即可实现指定进程的注入方式。

首先我们先来看一下该函数的原型定义;

HHOOK SetWindowsHookEx(
  int       idHook,
  HOOKPROC  lpfn,
  HINSTANCE hMod,
  DWORD     dwThreadId
);

参数说明如下:

  • idHook:钩子类型,标识了钩子函数要监视哪种事件。可以是整数值或预定义的常量值(如WH_MOUSE、WH_KEYBOARD、WH_SHELL等)。
  • lpfn:钩子函数的地址。
  • hMod:把钩子函数插入挂钩链中的应用程序的句柄,该参数通常被设置为包含钩子函数代码的DLL模块的句柄。
  • dwThreadId:要设置钩子的线程标识符或进程标识符,如果为 0,则钩子通常与所有线程的输入消息联系起来。

在安装全局消息钩子时,读者需要在DLL中对外暴漏两个接口,其中SetHook()用于设置钩子,UnHook()则用于取消钩子,在DLL入口处,通过调用GetFristModuleName()我们可以判断当前进程是否为我们所需操作的进程,如果是则执行进程内的流程,如果不是则跳过执行,这个流程可以描述为如下样子,读者可自行将如下代码编译为DLL文件。

#include <iostream>
#include <TlHelp32.h>
#include <windows.h>
#include <tchar.h>

// 指定全局变量
HHOOK global_Hook;

// 判断是否是需要注入的进程
BOOL GetFristModuleName(DWORD Pid, LPCTSTR ExeName)
{
  MODULEENTRY32 me32 = { 0 };
  me32.dwSize = sizeof(MODULEENTRY32);
  HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Pid);

  if (INVALID_HANDLE_VALUE != hModuleSnap)
  {
    // 先拿到自身进程名称
    BOOL bRet = Module32First(hModuleSnap, &me32);

    // 对比如果是需要注入进程,则返回真
    if (!_tcsicmp(ExeName, (LPCTSTR)me32.szModule))
    {
      CloseHandle(hModuleSnap);
      return TRUE;
    }
    CloseHandle(hModuleSnap);
    return FALSE;
  }
  CloseHandle(hModuleSnap);
  return FALSE;
}

// 获取自身DLL名称
char* GetMyDllName()
{
  char szFileFullPath[MAX_PATH], szProcessName[MAX_PATH];

  // 获取文件路径
  GetModuleFileNameA(NULL, szFileFullPath, MAX_PATH);
  
  int length = strlen(szFileFullPath);

  // 从路径后面开始找\,即倒着找右斜杠
  for (int i = length - 1; i >= 0; i--)
  {
    // 找到第一个\就可以马上获取进程名称了
    if (szFileFullPath[i] == '\\')
    {
      i++;
      // 结束符\0不能少 即i=length
      for (int j = 0; i <= length; j++)
      {
        szProcessName[j] = szFileFullPath[i++];
      }
      break;
    }
  }
  return szProcessName;
}

// 设置全局消息回调函数
LRESULT CALLBACK MyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  return CallNextHookEx(global_Hook, nCode, wParam, lParam);
}

// 安装全局钩子 此处的 GetMyDllName()函数 可以是外部其他DLL,可将任意DLL进行注入
extern "C" __declspec(dllexport) void SetHook()
{
  global_Hook = SetWindowsHookEx(WH_CBT, MyProc, GetModuleHandleA(GetMyDllName()), 0);
}

// 卸载全局钩子
extern "C" __declspec(dllexport) void UnHook()
{
  if (global_Hook)
  {
    UnhookWindowsHookEx(global_Hook);
  }
}

// DLL 主函数
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
  switch (ul_reason_for_call)
  {
    case DLL_PROCESS_ATTACH:
    {
      // 当DLL被加载时触发,判断当前自身父进程是否为 lyshark.exe 
      BOOL flag = GetFristModuleName(GetCurrentProcessId(), TEXT("lyshark.exe"));
      if (flag == TRUE)
      {
        MessageBoxA(0, "hello lyshark", 0, 0);
      }
      break;
    }
    case DLL_THREAD_ATTACH:
    {
      break;
    }
    case DLL_THREAD_DETACH:
    {
      break;
    }
    case DLL_PROCESS_DETACH:
    {
      // DLL卸载时自动清理
      UnHook();
      break;
    }
    default:
      break;
  }
  return TRUE;
}

接着我们需要编写一个专门用来加载该DLL的程序,在调用DLL之前,我们需要通过LoadLibrary()将此模块加载到内存中,并通过GetProcAddress(hMod, "SetHook")获取到该模块的中SetHook函数的内存地址,最后直接调用SetHook()安装一个全局钩子,实现安装的代码流程如下所示;

#include <iostream>
#include <windows.h>

int main(int argc, char* argv[])
{
    HMODULE hMod = LoadLibrary(TEXT("d://hook.dll"));

    // 挂钩
    typedef void(*pSetHook)(void);
    pSetHook SetHook = (pSetHook)GetProcAddress(hMod, "SetHook");
    SetHook();

    while (1)
    {
        Sleep(1000);
    }

    // 卸载钩子
    typedef BOOL(*pUnSetHook)(HHOOK);
    pUnSetHook UnsetHook = (pUnSetHook)GetProcAddress(hMod, "UnHook");
    pUnSetHook();

    FreeLibrary(hMod);
    return 0;
}
...全文

相关推荐

前端开发组件示例源码_f1b6a91d详解

前端开发组件示例源码_f1b6a91d,内容包含源码/脚本与使用说明文档,结构清晰、注释完整,适合学习参考与二次开发,下载解压即可查看。

鱿鱼助手

前端开发基于history.js的HTML5与HTML4浏览器兼容方案:单页应用无刷新历史状态管理技术实现-Gjl4Gf1792158475

内容概要:本文系统介绍了如何利用history.js实现单页应用(SPA)在HTML5c与HTML4浏览器间s草错发的无缝历史状态管理。通过封装原生History API并在不支持的浏览器中自动降级为哈希路由,history.js解决了因浏览器兼容性导致的后退按钮失效、URL混乱等问题。文章详细讲解了其核心机制,包括状态对象管理、自动模式切换(HTML5 pushState vs HTML4 哈希)、状态数据持久化以及针,对Safari、IE等浏\览器的兼容性修复方案,并提供了从入门到实战的完整示例,涵盖初始化、事,件监听、页面加载及性能优化技巧。;Gjl4Gf1792158475 www.gblp.net www.gsctlq.com gezhixq.cn www.greendalian.com wap.gxqnm.com

2601_97196179

前端开发基于history.js的HTML5与HTML4浏览器兼容方案:单页应用无刷新历史状态管理技术实现-5Z6jeSqI1792158476

内容概要:本文系统介绍了如何利用history.js实现单页应用(SPA)在HTML5c与HTML4浏览器间s草错发的无缝历史状态管理。通过封装原生History API并在不支持的浏览器中自动降级为哈希路由,history.js解决了因浏览器兼容性导致的后退按钮失效、URL混乱等问题。文章详细讲解了其核心机制,包括状态对象管理、自动模式切换(HTML5 pushState vs HTML4 哈希)、状态数据持久化以及针,对Safari、IE等浏\览器的兼容性修复方案,并提供了从入门到实战的完整示例,涵盖初始化、事,件监听、页面加载及性能优化技巧。;5Z6jeSqI1792158476 sdhmgggw168.com www.shangliangwangye.com www.sdbing.net migu.blsxex.abxlbz.sc.cn www.safespeed.net.cn

2601_97196179

高校如何通过科技报告服务提升技术转移转化效率?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

科技服务机构如何提升服务大企业的技术诊断能力?.docx

科技服务机构如何提升服务大企业的技术诊断能力?

BIZKEEN
评论
收藏 已收藏
分享
返回顶部
微软技术分享
微软技术分享 优质创作者: 编程框架技术领域 优质创作者: 编程框架技术领域领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
微软技术社区 8,414 成员 37,309 内容