一. 钩子技术介绍

前面介绍了《 Windows注入与拦截(2) – 使用注册表方式完成DLL注入》,本文介绍使用钩子的方式将DLL注入到进程的地址空间中。

Windows提供了3个API来让我们可以很方便使用钩子技术将DLL文件注入到进程之中:

// 安装指定消息类型的钩子到钩子链中
HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId
);// 从钩子链中删除钩子
BOOL UnhookWindowsHookEx(HHOOK hhk
);// 将消息转发到钩子链上的下一个钩子
LRESULT CallNextHookEx(HHOOK hhk,int nCode,WPARAM wParam,LPARAM lParam
);

Hook中文名“钩子”,我们可以把它想象成一个“鱼钩”,用来勾住指定类型的消息。“钩子”可以指定需要勾住哪个线程的消息,可以是当前线程,也可以是所有线程。当“指定线程”的“指定消息”被勾住时,系统就会将我们的DLL(如果钩子的处理过程位于DLL中)加载到该线程所属进程的地址空间中,并且在该地址空间中调用我们的DLL中的钩子处理过程函数,从而实现了注入功能。

我们通过SetWindowsHookEx函数来安装一个钩子,操作系统同时也允许开发人员为“同一个线程”的“同一个消息类型”指定多个钩子,这样就形成了一个“钩子链”Hook Chain)。

1.1 SetWindowsHookEx

idHook参数:指定我们需要勾住的消息类型;
lpfn参数:函数指针。当idHook指定的消息触发时,系统将会调用lpfn函数指针。
hMod参数:lpfn函数指针所在DLL的句柄。有2种情况下这个参数需要传NULL:

  1. lpfn函数的代码位于本进程内时。
  2. 只需要勾住本进程的消息时,即dwThreadId参数指定的线程位于当前进程。

dwThreadId参数:线程ID,用于指定勾住哪个线程的消息。如果传0,则表示勾住所有线程的指定消息。

SetWindowsHookEx详细的参数解释可以参考MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx

1.2 CallNextHookEx

当我们的钩子处理函数将消息处理完之后,我们可以选择将消息丢弃,不让钩子链上的后面的钩子处理;也可以选择将消息继续传递下去,从而让其他钩子有处理的机会。

如果需要让其他钩子有处理的机会,我们可以在钩子处理函数的最后调用CallNextHookEx函数。

1.3 UnhookWindowsHookEx

UnhookWindowsHookEx函数用于将指定钩子从钩子链中移除。

即使不调用UnhookWindowsHookEx,在调用SetWindowsHookEx的进程退出后,钩子也将被自动移除。

二、实例

SetWindowsHookEx函数返回一个HHOOK类型的钩子句柄,CallNextHookExUnhookWindowsHookEx函数都需要使用这个句柄作为参数。假设我们将“注入逻辑”放在独立的exe中,将“钩子处理过程”放到独立的dll中,那么为了在“钩子处理过程”中调用CallNextHookEx时能够拿到钩子的句柄,我们需要通过其他途径将该句柄从exe传递到dll中。

所以为了避免传递“钩子句柄”的麻烦,我们将“注入逻辑”和“钩子处理过程”都写入到一个DLL之中。我们只需要调用这个DLL的导出函数就可以将这个DLL注入到指定线程所属的进程中。

示例DLL名称为InjectDLL,用于勾住指定窗口的WH_GETMESSAGE消息,我们也可以指定其他的消息类型,如键盘消息等。完整的消息类型可以参考MSDN上关于SetWindowsHookEx函数的解释。

InjectDLL的完整代码如下:

