advapi32.dll kernel32.dll 中的两套注册表API

日前遇到一件事:WebBrowser中的网页会用到一个“大众”ActiveX控件,为了保证兼容性以及和其它程序互不干扰,咱们采用这样一种方案:
1. 咱们的软件会自带该控件;
2. 若是系统中已注册有该控件的话,咱们不用会咱们的控件进行覆盖注册;
3. 无论怎么样,咱们的程序都只会加载咱们自带的控件。
 
要作到第3条,显然要HOOK控件位置有关的注册表项。由于以前在作播放器时使用过一样的手段来处理媒体解码器,因此其实并无什么难度。但事实上却差点阴沟里翻船。
 
我必定肯定以及确定的是,我须要HOOK的只有几个API:RegQueryValue、RegQueryValueEx、RegGetValue。用ZwQueryKey还原一下路径,若是路径是"CLSID\{GUID}\InprocServer32",把咱们自带控件的路径返回便可。
 
然而,程序实际运行却并无预期效果,程序虽然执行到了API的替代函数中,可是结果却要么加载到其它版本的控件,要么加载失败。
 
修正了数遍代码,把捕获条件放宽收窄N次,尝试HOOK其它一些API以后,换了N台机器,检查了N遍注册表后,问题依旧。
 
跟踪了无数遍,程序始终会执行到API的替代函数中,也返回了正确结果。可是在procemon的监测里,却又始终能看到返回注册表中真实值的注册表读取操做。
我花了一些时间后,意识到:在API替代品中就已经被我处理掉的请求,应该是不会进入到Procemon纪录中的。也就是说,procemon中监控到的请求,跟被我HOOK到的请求,实际上是来自彻底不一样的调用路径。可是查看procemon纪录中这些操做的调用堆栈,无一不是来自已经被我HOOK了的API。
 
这说明了一个更加难以解释的问题:一样的API,一样的参数(路径),为何有些可以HOOK到,有些则HOOK不到?
 
为此又回过头去检查和修正捕获操做的代码,但毫无收获。
 
最后告诉我答案的来自美工使用旧版本程序的一个错误报告:XP系统下提示Advapi32.dll找不到某注册表API。我忽然想起,procemon纪录中的调用堆栈中的API,彷佛并非Advapi32.dll模块的,而是Kernel32.dll。立刻查询了一下,确认程序连接的都是Advapi32.dll,而procemon中监控到的,也确认属于Kernel32.dll。
 
答案呼之欲出,用depends看了一下Lernel32.dll,果真如此,如出一辙的API,一个很多!!!也就是说,我HOOK了advapi32.dll的API,但程序却明修栈道,暗渡陈仓,调用了一两次advapi32.dll中的API,最后却从Kernel32.dll绕道去拿了数据。
 
虽然问题找到了,可是依然仍是不太明白。之前HOOK注册表并无出现过相似问题,显然,那些程序里注册表调用都走的是Advapi32.dll,MSDN中全部的注册表API也都注明在Advapi32.dll里,那为何这一次却到了Kernel32.dll,惟一能想到的解释,或许这IE内核有关。但这一点就无力求证了。
 
最后,虽然没有文档告诉我Kernel32.dll中注册表函数的原型,但尝试用Advapi32.dll中的原型HOOK了一下,程序正常。可见是一个牌子,两套班子。
 
Tip:RegGetValue要求Vista以上或XP64bit。
相关文章
相关标签/搜索