反思一个问题的解决过程:多思考

反思一个问题的解决过程:多思考

今天来了后我就一直在调试驱动中没有在创建进程前向上层通知的问题,中间经历了几个过程,现在回想一下,如果是当时看代码的时候如果能够深入一些,应该就会一次解决问题的,会节约很多时间。

 

一、问题的来源

我们目前在做的一个软件中有一个功能是监视系统的进程创建,在进程创建前后创建后需要通知上层或者用户做出相应的反应。昨天我测试了进程通知的功能,发现以前的代码实际上完成的是进程创建后的通知,而我们现在需要的是进程创建前的通知。

  在代码中发现有进程创建函数 HOOK 的功能,其中进程创建函数 hook 的功能被注释掉了。于是把注释去掉,打开进程创建函数 HOOK 的功能,测试发现还是有问题。由于这些功能都是在驱动中的,调试起来比较麻烦,我现在虽然用虚拟机在调试,但是启动虚拟机后系统反应比较慢,因此我准备用输出 log 的方式来查看代码的运行情况。

昨天我在驱动中的替换的函数地方加了 log 输出,测试后发现没有输出,说明 hook 功能没有成功。今天上班后我的第一个任务就是检查 hook 的代码。

 

二、注册表的设置

  Hook 函数是在函数 SetSystemNotifiers 中进行的,调用的是函数 HookNtFunc ,我看了一下实现,发现有如下的代码:

if (!FlagOn( Globals.m_DrvFlags, _DRV_FLAG_HAS_SYSPATCH ))

              return FALSE;

看来这个功能是用一个标志来进行开关设置的,如果标志是默认关闭的,那么当然昨天的工作是不可能有效果的。需要马上检查该开关是如何初始化,什么地方设置的。

  在代码中我搜索了一下 _DRV_FLAG_HAS_SYSPATCH ,发现只有一个地方进行了设置,其他地方都是获取该变量标志的值。设置这个值的地方是在函数 CheckSysPatch 中,代码写的很清楚:

       if (g_bIsW2003 || g_bIsW2K || g_bIsWXP)

       {

              NTSTATUS status = RegQueryValue( L"SysPatch", &dwValue );

              if (NT_SUCCESS(status) )

              {

                     if (1 == dwValue)

                            SetFlag( Globals.m_DrvFlags, _DRV_FLAG_HAS_SYSPATCH );

              }

       }

这就是在说表标志是从注册表中读取的。终于发现了问题,我马上修改安装文件和配置文件,在安装的时候把这个标志设置进去。

在修改之后,重新安装驱动,启动系统。首先我用 TraceView 查了一下在新创建进程下 Log 的输出情况,奇怪的是仍然没有发现有关于进程创建前 log 的输出。想到冰刃有查看 SSDT 的功能,我启动冰刃查看一下,结果冰刃显示函数没有 hook

 

三、启动入口代码的修改

  调试到了这种情形确实很让人挠头,不应该发生的事情发生了。没有办法,我觉得调试一下驱动,不管系统反应慢,这是最后一招了。

  于是启动 WinDBG 调试器,准备设置一下断点,但是发现因为驱动没有启动,设置驱动入口例程的,但是现实断点无效。不管了,先启动系统进入调试。不管事情比较顺利的是系统竟然在驱动入口处中断了,很好啊。马上开始单步执行,到了初始化的地方,发现原来 CheckSysPatch 没有调用。以前看代码的时候对这些不熟悉,后来驱动出了问题就屏蔽了很多代码,这段代码就属于屏蔽之列。真后悔啊。马上修改,重新编译。

 

四、功能完成?

  这个问题解决了吗? No 。因为在我准备测试的时候,老大来了告诉我们有新的事情需要做,这个事情先撂下。

  事后我总结了一下,要是我一开始就专心去看源代码,把源代码彻底弄清楚, SSDT 的过程弄清楚,那么虽然时间也会长些,但是对以后的工作打了一个很好的基础。现在的情况是,看见一点问题就去测试,就去修改,就去调试,结果总是出乎自己的预料。想起来以前看到的一个博客说的:写代码要多思考少用电脑。

搞清楚事情的来龙去脉总是不会有错的

猜你喜欢

转载自luck-donkey.iteye.com/blog/999034