用户层异常的处理 - VEH异常

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

用户层异常的处理 - VEH异常

 

1.初始VEH异常

  1)VEH异常链表是一个全局链表,其模板如下:

    LONG NTAPI VehFunc(struct _EXCEPTION_POINTERS* ExceptionInfo) {
        return  EXCEPTION_CONTINUE_SEARCH;
    }
    int main(int argc, char* argv[])
    {
        // 1-veh链头部,0-veh链尾部。
        AddVectoredExceptionHandler(1,VehFunc);
        return 0;
    }
    其中 _EXCEPTION_POINTER结构体如下:

    typedef struct _EXCEPTION_POINTERS {
        PEXCEPTION_RECORD ExceptionRecord; // 异常记录
        PCONTEXT ContextRecord;  // 异常发生时的各个寄存器的值
    } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

  2)VEH异常的返回值

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

     注意:SEH异常与VEH异常返回值是不同的,对于SEH异常,其返回的是一个 enum EXCEPTION_DISPOSITION。

  3)我们根据ContextRecord中保存的寄存器我们就可以实现对我们的代码出现异常的修复,下面是除零异常代码的修复: 

复制代码
LONG NTAPI VehFunc(struct _EXCEPTION_POINTERS* ExceptionInfo) {
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xc0000094) {
        ExceptionInfo->ContextRecord->Eip += 2;
        printf("除零异常已被处理了!\n");
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return  EXCEPTION_CONTINUE_SEARCH;
}
int main(int argc, char* argv[])
{
    // 1-veh链头部,0-veh链尾部。
    AddVectoredExceptionHandler(1,VehFunc);
    _asm {
        mov ebx, 0;
        mov eax, 1;
        idiv ebx;
    }
    return 0;
}
复制代码

 

2. Ntdll!RtlAddVectoredExceptionHandler函数分析

  该函数分析如下,值得注意的是其中的Handler都是被加密的,因此这意味着你不能手动向Veh中加入链表然后期待着被调用触发。

  可以看出其调用AllocateHeap,说明存储在堆中,作为一个进程是全局共享的。

  

 

3. Ntdll!RtlCallVectoredExceptionHandlers函数分析

  该函数就是遍历VEH链表找到函数来进行分析,其函数结构时相当清晰地,VEH的handler被加密了,此时会执行加密。

  整体的处理流程下面已经分析地相当透彻了,这里就不在做过多的解释了。

  

posted @ 2020-04-25 16:50  OneTrainee  阅读(942)  评论(0编辑  收藏  举报