Windows上的SEH,调用堆栈追溯已经消失

时间:2017-01-07 09:28:06

标签: windows debugging seh

我正在阅读有关Windows上SEH的article。 这是myseh.cpp

的源代码

我调试了myseh.cpp。我在printf("Hello from an exception handler\n");第24行和DWORD handler = (DWORD)_except_handler;第36行设置了2个断点。

然后我跑了它,它突破了线:36。我看到堆栈跟踪如下。

enter image description here 由于mov [eax], 1,发生了 AccessViolationException 然后它突破了线:24。我看到堆栈跟踪如下。 enter image description here

相同的帖子,但main框架消失了!而不是_except_handle。 ESP从0018f6c8跳到0018ef34;这是0018f6c80018ef34之间的巨大差距 处理异常后。

我知道_except_handle必须以用户模式而不是内核模式运行。 返回_except_handle后,线程转到ring0,然后将windows内核修改为CONTEXT EAX&scratch&然后回到ring3。因此线程不断运行。

我很好奇windows处理异常的机制: 为什么调用main框架消失了?

为什么ESP从0018f6c8跳到0018ef34?(我的意思是一个大音调),那些ESP地址是否属于同一个线程的堆栈???内核是否在ring3中对ESP进行了一些技巧?如果是这样,为什么选择0018ef34的地址作为处理程序回调的框架?非常感谢!

1 个答案:

答案 0 :(得分:7)

您使用的是默认调试器设置,但不足以查看所有详细信息。选择它们是为了帮助您专注于自己的代码并尽快启动调试会话。

[外部代码]块告诉您堆栈帧的某些部分不属于您编写的代码。他们不是,他们属于操作系统。使用工具>选项>调试>一般并解开"启用我的代码"选项。

[下面的框架可能不正确...]警告告诉您调试器没有准确的PDB来正确地移动堆栈。使用工具>选项>调试>符号并勾选" Microsoft Symbol Servers"选项并选择缓存位置。调试器现在将下载您需要通过操作系统DLL调试的PDB。可能需要一段时间,它只需要完成一次。

你可以推断出大的ESP改变,CONTEXT结构相当大,占用了堆栈空间。

在这些变化之后,你现在应该看到类似的东西:

ConsoleApplication1942.exe!_except_handler(_EXCEPTION_RECORD * ExceptionRecord, void * EstablisherFrame, _CONTEXT * ContextRecord, void * DispatcherContext) Line 22    C++
ntdll.dll!ExecuteHandler2@20()  Unknown
ntdll.dll!ExecuteHandler@20()   Unknown
ntdll.dll!_KiUserExceptionDispatcher@8()    Unknown
ConsoleApplication1942.exe!main() Line 46   C++
ConsoleApplication1942.exe!invoke_main() Line 64    C++
ConsoleApplication1942.exe!__scrt_common_main_seh() Line 255    C++
ConsoleApplication1942.exe!__scrt_common_main() Line 300    C++
ConsoleApplication1942.exe!mainCRTStartup() Line 17 C++
kernel32.dll!@BaseThreadInitThunk@12()  Unknown
ntdll.dll!__RtlUserThreadStart()    Unknown
ntdll.dll!__RtlUserThreadStart@8()  Unknown

在Win10版本1607和VS2015 Update 2上录制。这不是编写SEH处理程序的正确方法,在this post中找到更好的示例。