HOOK API 在多线程时应该注意的问题点
在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系统软件时,会被时不时的一个内存错误搞得心浮气躁。
HOOK API数量越多,需要注意的内容越多,最近实现HOOK FileSystem API,由于是Kernel32中的函数,所有涉及到文件(filename,filehandle)的API均要被HOOK,同时需要在HOOK中实现overlapped功能,而这个功能点相对比较复杂,连带涉及到完成端口、事件等函数的HOOK。
经过上百个版本的更新调试,目前初步稳定下来,下面列出需要注意的地方,主要是与FileSystem API相关的,其他API(如网络API、内存API等)可能不太适用:
1)从稳定性方面考虑,建议使用JMP方式实现HOOK API,修改IAT的方式不是不可以,而是太容易被其他程序修改而导致不稳定的问题了,大部分杀毒软件均会对IAT进行修改同时保护,所以这种方法要么容易报病毒,要么HOOK失败,同时系统也会对IAT进行修补,对于小型系统或者小量API可能不出现问题,但是对于FileSystem API,个人不推荐。
2)对Vista、WIN7以上的兼容:一开始在XP中进行HOOK时,一切正常,当切换到WIN7后,发现HOOK不起作用,这是由于VISTA、WIN7以上的APP在原来调用Kernel32.DLL的函数时,由于系统AppPatch的功能,已被自动重定向到KernelBase.dll中,而微软有很奇怪的做法,当然估计也是由于兼容性的考虑(即在EXE右键属性中选择兼容XP,VISTA运行时,AppPatch会自动选择重定向哪些API),某些API同时存在于Kernel32和KernelBase中,而不知道是不是重定向功能的不完善还是其他什么原因,同一个App中两个模块即使调用同一个API,也有可能分别跳转到Kernel32和KernelBase中,适用JMP的方式进行HOOK API时,由于通过GetProcAddress获取函数地址,所以均会被自动重定向到KernelBase中,因此需要自己实现一个GetProcAddress函数。
3)多线程同步问题:个人建议使用临界区RTL_CRITICAL_SECTION,不管是开发效率还是运行效率,临界区是首选,对于HOOK后的API中使用不同进程资源的情况,也是在使用临界区进行同步处理后,再去使用其他方法实现的。
4)多线程HOOK后经常卡死的问题,WINDOWS的FileSystem API存在嵌套调用的问题,如CopyFile内部会调用CreateFile等函数,Kernel32的CreateFile会调用KernelBase中的CreateFile,GetFileSize函数内部可能会调用GetFileSizeEx的函数等等,如果在这些函数中同时使用一个内核对象进行同步,必定导致卡死,因此需要考虑这些问题,比如在调用CopyFile时,需要和CreateFile使用不同的内核对象进行同步,而在Kernel32的CreateFile中,需要对KernelBase的CreateFile进行解除HOOK。
5)在HOOK和UNHOOK过程中,需要使用同一个内核对象对WriteProcessMemory进行同步保护,否则将导致进程中某些不可预料的地址内存数据损坏的问题(这个应该是WriteProcessMemory函数内部不支持多线程导致的)。
6)在使用RTL_CRITICAL_SECTION或其他同步函数中,锁的进入和离开函数,尽量使用inline,减少SP的跳转可增加速度,可大大增加多线程切换寄存器的稳定性;
题外话:从硬件上讲CPU只有一套寄存器,但是对于系统运行环境来说,每一个线程(甚至是纤程,即协程或微线程)都有一套虚拟寄存器,这样才能实现不同线程切换时还原所谓的“CPU运行现场”,而每一次SP的跳转从目前各种编译器技术上来讲均会进行所谓的“现场保护”,也就是push各种寄存器,inline函数就是为了减少这种操作的,在于内核打交道的过程中,有些操作是可能被中断的,减少“运行现场”的切换次数必定是大大增强稳定性!
HOOK API 在多线程时应该注意的问题点的更多相关文章
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- [转]Delphi多线程编程入门(二)——通过调用API实现多线程
以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread( lpThreadAttributes: Pointer ...
- 汇编Ring 3下实现 HOOK API
[文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...
- HOOK API(四)—— 进程防终止
HOOK API(四) —— 进程防终止 0x00 前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API ...
- HOOK API(三)—— HOOK 所有程序的 MessageBox
HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...
- HOOK API(二)—— HOOK自己程序的 MessageBox
HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...
- 汇编 -- Hook API (MessageBoxW)
说到HOOK.我看了非常多的资料和教程.无奈就是学不会HOOK.不懂是我的理解能力差.还是你们说的 不够明确,直到我看了下面这篇文章,最终学会了HOOK: http://blog.sina.com.c ...
- HOOK API入门之Hook自己程序的MessageBoxW(简单入门)
说到HOOK,我看了很多的资料和教程,无奈就是学不会HOOK,不懂是我的理解能力差,还是你们说的 不够明白,直到我看了以下这篇文章,终于学会了HOOK: http://blog.sina.com.cn ...
随机推荐
- [HDU 4821] String (字符串哈希)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意:给你M,L两个字母,问你给定字串里不含M个长度为L的两两相同的子串有多少个? 哈希+枚 ...
- Linux Hugepage ,AMM及 USE_LARGE_PAGES for oracle 11G(转载)
1. Hugepage基本概念 系统进程是通过虚拟地址访问内存,但是CPU必须把它转换成物理内存地址才能真正访问内存.为了提高这个转换效率,CPU会缓存最近的“虚拟内存地址和物理内存地址”的 ...
- 11gR2 Clusterware and Grid Home - What You Need to Know
11gR2 Clusterware Key Facts 11gR2 Clusterware is required to be up and running prior to installing a ...
- mysql 使用说明-3
3.4 Getting Information About Databases and Tables 获取数据库和表格的信息 如果你忘记了数据库或者表格的名字怎么办?或者给定的表格的结构怎么办?(例如 ...
- Object的toString决定了重写equals
默认的toString结果public String toString(){ return getClass().getName()+"@"+Integer.toHexStr ...
- FZU Problem 2136 取糖果
Problem 2136 取糖果 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description 有N个袋子放成一排,每个 ...
- Junit3
package code; public class MyCode { public int m1(){ System.out.println("数字型"); return 1; ...
- .NET MVC4.0与CA对接
1.改web.confog 2.引用CA提供的 dll 3.在controller层加个方法,记得加上授权认证的特性,获取信息 [Authorize] publi void calogin() { H ...
- CentOS安装 Docker
系统的要求64 位操作系统,内核版本至少为 3.10. Docker 目前支持 CentOS 6.5 及以后的版本,推荐使用 CentOS 7 系统. cat /proc/version 首先,也是要 ...
- phpexcel 导入导出
导出excel /** * 以下是使用示例,对于以 //// 开头的行是不同的可选方式,请根据实际需要 * 打开对应行的注释. * 如果使用 Excel5 ,输出的内容应该是GBK编码. */ //r ...