内联asm分配给' FS:0':处理程序未注册为安全处理程序

时间:2016-05-18 11:19:47

标签: c++ visual-studio-2015 inline-assembly seh

我正在尝试关注有关Win32结构化异常处理的this文章。这篇文章很老了,但仍然被认为是对这个主题的一个非常好的介绍。

我正在尝试从下面的文章中编译代码示例 -

//==================================================
// MYSEH - Matt Pietrek 1997
// Microsoft Systems Journal, January 1997
// FILE: MYSEH.CPP
// To compile: CL MYSEH.CPP
//==================================================
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

DWORD  scratch;

EXCEPTION_DISPOSITION
__cdecl
_except_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void * EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void * DispatcherContext )
    {
    unsigned i;

    // Indicate that we made it to our exception handler
    printf( "Hello from an exception handler\n" );

    // Change EAX in the context record so that it points to someplace
    // where we can successfully write
    ContextRecord->Eax = (DWORD)&scratch;

    // Tell the OS to restart the faulting instruction
    return ExceptionContinueExecution;
    }

int main()
{
    DWORD handler = (DWORD)_except_handler;

    __asm
    {                           // Build EXCEPTION_REGISTRATION record:
        push    handler         // Address of handler function
        push    FS:[0]          // Address of previous handler
        mov     FS:[0],ESP      // Install new EXECEPTION_REGISTRATION
    }

    __asm
    {
        mov     eax,0           // Zero out EAX
        mov     [eax], 1        // Write to EAX to deliberately cause a fault
    }

    printf( "After writing!\n" );

    __asm
    {                           // Remove our EXECEPTION_REGISTRATION record
        mov     eax,[ESP]       // Get pointer to previous record.
        mov     FS:[0], EAX     // Install previous record
        add     esp, 8          // Clean our EXECEPTION_REGISTRATION off stack
    }

    return 0;
}

用&#34; cl&#34;编译它时,它似乎产生了一个可执行文件,但也引发了以下错误:

myseh.cpp(42) : warning C4733: Inline asm assigning to 'FS:0': handler not registered as safe handler
myseh.cpp(56) : warning C4733: Inline asm assigning to 'FS:0': handler not registered as safe handler

可执行文件崩溃,并且它看起来不像自定义异常处理程序正在执行其工作。 搜索互联网似乎表明我需要将自定义异常处理函数注册为安全异常处理程序。我不是专业开发人员。但我还是想关注这篇文章。我需要一些关于如何获得可执行文件的指导。

我在Windows 10上使用Visual Studio 2015.

2 个答案:

答案 0 :(得分:1)

来自C4733警告的说明:

  

内联asm分配给&#39; FS:0&#39; :处理程序未注册为安全   处理

     

修改FS:0处的值的函数,以添加新的异常   处理程序可能无法使用安全例外,因为处理程序可能不会   被注册为有效的异常处理程序(请参阅/ SAFESEH)。

     

要解决   此警告,要么删除FS:0定义,要么关闭它   警告并使用.SAFESEH来指定安全的异常处理程序。

这基本上意味着您尝试在生成的可执行映像中使用未注册为安全SEH处理程序的处理程序。
根据您的链接器设置,它可能会也可能不会执行。

默认情况下,链接器会生成安全处理程序表,但它不知道您的.safeseh是异常处理程序,因此它不会将其放入安全SEH处理程序表< / em>的。要解决它,你基本上有两个选择:

  • 使用/SAFESEH:NO MASM指令将您的函数标记为安全处理程序 您必须将其放入单独的ASM文件中,因为内联汇编不支持这些指令。

  • 使用md-select开关指示链接器不创建安全处理程序表 这种方式将是您的可执行文件中的任何SEH处理程序视为操作系统的安全处理程序。

我建议查看/SAFESEH链接器开关和.safeseh MASM指令文档以获取更多信息。

有关安全SEH处理程序的更多信息,请参阅此article

  

一般的想法是收集处理程序&#39;指定的入口点   只读表,并根据此表验证每个入口点   对于控制传递给处理程序之前的异常。

答案 1 :(得分:0)

经过大量的反复试验后,对我有用的是:

cl /c myseh.cpp
link myseh.obj /SAFESEH:NO

虽然,我仍然想知道如何将异常处理程序注册为安全异常处理程序。