在使用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 在多线程时应该注意的问题点的更多相关文章

  1. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

  2. [转]Delphi多线程编程入门(二)——通过调用API实现多线程

    以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread(    lpThreadAttributes: Pointer ...

  3. 汇编Ring 3下实现 HOOK API

    [文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...

  4. HOOK API(四)—— 进程防终止

    HOOK API(四) —— 进程防终止 0x00        前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API ...

  5. HOOK API(三)—— HOOK 所有程序的 MessageBox

    HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

  6. HOOK API(二)—— HOOK自己程序的 MessageBox

    HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...

  7. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  8. 汇编 -- Hook API (MessageBoxW)

    说到HOOK.我看了非常多的资料和教程.无奈就是学不会HOOK.不懂是我的理解能力差.还是你们说的 不够明确,直到我看了下面这篇文章,最终学会了HOOK: http://blog.sina.com.c ...

  9. HOOK API入门之Hook自己程序的MessageBoxW(简单入门)

    说到HOOK,我看了很多的资料和教程,无奈就是学不会HOOK,不懂是我的理解能力差,还是你们说的 不够明白,直到我看了以下这篇文章,终于学会了HOOK: http://blog.sina.com.cn ...

随机推荐

  1. [HDU 4821] String (字符串哈希)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意:给你M,L两个字母,问你给定字串里不含M个长度为L的两两相同的子串有多少个? 哈希+枚 ...

  2. Linux Hugepage ,AMM及 USE_LARGE_PAGES for oracle 11G(转载)

    1.  Hugepage基本概念     系统进程是通过虚拟地址访问内存,但是CPU必须把它转换成物理内存地址才能真正访问内存.为了提高这个转换效率,CPU会缓存最近的“虚拟内存地址和物理内存地址”的 ...

  3. 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 ...

  4. mysql 使用说明-3

    3.4 Getting Information About Databases and Tables 获取数据库和表格的信息 如果你忘记了数据库或者表格的名字怎么办?或者给定的表格的结构怎么办?(例如 ...

  5. Object的toString决定了重写equals

    默认的toString结果public String toString(){    return getClass().getName()+"@"+Integer.toHexStr ...

  6. FZU Problem 2136 取糖果

     Problem 2136 取糖果 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 有N个袋子放成一排,每个 ...

  7. Junit3

    package code; public class MyCode { public int m1(){ System.out.println("数字型"); return 1; ...

  8. .NET MVC4.0与CA对接

    1.改web.confog 2.引用CA提供的 dll 3.在controller层加个方法,记得加上授权认证的特性,获取信息 [Authorize] publi void calogin() { H ...

  9. CentOS安装 Docker

    系统的要求64 位操作系统,内核版本至少为 3.10. Docker 目前支持 CentOS 6.5 及以后的版本,推荐使用 CentOS 7 系统. cat /proc/version 首先,也是要 ...

  10. phpexcel 导入导出

    导出excel /** * 以下是使用示例,对于以 //// 开头的行是不同的可选方式,请根据实际需要 * 打开对应行的注释. * 如果使用 Excel5 ,输出的内容应该是GBK编码. */ //r ...