• 内核层异常的收集与处理


    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

    内核层异常的收集与处理

      前面我们分析过,存在两种异常,CPU异常与用户模拟异常,其异常触发时收集的线路是不同的,但是其最终走经过KiDispatchException函数。

      当走到KiDispatchException,CPU异常与用户模拟异常唯一的区别是CPU异常最高位置1(nt!KiRaiseException异常派发时的上一行代码),其余记录的都是一样的。

      而KiDispatchException的处理是按照其先前模式来处理的,也就是内核异常与用户异常两种,而不是按照CPU异常与用户模拟异常来进行处理。

     

    1.内核层异常的派发(Nt!KiDispatchException函数分析)

      这部分我们先看内核异常的处理流程,至于用户模式,其因为要返回三环执行,稍微复杂,等其分析完成之后再来一起进行汇总处理。

      如下图,我们截取一部分,其核心的执行流程为:

      ① 如果存在内核调试器则调用内核调试器;

      ② 如果不存在或者不成功,调用RtlDispatchException调用内核的SEH异常来进行处理;

      ③ 如果RtlDispatchException不成功,则再次尝试判断内核调试器;

      ④ 如果上面某一步成功,则直接返回正常退出;

      ⑤ 否则调用KeBugCheckEx触发蓝屏。

      

    2.内核层异常的处理(Nt!RtlDispatchException函数分析)

      该函数是处理内核异常的核心函数,如果没有内核调试器,则就使用这个函数来进行分析,其操作如下所示:

      其中,我们在分析前必须要有几个重要的数据结构:

      1)异常的标志位 flag

        #define EXCEPTION_NONCONTINUABLE 0x1    // Noncontinuable exception
        #define EXCEPTION_UNWINDING 0x2         // Unwind is in progress
        #define EXCEPTION_EXIT_UNWIND 0x4       // Exit unwind is in progress
        #define EXCEPTION_STACK_INVALID 0x8     // Stack out of limits or unaligned
        #define EXCEPTION_NESTED_CALL 0x10      // Nested exception handler call
        #define EXCEPTION_TARGET_UNWIND 0x20    // Target unwind in progress
        #define EXCEPTION_COLLIDED_UNWIND 0x40  // Collided exception handler call

      2)异常结果的返回值

          enum _EXCEPTION_DISPOSITION {
            ExceptionContinueExecution = 0,  // 异常处理成功
            ExceptionContinueSearch = 1,    // 异常没有处理,继续寻找
            ExceptionNestedException = 2,   // 二次异常,存在嵌套异常
            ExceptionCollidedUnwind = 3   // 发生嵌套的展开
          };

        注意:如果是SEH扩展的异常,我们使用这个,因为其使用SEH拓展结构,需要进行异常展开的操作,这些对程序员是不可见的。

        平时我们再手动写SEH异常,不需要操心异常的展开等额外操作,所以使用下面的结构:

         #define EXCEPTION_EXECUTE_HANDLER      1     // 异常被识别,_except模块中处理该异常
         #define EXCEPTION_CONTINUE_SEARCH      0    // 异常未被识别,继续调用下一个Handler来处理异常
         #define EXCEPTION_CONTINUE_EXECUTION (-1)   // 异常已被忽略或修复,不继续往下寻找

      该函数的核心操作如下:

      ① 通过KPCR获取异常链;

      ② 取出一个异常处理结点,ExceptionRegistrationRecord(next,handler);

      ③ 通过全局变量判断是否需要异常记录;

      ④ 执行对应的handler函数,获取返回结果;

      ⑤ 如果返回为 ExceptionContinueExecution并且eflags的EXCEPTION_NONCONTINUABLE位为0,则返回成功;

      ⑥ 否则继续找下一个,处理失败,或者引发二次异常。

       

    3.总结

      这里我们只是简单分析了一下内核层的SEH异常的大体流程,其中我们会发现二次异常的嵌套以及展开UnWind等操作,这里可能会让你感到头晕,

      没关系,我们在分析用户异常时会详细解释其编译器对于SEH异常的拓展,之后我们会讲解局部展开与全局展开等骚操作,之后你再看这里就能很好理解了。

  • 相关阅读:
    【转载】超级实用且不花哨的js代码大全 -----高级应用(一)
    【 Date 对象 参考手册】
    js随机数random()方法
    【转载】js数组的操作
    【转载】js数组和json的区别
    干货----004----MySQL忘记root密码怎么办?
    PHP框架——TP_0001----ThinkPHP常用配置
    干货----003----乱码解决方法
    Python之路【第二十六篇】:xml模块
    Python之路【番外篇1】:使用Python创建照片马赛克
  • 原文地址:https://www.cnblogs.com/onetrainee/p/12771544.html
Copyright © 2020-2023  润新知