FishHook是我开发了将近两年的Windows API Hook库,支持Win7/XP,支持x86和AMD64架构,如果开发成熟了以后也许会开源发布上来的。
最近开发软件工程的大作业项目,用到FishHook,发现各种各样的BUG,这里简单记录下,聊表纪念
14-4-15 发现IE运行在FishHook下时,Hook没有正常工作,结果发现是IE的“保护模式”作崇。保护模式下,程序很难打开其他程序的内核对象(比如公共的Event,FileMappingObject等等),造成我的钩子无法正常与主程序通信。很久以前解决了FileMappingObject的问题(使用了句柄从父进程继承的办法)。Event其实也是需要继承的,但是被我忽略了。。。。。这次发现的问题就在event没法正确打开。在父进程创建IE时把父进程的句柄PUSH进共享内存,IE中得到这些句柄就可以解决问题
4-16 结果另一个浏览器Chrome也出问题了。发现他使用了SUSPEND的参数来CreateProcess他的子进程,我的钩子处理的不好,之前没有认真考虑SUSPEND时候的情况。
临时解决SUSPEND后发现钩子共享内存中的一些关键变量竟然被篡改!使用Windbg的内存断点发现是wcscpy函数的问题。程序被创建时,我把路径和参数写入共享内存,但是没有检查路径字符串的长度,结果竟然造成缓冲区溢出!!!紧邻路径字符串的关键变量被覆盖了。这是我第一次遇到缓冲区溢出的问题,如果这个路径字符串被精心编制,后果不堪设想啊!以后要逐个把wcscpy改为wcsncpy
4-17 Chrome继续出错,调试半天结果是漏继承一个EVENT句柄造成子进程与父进程无法通信。修改后还是会卡住。。。。继续努力
4-18 Chrome的注入bug修复,真是累啊,详见http://hi.baidu.com/myjisgreat/item/8eda051e560db5081994ec1e
主要是低权限的问题。
把所有的*cpy系列函数都加上检查溢出问题的代码或者使用*ncpy函数
终于目前没有已知影响运行的bug了
5-6
之前FishHook使用两个模式,标准钩子模式和用户自定义钩子模式。
标准钩子模式的过滤函数在调试者进程里,当“被调试进程”调用了被hook的函数后,在“调试者进程”里的用户过滤函数将会决定是否放行这个API。这个模式的缺点是只能钩已有的某几个API。优点在于过滤函数集中于“调试者进程”中。
而用户自定义钩子模式只负责把用户的DLL加载到“被调试进程”,并且Hook相关函数(把用户DLL给定的函数代替原有API)。这样,决定被Hook的API的行为的将是用户DLL中的函数。这个模式的优点是相对自由,对于被调用的API用户可以自由控制其行为。而缺点在于过滤函数相当于随DLL加载到“被调试进程”中了,不利于对API在“调试者进程”中统一过滤。
这次更新加强了“用户自定义钩子模式”,提供一整套“同步API”用于“被调试进程”与“调试者进程”的同步,实现了在“用户自定义钩子模式”下也可以远程调用“调试者进程”里的用户过滤函数。
5-13
修改两处“同步API”的bug:
1. 在测试程序中重复命名了一个变量名(记录createfile的返回值的变量和记录远程调用过滤函数的返回值的变量)造成严重混乱
2. 在远程调用过滤函数CallFilter中应该把返回值写入SyncBlock的SharedInfo中,却笔误写入了标准钩子模式的SharedInfo中
6-25
修复问题1:IsWow64Process函数理解的偏差,造成对32位与64位进程判断的偏差
修复问题2:子进程与父进程同步的问题:
原来的设计:被钩的子进程在向父进程发送消息后立即suspend自己;父进程等待消息,收到消息后根据函数参数resume子进程。按照我的想法顺序如下:子进程发送消息-子进程suspend-父进程接受消息-父进程resume子进程
但是在某些情况下,由于父进程与子进程是同时运行的,实际的运行顺序可能是:子进程发送消息-父进程接受消息-父进程resume子进程(子进程仍在运行,所以这一步等于没有做)-子进程suspend
顺序错乱导致子进程被block了。
解决办法:父进程轮询子进程(通过ResumeThread的返回值得知子进程的主线程是不是已经suspend了),如果没有suspend,则sleep(0)放弃当前时间片。经过测试,大概只需要轮询一次循环就可以正常resume了