一周回顾
辞掉了JBNS的兼职后,我的生活发生了很大的变化,可能是因为没有固定的作息时间来约束我了吧,我再也不用每天早上七点二十就起床了。这些天武汉一直都在下雨,温度也降得厉害,赖床的恶习也开始死灰复燃了。
上周二去实验室登记的,其实我的毕设工作几天之前就开始动工了。说下进度吧。
我现在要做的事情是拦截软件安装过程中所有对文件和注册表的访问(主要是写操作)。在软件安装完成后将软件安装过程中生成和修改过的文件打成RA包,而对注册表的访问则写成REG文件,也一定打入RAR包中。
开始时李学长给我看了一篇关于便携桌面应用程序的论文,其实里面也包括了我要实现的功能了。论文中对文件和注册表拦截这一块是通过API拦截来实现的,用的是他们自己写的一个基于微软的Detours的包。后来我在网上发现了一个实现API拦截的更好的方法,即是基于manifest文件的DLL重定向。所以我一开始是打算采用这个方法的,这种方法只需要在软件安装程序的相同目录下建立一个对应的manifest文件,该manifest指明了优先从应用程序所在目录寻找相关的DLL。我们要做的就是自己写一个DLL,比如user32.dll,在这个DLL中重定相关的API函数,从而实现API的拦截。对于该DLL中我们并不想拦截的API函数,可以再将其重定向到系统的那个DLL中。
然而我只是测试了几个简单的函数,学长说这种基于manifest的方法不是很好,应该弄一个可以拦截磁盘访问的。于是我只好再寻其他的方法了。这个时候想起了论文中提到的detours。detours现在的最新版本是2.1的,其旧版本中比较常用的是1.5,而2.1相较1.5而言,改动是很大的。2.1版中的API拦截只能针对某个线程,或者是通过在进程启动时注入DLL来实现。而1.5是可以拦截所有进程的。我觉得2.1应该也可能实现对当前机器止所有正在运行程序的API访问拦截的,但是它要获取相应的线程句柄,这个还比较难办。而1.5就缺少了一些安全机制,而且也工作得不是很好,只要我一启动拦截,Explorer.exe就马上挂断了,应该是替换的API函数写得有问题吧,我是嫌太难调试了,Explorer.exe挂掉搞不好就要注销一次。
于是决定回到detours2.1,只监控指定进程。刚开始时测试的几个API还比较正常,不过后来测试注册表函数的时候就开始遇到麻烦了,比如Photoshop在安装程序的最后,即修改注册表的时候会提示遇到问题要关闭(Access Violation),而有道则根本无法启动。在vs2005中调试,都是说在RegOpenKeyEx上出现访问冲突。在网上搜了很长时间,后来在微软的官网上找到了一个可能的理由:在我的替换DLL中,我需要加载系统原来的DLL中的函数,但是原来的DLL已经被其他的DLL加载了,而advpi32中的RegOpenKey可能访问了一个未被初始化的关键代码段,从而造成访问冲突。
后来证明通过manifest文件的方法也会有这一样的问题。
耗了几天时间,感觉都浪费了。眼看着不能如期达到目标了,学长说就用C#来写吧,C#实现文件访问的操作可是相当简单的。于是从没有接触过.net跟C#的我开始装VS2005,看C#。C#提供了一个FileSystemWatcher这个类的支持,所以实现起来就相当简单了。剩下的不是注册表了,在网上找C#的代码,点遍了GOOGLE也没有发现一个好用的C#注册表拦截器。很多例子都只能指出某个键发生了改动,而不能指明发生了何种改动。有一个程序可以监测到某键下的所有项的改动,但是不能监测到其子键的改动,因为它还是基于那个API的,对项改动的监视是通过重复枚举和扫描来实现的,这很显然是一个相当原始的方法。
后来只好拿RegMon来开刀了,它是从驱动级来写的,而且程序中所有的界面工作都是手工完成,可见程序作者之牛了。我把程序中的一些我们用不着的代码给删减减了,然后把界面去掉,再给它传递相关的参数,然后在我的C#程序中创建一个新的进程来调用它。呵呵,这样一来事情就好办多了。
今天给程序添加了根据文件和注册表的拦截记录来拷贝文件和生成REG文件的功能。还不是很麻烦,大体工作都完成的差不多了。不过在调用RAR的时候还有些小问题需要我去解决。首先是先成的RAR文件里面多了几级父目录,然后是我想把压缩进度显示出来,这个暂时还没有很好的办法。我原以为通过进程的输出重定向就可以了的,但事实上这根本没有什么效果。
终于在新的一周开始之前完成了这份工作,明天开始新的任务了,当然这几天的东西还要改进的。
很久很久没有写过东西了,有点语无伦次。