#include <stdio.h>
#include <windows.h>
#include <tchar.h>HHOOK g_hook = NULL;BOOL APIENTRY DllMain(HMODULE hModule, DWORD  fdwReason, LPVOID lpReserved) {switch(fdwReason) {case DLL_PROCESS_ATTACH:{break;}case DLL_THREAD_ATTACH:{break;}case DLL_THREAD_DETACH:{break;}case DLL_PROCESS_DETACH:{break;}}return TRUE;
}// 提权函数
// 参考:https://blog.csdn.net/china_jeffery/article/details/79173417
//
BOOL EnablePrivilege(LPCTSTR szPrivilege, BOOL fEnable) {BOOL fOk = FALSE;HANDLE hToken = NULL;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, szPrivilege, &tp.Privileges[0].Luid);tp.Privileges->Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;
}// 钩子处理过程
LRESULT CALLBACK HookProc_GetMsg(int code, WPARAM wParam, LPARAM lParam) {char szMsg[512] = { 0 };sprintf_s(szMsg, 512, "code: %d, wParam: %d, lParam: %d", code, wParam, lParam);OutputDebugStringA(szMsg);return CallNextHookEx(g_hook, code, wParam, lParam);;
}// 导出函数
HHOOK InjectDllByHook(HWND hwnd) {DWORD dwThreadId = 0;HHOOK hHook = NULL;__try {if (!EnablePrivilege(SE_DEBUG_NAME, TRUE)) {__leave;}// 通过窗口句柄获取到窗口所属线程dwThreadId = GetWindowThreadProcessId(hwnd, NULL);if (dwThreadId == 0) {__leave;}// 获取DLL自身的句柄HMODULE hModule = NULL;GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,(LPCWSTR)InjectDllByHook, &hModule);hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc_GetMsg, hModule, dwThreadId);}__finally {}return (hHook);
}// 导出函数
BOOL EjectDllByHook(HHOOK hook) {return UnhookWindowsHookEx(hook);
}

我们可以直接调用该DLL的导出函数InjectDllByHook,实现Hook指定窗口(也可以改成线程,因为InjectDllByHook函数内部也是通过窗口查找到对应线程的)的指定消息。当指定的消息类型被勾住时,我们的DLL也就被加载到了该窗口所属的进程地址空间了,从而实现了注入。

完整的示例代码下载地址: https://download.csdn.net/download/china_jeffery/10323108

Windows注入与拦截(3) -- 使用钩子方式完成DLL注入相关推荐

  1. Windows核心编程_远线程方式实现Dll注入

    之前有介绍过HOOK的方式注入,这次介绍以其它方式注入,而无须HOOK,要知道在Windows这个浩荡的海洋里,API就是宝藏,找到足够多的宝藏那么你就是海贼王~! 实现思路如下: 首先打开一个进程的 ...

  2. c语言 dll注入,教大家写一个远程线程的DLL注入,其实还是蛮简单的……………………...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 然后新建一个win32 application 的工程 新建c++ source file 写入: #include #include int WINAP ...

  3. c语言dll注入,教大家写一个远程线程的DLL注入,其实还是蛮简单的……………………...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 然后新建一个win32 application 的工程 新建c++ source file 写入: #include #include int WINAP ...

  4. C语言 编写的DLL注入工具,新人开源一个自己开发的DLL注入和汇编注入器(简单的讲解)...

    本帖最后由 zhaobisheng 于 2020-11-13 15:18 编辑 新人双11刚注册了帐号,来个新人贴冒一下泡 ,因为我写文章比较少,如果表达的不够清晰的话,大家可以留言哈,多多谅解,源码 ...

  5. 关于dll注入方式的学习(全局钩子注入)

    何为dll注入 DLL注入技术,一般来讲是向一个正在运行的进程插入/注入代码的过程.我们注入的代码以动态链接库(DLL)的形式存在.DLL文件在运行时将按需加载(类似于UNIX系统中的共享库(shar ...

  6. 2020-11-23(Windows系统的dll注入 )

    一.什么是dll注入 在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,每个进程都认为自己拥有计算机的整个内存空间,这些假象都 ...

  7. 【安全技术】关于几种dll注入方式的学习

    何为dll注入 DLL注入技术,一般来讲是向一个正在运行的进程插入/注入代码的过程.我们注入的代码以动态链接库(DLL)的形式存在.DLL文件在运行时将按需加载(类似于UNIX系统中的共享库(shar ...

  8. Windows系统的dll注入

    一.什么是dll注入 在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,每个进程都认为自己拥有计算机的整个内存空间,这些假象都 ...

  9. DLL注入的方式 (转载自看雪学院)

    DLL 注入技术的 N 种姿势 看雪学院 看雪学院,为IT专业人士.技术专家提供了一个民间交流与合作空间. 18 人赞同了该文章 本文中我将介绍DLL注入的相关知识.不算太糟的是,DLL注入技术可以被 ...

最新文章

  1. 【ORACLE 高可用】作业 :配置ORACLE GoldenGate 2
  2. Thread.interrupt()方法理解
  3. Oracle sql如何把毫秒转为日期,sql – 将毫秒转换为时间戳
  4. excel 行高 上下留白_拒绝加班,工作中最常用的57个Excel小技巧来了!
  5. POJ 1276 Cash Machine
  6. HDU 1757 A Simple Math Problem(矩阵快速幂)
  7. 推荐95个极富创意的单页网站设计实例欣赏
  8. 解决CentOS遇到Qt编译(error: cannot find -lGL)
  9. redhat常用基础命令代码
  10. 多任务学习(MTL)在转化率预估上的应用
  11. AngularJS+Ionic开发-2.项目结构介绍
  12. Spring Bean配置默认为单实例 pring Bean生命周期
  13. HDU 4548 美素数
  14. 区块链 预言机 Oracle是什么 例子
  15. Unity3d资源包的使用心得
  16. hightopo学习笔记--2D编辑器使用
  17. DIY,PC采购,服务器介绍
  18. Vue隐藏技能:运行时渲染用户写入的组件代码!
  19. pythonturtle魔法阵_python turtle 库绘制简单魔法阵
  20. 爬虫小程序 - 单词量测试

热门文章

  1. html视频教程全套
  2. MyBatis 自关联查询省市区地区数据,一对多自关联查询
  3. 腾讯云轻量2核4G/4核8G/8核16G/16核32G服务器配置详解
  4. 《比尔总动员》删档测验正式敞开,开端你的地球捍卫之旅吧
  5. 安捷伦示波器DSO-X3034A进入不了测试界面是什么原因?
  6. Micro LED再生并购 | 谷歌收购Raxium
  7. 【公示】关于举办“元宇宙数字人制作竞赛”的复函
  8. 幸福的烦恼—当本地化客户端遇上本地化服务器
  9. android 新闻频道,GitHub - xiyy/TopNews: 一款Android新闻客户端,并提供电视台直播功能...
  10. 蚂蚁金服估值1500亿只是起点 阿里经济体一骑绝尘 腾讯望尘莫及