windows钩子保护自身进程不被破坏
代码来自于《windows核心编程》作者:
APIHOOK.h头文件:
#pragma once
#include <Windows.h> class CAPIHOOK
{
public: CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE); ~CAPIHOOK(void); private: static void ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller); static void ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod); //防止程序运行期间动态加载模块, 当一个新DLL被加载时调用 static void HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags); //跟踪当前进程加载新的DLL static HMODULE WINAPI LoadLibraryA(LPCTSTR lpFileName); static HMODULE WINAPI LoadLibraryW(LPCTSTR lpFileName); static HMODULE WINAPI LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags); static HMODULE WINAPI LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags); //防止程序运行期间动态调用API函数 对于请求已HOOK的API函数,返回用户自定义的函数地址 static FARPROC WINAPI GetProcess(HMODULE hModule, PCSTR pszProcName);private: //定义成静态的,会自动调用,从而实现自动HOOK static CAPIHOOK sm_LoadLibraryA; static CAPIHOOK sm_LoadLibraryW; static CAPIHOOK sm_LoadLibraryExA; static CAPIHOOK sm_LoadLibraryExW; static CAPIHOOK sm_GetProcAddress; private: static CAPIHOOK* sm_pHeader; //钩子链表 CAPIHOOK* m_pNext; //要钩子的函数 PROC m_pfnOrig; PROC m_pfnHook; //要钩子的函数所在的dll LPSTR m_pszModName; //要钩子的函数名称 LPSTR m_pszFuncName;
};
APIHOOK.cpp实现文件:
#include "APIHOOK.h"
#include <Tlhelp32.h> CAPIHOOK *CAPIHOOK::sm_pHeader = NULL;
CAPIHOOK CAPIHOOK::sm_LoadLibraryA("kernel32.dll", "LoadLibraryA", (PROC)CAPIHOOK::LoadLibraryA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryW("kernel32.dll", "LoadLibraryW", (PROC)CAPIHOOK::LoadLibraryW, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExA("kernel32.dll", "LoadLibraryExA", (PROC)CAPIHOOK::LoadLibraryExA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExW("kernel32.dll", "LoadLibraryExW", (PROC)CAPIHOOK::LoadLibraryExW, TRUE);
CAPIHOOK CAPIHOOK::sm_GetProcAddress("kernel32.dll", "GetProcAddress", (PROC)CAPIHOOK::GetProcess, TRUE);CAPIHOOK::CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)
{ //初始化变量 m_pszModName = lpszModName; m_pszFuncName = pszFuncName; m_pfnOrig = ::GetProcAddress(::GetModuleHandleA(lpszModName), pszFuncName); m_pfnHook = pfnHook; //将此对象加入链表中 m_pNext = sm_pHeader; sm_pHeader = this; //在当前已加载的模块中HOOK这个函数 ReplaceIATEntryInAllMods(lpszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);
} CAPIHOOK::~CAPIHOOK(void)
{ //取消对函数的HOOK ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, TRUE); //把自己从链表中删除 CAPIHOOK* p = sm_pHeader; if (p == this) { sm_pHeader = this->m_pNext; } else { while(p != NULL) { if (p->m_pNext == this) { p->m_pNext = this->m_pNext; break; } p = p->m_pNext; } }
}
//防止程序运行期间动态加载模块
void CAPIHOOK::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)
{ if (hModule!=NULL && (dwFlags&LOAD_LIBRARY_AS_DATAFILE)==0) { CAPIHOOK* p = sm_pHeader; //循环遍历链表,对每个CAPIHOOK进入HOOK if (p != NULL) { ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule); p = p->m_pNext; } }
}
//防止程序运行期间动态调用API函数
FARPROC WINAPI CAPIHOOK::GetProcess(HMODULE hModule, PCSTR pszProcName)
{ //得到函数的真实地址 FARPROC pfn = ::GetProcAddress(hModule, pszProcName); //遍历列表 看是不是要HOOK的函数 CAPIHOOK* p = sm_pHeader; while(p != NULL) { if (p->m_pfnOrig == pfn) //是要HOOK的函数 { pfn = p->m_pfnHook; //HOOK掉 break; } p = p->m_pNext; } return pfn;
} void CAPIHOOK::ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller)
{ IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hModCaller; IMAGE_OPTIONAL_HEADER* pOpNtHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hModCaller + pDosHeader->e_lfanew + 24); //这里加24 IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hModCaller + pOpNtHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); BOOL bFindDll = FALSE; while (pImportDesc->FirstThunk) { char* pszDllName = (char*)((BYTE*)hModCaller + pImportDesc->Name); if (stricmp(pszDllName, pszExportMod) == 0)//如果找到pszExportMod模块,相当于hook messageboxa时的“user32.dll” { bFindDll = TRUE; break; } pImportDesc++; } if (bFindDll) { DWORD n = 0; //一个IMAGE_THUNK_DATA就是一个导入函数 IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModCaller + pImportDesc->OriginalFirstThunk); while (pThunk->u1.Function) { //取得函数名称 char* pszFuncName = (char*)((BYTE*)hModCaller+pThunk->u1.AddressOfData+2); //函数名前面有两个.. //printf("function name:%-25s, ", pszFuncName); //取得函数地址 PDWORD lpAddr = (DWORD*)((BYTE*)hModCaller + pImportDesc->FirstThunk) + n; //从第一个函数的地址,以后每次+4字节 //printf("addrss:%X\n", lpAddr); //在这里是比较的函数地址 if (*lpAddr == (DWORD)pfnCurrent) //找到iat中的函数地址 { DWORD* lpNewProc = (DWORD*)pfnNewFunc; MEMORY_BASIC_INFORMATION mbi; DWORD dwOldProtect; //修改内存页的保护属性 ::VirtualQuery(lpAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); ::VirtualProtect(lpAddr, sizeof(void*), PAGE_READWRITE, &dwOldProtect); ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &lpNewProc, sizeof(void*), NULL); ::VirtualProtect(lpAddr, sizeof(void*), dwOldProtect, NULL); return; } n++; //每次增加一个DWORD } }
} void CAPIHOOK::ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod)
{ //取得当前模块句柄 HMODULE hModThis = NULL; if (bExcludeAPIHookMod) { MEMORY_BASIC_INFORMATION mbi; if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods必须为类的static函数 { hModThis = (HMODULE)mbi.AllocationBase; } } //取得本进程的模块列表 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (INVALID_HANDLE_VALUE == hModuleSnap) { return; } me32.dwSize = sizeof( MODULEENTRY32 ); if( !Module32First( hModuleSnap, &me32 ) ) { return; } do { //对每一个模块 if (me32.hModule != hModThis) { ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule); } } while( Module32Next( hModuleSnap, &me32 ) ); ::CloseHandle(hModuleSnap); //配对写
} //防止自动加载
HMODULE WINAPI CAPIHOOK::LoadLibraryA(LPCTSTR lpFileName)
{ HMODULE hModule = LoadLibraryA(lpFileName); HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了 return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryW(LPCTSTR lpFileName)
{ HMODULE hModule = LoadLibraryW(lpFileName); HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了 return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{ HMODULE hModule = LoadLibraryExA(lpFileName, hFile, dwFlags); HookNewlyLoadedModule(hModule, dwFlags); //这个函数中忆检测hModule 了 return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{ HMODULE hModule = LoadLibraryExW(lpFileName, hFile, dwFlags); HookNewlyLoadedModule(hModule, dwFlags); //这个函数中忆检测hModule 了 return hModule;
}
相关文章:
windows钩子保护自身进程不被破坏
代码来自于《windows核心编程》作者: APIHOOK.h头文件: #pragma once #include <Windows.h> class CAPIHOOK { public: CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod TRUE); ~CAPIHOOK(void); p…...
Linux系统查看文件系统类型C代码
系统:VM Ubuntu 实现Linux系统下通过输入指定路径查看文件系统类型,MSDOS_SUPER_MAGIC,NTFS_SUPER_MAGIC和EXT4_SUPER_MAGIC这些宏定义并不是在sys/mount.h中定义的,它们实际上是在linux/magic.h头文件中定义的。不同系统下宏定义可能不一样&…...
Python中的正则表达式
大家好,今天我们将通过详细的解释和代码示例,探讨如何在Python中使用正则表达式。 介绍 正则表达式(regex)是一种用于操作文本和数据的强大工具,它们提供了一种简洁灵活的方式来“匹配”(指定和识别&…...
第六章,创作文章
6.1添加创作页面 <template><div class="blog-container"><div class="blog-pages"><div class="col-md-12 panel"><div class="panel-body"><h2 class="text-center">创作文章&l…...
Win10c盘满了怎么清理?快速清理,5个方法!
“快救救孩子吧!我的电脑是win10系统的,现在c盘满了,根本没法继续使用电脑了。怎么才能快速的释放内存呢?非常着急!感谢大家!” C盘是Windows系统中重要的分区,当其存储空间满了,可能…...
回归预测 | MATLAB实现GWO-BP灰狼算法优化BP神经网络多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现GWO-BP灰狼算法优化BP神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现GWO-BP灰狼算法优化BP神经网络多输入单输出回归预测(多指标,多图)效果一览基本介绍程序…...
docker 06(docker compose)
一、服务编排 二、docker compose...
非阻塞重试与 Spring Kafka 的集成测试
如何为启用重试和死信发布的消费者的 Spring Kafka 实现编写集成测试。 Kafka 非阻塞重试 Kafka 中的非阻塞重试是通过为主主题配置重试主题来完成的。如果需要,还可以配置其他死信主题。如果所有重试均已用尽,事件将转发至 DLT。公共领域提供了大量资…...
基于 Debian 12 的MX Linux 23 正式发布!
导读MX Linux 是基于 Debian 稳定分支的面向桌面的 Linux 发行,它是 antiX 及早先的 MEPIS Linux 社区合作的产物。它采用 Xfce 作为默认桌面环境,是一份中量级操作系统,并被设计为优雅而高效的桌面与如下特性的结合:配置简单、高…...
Nginx代理功能与负载均衡详解
序言 Nginx的代理功能与负载均衡功能是最常被用到的,关于nginx的基本语法常识与配置已在上篇文章中有说明,这篇就开门见山,先描述一些关于代理功能的配置,再说明负载均衡详细。 Nginx代理服务的配置说明 1、上一篇中我们在http…...
部署问题集合(特辑)虚拟机常用命令
基础 查看ip:ip addr或ipconfig压缩:tar -zcvf redis-3.2.8.tar.gz redis-3.2.8/ 注意:-zcvf对应gz,-vcf对应tar 解压:tar -zxvf redis-3.2.8.tar.gz压缩zip:zip nginx.zip nginx.txt nginx2.txt解压zip&a…...
【Git】如何将本地文件进行Git仓库归档
Git 全局设置 git config --global user.name "mcihael" git config --global user.email "michael520.com"创建新版本库 git clone gitcode.xxxxxx.git cd branch-name touch README.md git add README.md git commit -m "add README" git pu…...
uniapp 使用腾讯视频 的 坑
1. 版本号的问题 注意 1.X.X不维护了 , 需要升级要 2.X.X 2. 官网的 组件事件 调用需要去掉bind 才能调用 官网地址:腾讯视频 | 小程序插件 | 微信公众平台...
LinkedList
LinkedList的模拟实现(底层是一个双向链表)LinkedList使用 LinkedList的模拟实现(底层是一个双向链表) 无头双向链表:有两个指针;一个指向前一个节点的地址;一个指向后一个节点的地址。 节点定…...
创作新纪元:知乎、阅文加码AI大模型,撬动创作者经济
输入几个关键词就能生成一篇文章、一篇新闻、一篇小说,ChatGPT自诞生以来文本生成能力一直备受赞誉,ChatGPT要替代记者、编辑、作家的言论愈演愈烈,甚至有一些互联网企业宣布砍掉记者、编辑、文案等岗位全面拥抱AIGC。 目前ChatGPT是否会全面…...
PAT(Advanced Level) Practice(with python)——1067 Sort with Swap(0, i)
Code # 输入有毒,需避坑 # N int(input()) L list(map(int,input().split())) N L[0] L L[1:] res 0 for i in range(1,N):while L[0]!0:# 把所有不在正常位置下的数换到正常t L[0]L[0],L[t] L[t],L[0]res1if L[i]!i:# 换完全后如果对应位置下的数不是目标…...
Python爬取斗罗大陆全集
打开网址http://www.luoxu.cc/dmplay/C888H-1-265.html F12打开Fetch/XHR,看到m3u8,ts,一眼顶真,打开index.m3u8 由第一个包含第二个index.m3u8的地址,ctrlf在源代码中一查index,果然有,不过/…...
前馈神经网络解密:深入理解人工智能的基石
目录 一、前馈神经网络概述什么是前馈神经网络前馈神经网络的工作原理应用场景及优缺点 二、前馈神经网络的基本结构输入层、隐藏层和输出层激活函数的选择与作用网络权重和偏置 三、前馈神经网络的训练方法损失函数与优化算法反向传播算法详解避免过拟合的策略 四、使用Python…...
顺序栈Sequential-stack
0、节点结构体定义 typedef struct SqStack{int *base;int *top; } SqStack; 1、初始化 bool InitStack(SqStack &S) {S.base new int[Maxsize]; //eg. #define Maxsize 100if(!S.base){return false;}S.top S.base;return true; } 2、入栈 bool Push(SqStack &…...
关于工牌(必须5-10个字)
今天蹲坑,低头看了下工牌觉得挺有意思:我从啥时候起也不排斥将工牌挂在脖子上了? 工牌,一个标识。不仅标识了你,也标识了你所在的群体。如果你认可这个群体,佩戴它那是一种荣誉、荣耀;如果你不…...
基于Arduino与VS1053的宠物智能服装DIY:嵌入式系统集成实践
1. 项目概述与核心思路给宠物做一件会发光、会发声的智能服装,听起来像是科幻电影里的情节,但用今天触手可及的硬件和开源工具,这完全是一个可以亲手实现的周末项目。这个项目的核心,是将一个微小的“智能大脑”和一套声光系统&am…...
【AI编程生产力跃迁】:用Perplexity秒级获取可运行代码示例的6大权威提示工程模板
更多请点击: https://codechina.net 第一章:Perplexity代码示例查询的核心机制与能力边界 Perplexity 在处理代码示例查询时,并非依赖静态模板匹配,而是通过多阶段语义理解与上下文感知检索协同实现:首先对用户自然语…...
我用豆包写的论文 AI 率为什么 95%?这款工具一次降到 4% 万方检测合格
我用豆包写的论文 AI 率为什么 95%?这款工具一次降到 4% 万方检测合格 去年我用豆包写了 1 万字的生物学本科论文——自己读着挺顺、像人写的。送学校万方 AIGC 检测——AI 率 95.7%,学校卡的是 30%。我整个人懵了。 这篇文章我把当时的实测过程写下来—…...
ASML财报解读:高毛利与利润倍增背后的光刻机技术垄断与市场逻辑
1. 财报核心数据深度解读:高毛利与利润倍增的背后 看到ASML最新发布的Q2财报,最抓人眼球的两个数字无疑是“毛利率超50%”和“每股净利润增长近一倍”。这不仅仅是两个亮眼的财务指标,更是理解这家全球光刻机巨头当前市场地位、技术壁垒和未来…...
OpenPLC Editor工业自动化编程深度解析:开源PLC开发环境实战指南
OpenPLC Editor工业自动化编程深度解析:开源PLC开发环境实战指南 【免费下载链接】OpenPLC_Editor 项目地址: https://gitcode.com/gh_mirrors/ope/OpenPLC_Editor OpenPLC Editor是一款基于Beremiz项目的开源工业自动化编程工具,为工程师和开发…...
3个超实用场景解析:Cloud Document Converter如何让飞书文档转换变得轻松
3个超实用场景解析:Cloud Document Converter如何让飞书文档转换变得轻松 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 还在为飞书文档的格式转换问题而…...
C++ inline函数深度解析:从链接属性到性能优化的实战指南
1. 项目概述:为什么我们需要关注inline函数?在C项目里,尤其是那些对性能有极致追求的系统、游戏引擎或者高频交易框架中,你经常会看到代码里散落着inline关键字。新手可能会觉得它只是个“建议编译器内联”的提示符,有…...
别再只盯着业务代码了!SpringBoot应用层安全之Tomcat连接管理实战
SpringBoot应用层安全实战:Tomcat连接管理的三驾马车 当我们在讨论SpringBoot应用安全时,业务代码的漏洞修复往往占据了大部分注意力。然而,真正的安全防线远不止于此——应用层基础设施的配置与优化同样至关重要。想象一下,你的应…...
5.3、从双亲表示法看树的存储设计哲学
1. 双亲表示法的本质:用数组重构树形关系 第一次接触双亲表示法时,我被它的简洁性惊艳到了——仅用数组就能完整描述整棵树的拓扑结构。这种存储方式的核心在于:每个节点只需要记住自己的父亲是谁。就像现实中的家族族谱,我们通过…...
Windows热键冲突检测终极方案:Hotkey Detective一键定位占用程序
Windows热键冲突检测终极方案:Hotkey Detective一键定位占用程序 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective …...
