日前遇到一件事: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。

advapi32.dll kernel32.dll 中的两套注册表API的更多相关文章

  1. 入侵检测中需要监控的注册表路径研究(Windows Registry Security Check)

    1. Windows注册表简介 注册表(Registry,繁体中文版Windows称之为登录档)是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息.早在Wind ...

  2. Ubuntu中的两套网络连接管理方式

     版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/haifeng_gu/article/details/78286895 Linux里面有两套管理网络 ...

  3. 3dTiles 数据规范详解[3] 内嵌在瓦片文件中的两大数据表

    转载请声明出处:全网@秋意正寒 零.本篇前言 说实话,我很纠结是先介绍瓦片的二进制数据文件结构,还是先介绍这两个重要的表.思前想后,我决定还是先介绍这两个数据表. 因为这两个表不先给读者灌输,那么介绍 ...

  4. Inno Setup中做补丁通过注册表获取原程序安装目录

    今天找VM补丁看到的,是个innosetup封装的,所以习惯性的喜欢去看人家的iss文件是怎么编写的. DefaultDirName={reg:HKLM\SOFTWARE\VMware%2c%20In ...

  5. 关于 JAVA 中使用 Preferences 读写注册表时要注意的地方

    要注意的只有一个地方,那就是键名或者项名不要包含大写字母,否则读不到数据. 代码是这样的: 1: Preferences preferences = Preferences.systemRoot(); ...

  6. MAC中如何配置两套android-sdk环境

    1 背景介绍 随着android studio的完善和普及,越来越多Android app开发者从Eclipse+ADT环境转到Android Studio(后文统一用AS表示).但是,AS往往需要较 ...

  7. 数据结构学习-数组A[m+n]中依次存放两个线性表(a1,a2···am),(b1,b2···bn),将两个顺序表位置互换

    将数组中的两个顺序表位置互换,即将(b1,b2···bn)放到(a1,a2···am)前边. 解法一: 将数组中的全部元素(a1,a2,···am,b1,b2,···bn)原地逆置为(bn,bn-1, ...

  8. SetCookies, cookie规范注册表和cookie存储将会优先于设置在HTTP客户端级别中默认的那些

    遇到下面问题解决方法: Hey? 404 抱歉,你输入的网址可能不正确,或者该网页不存在. 7 秒后返回首页 使用独立的本地执行上下文来实现对每个用户(或每个线程)状态的管理. 定义在本地内容中的co ...

  9. Ruby Rails学习中:注册表单,注册失败,注册成功

    接上篇 一. 注册表单 用户资料页面已经可以访问了, 但内容还不完整.下面我们要为网站创建一个注册表单. 1.使用 form_for 注册页面的核心是一个表单, 用于提交注册相关的信息(名字.电子邮件 ...

随机推荐

  1. js 计算时间

    var date1=new Date();  //开始时间   var date2=new Date();    //结束时间 var date3=date2.getTime()-date1.getT ...

  2. LeetCode OJ:Copy List with Random Pointer(复制存在随机链接的链表)

    A linked list is given such that each node contains an additional random pointer which could point t ...

  3. iOS跳转支付宝付款码和扫一扫页面

    iOS跳转支付宝付款码和扫一扫页面 // 是否支持支付宝 NSURL * myURL_APP_A = [NSURL URLWithString:@"alipay://"]; if ...

  4. JSON数组字典解析

    遇到这样的字典数组字符串 priceRange = "[{\"id\":149075584861800,\"price\":9.9,\"nu ...

  5. awk与sed:一个关于多行处理的例子

    前几天在CSDN上看到一个帖子http://bbs.csdn.net/topics/390848841,楼主贴了下面的问题: 例: 12345 67890 1234567890 123 4567890 ...

  6. java集合运算:求交集,并集,集合差

    今天突然想用Java实现如何用集合实现交集,并集和差集的运算了!主要是看Python语言的时候想起来的. 实现主要使用的Set集合,Set集合的特点是集合内的元素不可重复. 具体代码如何: packa ...

  7. Vim技能修炼教程(7) - 可视模式

    可视模式 可视模式是与正常模式.插入模式一起并列的模式.它的作用就像图形化编辑器下用鼠标来选择一个块. 在vim下,使用正常模式和ex命令,连搜带跳行的,未必就比用鼠标慢. 我们先做一个例子找找感觉, ...

  8. oracle对三个列求sum

    oracle数据库对test_table表的三个列count1,count2,count3求sum的两种sql,做个记录 第一种 select sum (case when count1 is not ...

  9. Jenkins构建持续集成

    Jenkins 是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变得可能.现在软件开发追求的是效率以及质量,Jenkins使得自动化成为可能! 亮点 采用shell自定义脚本,控制 ...

  10. 一个简单的程序,统计文本文档中的单词和汉字数,逆序排列(出现频率高的排在最前面)。python实现。

    仅简单统计英文. from collections import Counter f = open('1') c = Counter() for line in f: g = (x for x in ...