首页 > 其他分享 >3.4 DLL注入:全局消息钩子注入

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

时间:2023-09-13 15:32:41浏览次数:49  
标签:钩子 SetHook DLL hMod 3.4 hModuleSnap 进程 注入

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;
}

本文作者: 王瑞 本文链接: https://www.lyshark.com/post/a685dbbd.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

标签:钩子,SetHook,DLL,hMod,3.4,hModuleSnap,进程,注入
From: https://blog.51cto.com/lyshark/7455655

相关文章

  • @Autowired注入属性idea警告
    1.@Autowired报错原因分析和4种解决方案!上图的报错信息相信大部分程序员都遇到过,奇怪的是虽然代码报错,但丝毫不影响程序的正常执行,也就是虽然编译器IDEA报错,但程序却能正常的执行,那这其中的原因又是为何?​报错原因分析报错的原因首先是因为IDEA强大的报警机制,@Autowi......
  • 3.1 DLL注入:常规远程线程注入
    动态链接库注入技术是一种特殊的技术,它允许在运行的进程中注入DLL动态链接库,从而改变目标进程的行为。DLL注入的实现方式有许多,典型的实现方式为远程线程注入,该注入方式的注入原理是利用了Windows系统中提供的CreateRemoteThread()这个API函数,该函数第四个参数是准备运行的线程,我......
  • 3.2 DLL注入:远程APC异步注入
    APC(AsynchronousProcedureCall)异步过程调用是一种Windows操作系统的核心机制,它允许在进程上下文中执行用户定义的函数,而无需创建线程或等待OS执行完成。该机制适用于一些频繁的、短暂的或非常细微的操作,例如改变线程优先级或通知线程处理任务。在APC机制中,当某些事件发生时(例如......
  • .Net Framework使用Autofac实现依赖注入
    .NetFramework使用Autofac实现依赖注入前言最近也是找了快2周的工作了,收到的面试邀请也就几个,然后有个面试题目是用asp.netmvc+Entityframework做一个学生信息增删改查系统。因为题目要求了用Entityframework也就是EF那也就不上core了,web项目也是用Framework4.8去做的。......
  • Spring 注入集合
    使用<property>标签的value属性配置原始数据类型和ref属性配置对象引用的方式来定义Bean配置文件。这两种情况都涉及将单一值传递给Bean。那么如果您想传递多个值,例如Java集合类型,如List、Set、Map和Properties怎么办?为了处理这种情况,Spring提供了四种类型的集合配置元素,如下所示:......
  • Drupal < 7.32版本 _“Drupalgeddon” SQL注入漏洞(CVE-2014-3704)
    目录1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证说明内容漏洞编号CVE-2014-3704漏洞名称Drupal“Drupalgeddon”SQL注入漏洞漏洞评级影响范围Drupal7.0~7.31版本漏洞描述修复方案1.1、漏洞......
  • 提取.NET开发的DLL中的类为json文件工具软件ConsoleApp_Dll_Class2Json_V1.0开源了
    提取.NET开发的DLL中的类为json文件工具软件ConsoleApp_Dll_Class2Json_V1.0开源了同步在github和gitee上面发布。github https://github.com/binghe021/ConsoleApp_Dll_Class2Jsongitee https://gitee.com/binghe021/ConsoleApp_Dll_Class2Json......
  • Web攻防--JNDI注入--Log4j漏洞--Fastjson反序列化漏洞
    JNDI注入什么是JNDIJNDI全称为JavaNamingandDirectoryInterface(Java命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定义用户、网络、机器、对象和服务等各种资源。JNDI支持的服务主要有:DNS、LDAP、CORBA、RMI等。简单从安全......
  • 2.12 PE结构:实现PE字节注入
    本章笔者将介绍一种通过Metasploit生成ShellCode并将其注入到特定PE文件内的Shell注入技术。该技术能够劫持原始PE文件的入口地址,在PE程序运行之前执行ShellCode反弹,执行后挂入后台并继续运行原始程序,实现了一种隐蔽的Shell访问。而我把这种技术叫做字节注入反弹。字节注入功能调......
  • 07SQL注入:明明设置了强密码,为什么还会被别人登录?
    预声明的原理是将SQL查询语句和参数分离,通过绑定参数的方式确保参数的值不会被解释为SQL代码的一部分,从而有效地防止注入攻击。 ......