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个字)
今天蹲坑,低头看了下工牌觉得挺有意思:我从啥时候起也不排斥将工牌挂在脖子上了? 工牌,一个标识。不仅标识了你,也标识了你所在的群体。如果你认可这个群体,佩戴它那是一种荣誉、荣耀;如果你不…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...