Windows异常世界历险记(三)——VC6中结构化异常处理机制的反汇编分析(上)

在《Visual C++异常处理机制原理与应用》部分,我们讲解了Visual C++提供的结构化异常处理机制,并对其中比较简单的终止型异常处理程序在部分条件下(自然执行、提前越出、__leave关键字等)进行了反汇编分析。下面我们继续对整个Visual C++结构化异常处理机制进行分析。

本次分析的目标环境是VC++ 6.0,这是一款已经有些“美人迟暮”的集成开发环境。使用它进行分析,主要原因如下:

  1. 仍有不少程序使用VC++ 6.0开发和编译(特别是恶意代码、灰产代码等)

  2. Visual Studio的发展是一脉相承的,VC++ 6.0所使用的异常处理机制也为后续Visual Studio所借鉴并发展,大框架并没变。VC++ 6.0中的结构化异常机制相对比较简单,却囊括了所有关键部分。

因此,下面先在VC++ 6.0环境下进行相关分析,完毕后再分析Visual Studio 2017中C/C++结构化异常处理机制。

测试代码与分析

下面是用于测试的代码:

#include <windows.h>
#include <tchar.h>

int ExceptFilterInner(DWORD dwExceptionCode)
{
    MessageBox(NULL, TEXT("Inner try`s filter running"), TEXT("Inner Try"), MB_OK);
    if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION)
    {
        return EXCEPTION_CONTINUE_SEARCH;
    }
    else
    {
        return EXCEPTION_CONTINUE_EXECUTION;
    }
}

int ExceptFilterOuter()
{
    MessageBox(NULL, TEXT("Outer try`s filter running"), TEXT("Outer Try"), MB_OK);
    //return EXCEPTION_CONTINUE_SEARCH;
    return EXCEPTION_EXECUTE_HANDLER;
}

void RaiseExcept()
{
    __try
    {
        _try
        {
            *(PDWORD)NULL = 0;
        }
        __finally
        {
            MessageBox(NULL, TEXT("Inner::Finally block execute"), TEXT("In Inner::finally"), MB_OK);
        }
    }
    __except (ExceptFilterInner(GetExceptionCode()))
    {
        MessageBox(NULL, TEXT("Never execute"), TEXT("haha"), MB_OK);
    }
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
    __try
    {
        __try
        {
            RaiseExcept();
        }
        __finally
        {
            MessageBox(NULL, TEXT("Outer::Finally block execute"), TEXT("In Outer::finally"), MB_OK);
        }
    }
    __except (ExceptFilterOuter())
    {
        MessageBox(NULL, TEXT("Outer try catched"), TEXT("haha"), MB_OK);
    }
    return 0;
}

在WinMain中设置了两个try块,其中:

  1. 内层的try块为try-finally终止异常处理
  2. 外层try块为try-except型异常处理,能处理任何异常程序

而在WinMain中被try块保护范围内,调用了一个名为RaiseExcept的函数,该函数被两层try块保护,其中执行了一段导致违规访问的代码:

  1. 内层try块为try-finally终止型异常处理

  2. 外层try块为try-except异常处理,但不处理违规访问类型的异常

按照之前的分析,执行的顺序是:

  1. RaiseExcept中外层try-except中的过滤函数,而该异常处理块不处理此类型异常;

  2. 转而执行WinMain中外层try-except的过滤函数,并确定该异常处理块可以执行此类异常;

  3. 执行RaiseExcept内层finally块的代码

  4. 执行WinMain内层finally块的代码

  5. 执行WinMain中try-except的异常处理代码

异常处理块的安装和卸载

WinMain中的异常处理函数

43:   int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
44:   {
00401220 55                   push        ebp
00401221 8B EC                mov         ebp,esp
00401223 6A FF                push        0FFh
00401225 68 38 21 42 00       push        offset string "In Outer::finally"+18h (00422138)
0040122A 68 60 14 40 00       push        offset __except_handler3 (00401460)
0040122F 64 A1 00 00 00 00    mov         eax,fs:[00000000]
00401235 50                   push        eax
00401236 64 89 25 00 00 00 00 mov         dword ptr fs:[0],esp
; 省略部分代码
45:       __try
00401255 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0   ; tryLevel置为0,表明进入外层try块
46:       {
47:           __try
0040125C C7 45 FC 01 00 00 00 mov         dword ptr [ebp-4],1   ; tryLevel置为1,表明进入第二层try块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值