<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[Boxcounter 的烂笔头 - All Forums]]></title>
		<link>http://boxcounter.com/</link>
		<description><![CDATA[Boxcounter 的烂笔头 - http://boxcounter.com]]></description>
		<pubDate>Tue, 07 Feb 2012 03:14:04 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[加强版的OsrNTStatusToString]]></title>
			<link>http://boxcounter.com/showthread.php?tid=80</link>
			<pubDate>Wed, 01 Feb 2012 10:47:05 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=80</guid>
			<description><![CDATA[之前一直用osr的OsrNTStatusToString来显示NTSTATUS的字符串形式，很省事。但是有个缺陷，osr应该是基于比较早的ntddk来整理的，不&#8203;全，比如minifilter专用的NTSTATUS。<br />
于是花了一点时间用最新的wdk整理了一份，可以比较完美替换osr的那份。需要的童鞋请自取。（整理的方法比较简单，主要用到vim和正则表达式）<br />
目前只在最新的wdk上测试过，如果有BUG请告知我，谢谢。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".7z" />&nbsp;&nbsp;<a href="attachment.php?aid=20" target="_blank">StatusStr.7z</a> (Size: 24.3 KB / Downloads: 178)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[之前一直用osr的OsrNTStatusToString来显示NTSTATUS的字符串形式，很省事。但是有个缺陷，osr应该是基于比较早的ntddk来整理的，不&#8203;全，比如minifilter专用的NTSTATUS。<br />
于是花了一点时间用最新的wdk整理了一份，可以比较完美替换osr的那份。需要的童鞋请自取。（整理的方法比较简单，主要用到vim和正则表达式）<br />
目前只在最新的wdk上测试过，如果有BUG请告知我，谢谢。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".7z" />&nbsp;&nbsp;<a href="attachment.php?aid=20" target="_blank">StatusStr.7z</a> (Size: 24.3 KB / Downloads: 178)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[无锁数组]]></title>
			<link>http://boxcounter.com/showthread.php?tid=79</link>
			<pubDate>Sun, 15 Jan 2012 15:05:08 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=79</guid>
			<description><![CDATA[项目里有一个地方可能要去掉用于链表的锁，但是又得保证读写互斥。于是琢磨了一个土办法：<br />
（琢磨时的目标是用于异步发送日志，即多个日志存储者，一个发送者，接收者在另一个进程不用管它）<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>#define N 200<br />
PVOID g_Buffer[N] = {0};<br />
UINT&nbsp;&nbsp;g_uSaveIndex = 0;<br />
<br />
<br />
VOID <br />
&nbsp;&nbsp;&nbsp;&nbsp;Save(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID pLog<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;UINT uMySaveIndex = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PVOID pOldLog = NULL;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 获取目前可以操作的数组下标<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;uMySaveIndex = InterlockedIncrement(&amp;g_uSaveIndex) % N;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 存储日志<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;pOldLog = InterlockedExchangePointer(g_Buffer[uMySaveIndex], pLog);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (NULL != pOldLog)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 这个数组单元有老日志，释放这条老日志。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; （这条老日志距离本条日志中间已经有2000条日志了，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 这么久都没有发送出去，说明日志存储速度可能远大于发送速度，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 只能抛弃一部分日志了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 如果不希望抛弃任何日志，那可以考虑使用链表，而不是用数组。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
}<br />
<br />
<br />
<br />
VOID <br />
&nbsp;&nbsp;&nbsp;&nbsp;Send(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static UINT uSendIndex = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PVOID pLogToSend = NULL;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;pLogToSend = InterlockedExchangePointer(g_Buffer[uSendIndex++ % N], NULL);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 发送并清理日志<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
}</code></div></div>
]]></description>
			<content:encoded><![CDATA[项目里有一个地方可能要去掉用于链表的锁，但是又得保证读写互斥。于是琢磨了一个土办法：<br />
（琢磨时的目标是用于异步发送日志，即多个日志存储者，一个发送者，接收者在另一个进程不用管它）<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>#define N 200<br />
PVOID g_Buffer[N] = {0};<br />
UINT&nbsp;&nbsp;g_uSaveIndex = 0;<br />
<br />
<br />
VOID <br />
&nbsp;&nbsp;&nbsp;&nbsp;Save(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID pLog<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;UINT uMySaveIndex = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PVOID pOldLog = NULL;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 获取目前可以操作的数组下标<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;uMySaveIndex = InterlockedIncrement(&amp;g_uSaveIndex) % N;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 存储日志<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;pOldLog = InterlockedExchangePointer(g_Buffer[uMySaveIndex], pLog);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (NULL != pOldLog)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 这个数组单元有老日志，释放这条老日志。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; （这条老日志距离本条日志中间已经有2000条日志了，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 这么久都没有发送出去，说明日志存储速度可能远大于发送速度，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 只能抛弃一部分日志了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 如果不希望抛弃任何日志，那可以考虑使用链表，而不是用数组。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
}<br />
<br />
<br />
<br />
VOID <br />
&nbsp;&nbsp;&nbsp;&nbsp;Send(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static UINT uSendIndex = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PVOID pLogToSend = NULL;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;pLogToSend = InterlockedExchangePointer(g_Buffer[uSendIndex++ % N], NULL);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 发送并清理日志<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
}</code></div></div>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[求垃圾回复拦截插件]]></title>
			<link>http://boxcounter.com/showthread.php?tid=78</link>
			<pubDate>Sun, 15 Jan 2012 09:32:30 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=78</guid>
			<description><![CDATA[最近我的blog每天只能都有垃圾右键，人工删不过来，验证码什么的早就加上了。求适用于mybb论坛的自动拦截垃圾回复的插件……]]></description>
			<content:encoded><![CDATA[最近我的blog每天只能都有垃圾右键，人工删不过来，验证码什么的早就加上了。求适用于mybb论坛的自动拦截垃圾回复的插件……]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[程序猿的字体]]></title>
			<link>http://boxcounter.com/showthread.php?tid=77</link>
			<pubDate>Mon, 26 Dec 2011 19:22:56 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=77</guid>
			<description><![CDATA[作为一名光荣的程序猿，我对字体的挑剔程度一点也不亚于对编辑器的挑剔程度。<br />
<br />
之前一直用consolas字体编码。这个字体英文看着很舒服，但是貌似是没有中文部分的，中文使用的是宋体。虽然宋体使用范围很广，很多人都偏爱。但是我却不咋喜欢，感&#8203;觉字体怪怪的。中文我更倾向于雅黑字体。<br />
<br />
自然也就希望能兼得两者所长，之前用emacs的时候可以设置，中文用雅黑英文用consolas，但是后来习惯不了emacs的各种问题（比如翻页刷新效率，启动慢，e&#8203;cb自动补全慢等等），于是又捡起vim。vim不支持同时使用两种字体，于是只好囧囧的用纯consolas。<br />
<br />
朋友推荐混合字体，我也关注了一下，网上大部分的consolas+雅黑的混合字体都有瑕疵，比如下图所示：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=13" target="_blank">有瑕疵的混合字体.jpg</a> (Size: 4.18 KB / Downloads: 20)
<!-- end: postbit_attachments_attachment --><br />
明显看得出其中字体变形了。<br />
<br />
后来cntrump给了个新的consolas+雅黑的混合字体，用了段时间，效果挺好，所以推荐下，也在这里备个份，以后自己也好找。<br />
效果图：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=14" target="_blank">完美的混合字体.jpg</a> (Size: 20.25 KB / Downloads: 25)
<!-- end: postbit_attachments_attachment --><br />
<br />
字体：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".7z" />&nbsp;&nbsp;<a href="attachment.php?aid=16" target="_blank">MSYHMONO.7z</a> (Size: 6.84 MB / Downloads: 23)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[作为一名光荣的程序猿，我对字体的挑剔程度一点也不亚于对编辑器的挑剔程度。<br />
<br />
之前一直用consolas字体编码。这个字体英文看着很舒服，但是貌似是没有中文部分的，中文使用的是宋体。虽然宋体使用范围很广，很多人都偏爱。但是我却不咋喜欢，感&#8203;觉字体怪怪的。中文我更倾向于雅黑字体。<br />
<br />
自然也就希望能兼得两者所长，之前用emacs的时候可以设置，中文用雅黑英文用consolas，但是后来习惯不了emacs的各种问题（比如翻页刷新效率，启动慢，e&#8203;cb自动补全慢等等），于是又捡起vim。vim不支持同时使用两种字体，于是只好囧囧的用纯consolas。<br />
<br />
朋友推荐混合字体，我也关注了一下，网上大部分的consolas+雅黑的混合字体都有瑕疵，比如下图所示：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=13" target="_blank">有瑕疵的混合字体.jpg</a> (Size: 4.18 KB / Downloads: 20)
<!-- end: postbit_attachments_attachment --><br />
明显看得出其中字体变形了。<br />
<br />
后来cntrump给了个新的consolas+雅黑的混合字体，用了段时间，效果挺好，所以推荐下，也在这里备个份，以后自己也好找。<br />
效果图：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=14" target="_blank">完美的混合字体.jpg</a> (Size: 20.25 KB / Downloads: 25)
<!-- end: postbit_attachments_attachment --><br />
<br />
字体：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".7z" />&nbsp;&nbsp;<a href="attachment.php?aid=16" target="_blank">MSYHMONO.7z</a> (Size: 6.84 MB / Downloads: 23)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[检讨书]]></title>
			<link>http://boxcounter.com/showthread.php?tid=76</link>
			<pubDate>Sun, 20 Nov 2011 20:18:58 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=76</guid>
			<description><![CDATA[今天打球发脾气了，很大的火气，在这里记一笔，反省，也给自己敲一棒，希望能起到警钟的作用。<br />
    爱憎过于分明是我的一个很严重的性格缺陷，但是没办法，我就这臭脾气，虽然一直提醒自己要克制，要慢慢淡化这种情绪，但是效果甚微。<br />
    我对行为、个性猥琐无赖的人相当排斥，我有自我分析过，最后的结论是小时候看了太多的小说，武侠的历史的，影响太深，欣赏耿直正派的侠义，但并不仇恨个性反派，却对中间那&#8203;类猥琐阴险的角色恨之入骨。这种情绪逐步渗入到我的思维判断方式和性格。最后演变成现在这个样子。<br />
    我知道我的这个性格很不好，人生百态，胸怀应当宽广，能纳百川。<br />
<br />
    还有我的破脾气，平常都还好，但有时候会突然一下就爆掉。mrcool和大纯都跟我说过。<br />
    我想改，努力地改。<br />
<br />
    以前，这个时候，mrcool 就会很欢乐的在我耳边嗡嗡：“莫生气，人生就像一场戏，因为有缘来相聚……”，一脸贱相。<br />
<br />
    另外，感谢……赐予我一个愿意包容我这种臭脾气的老婆。也感谢有朋友，愿意直白的告诉我我的缺点，因为有你们这些垫脚石，我才能更清楚的读懂自己，完善自己，爬得更高，尿&#8203;得更远。谢谢。]]></description>
			<content:encoded><![CDATA[今天打球发脾气了，很大的火气，在这里记一笔，反省，也给自己敲一棒，希望能起到警钟的作用。<br />
    爱憎过于分明是我的一个很严重的性格缺陷，但是没办法，我就这臭脾气，虽然一直提醒自己要克制，要慢慢淡化这种情绪，但是效果甚微。<br />
    我对行为、个性猥琐无赖的人相当排斥，我有自我分析过，最后的结论是小时候看了太多的小说，武侠的历史的，影响太深，欣赏耿直正派的侠义，但并不仇恨个性反派，却对中间那&#8203;类猥琐阴险的角色恨之入骨。这种情绪逐步渗入到我的思维判断方式和性格。最后演变成现在这个样子。<br />
    我知道我的这个性格很不好，人生百态，胸怀应当宽广，能纳百川。<br />
<br />
    还有我的破脾气，平常都还好，但有时候会突然一下就爆掉。mrcool和大纯都跟我说过。<br />
    我想改，努力地改。<br />
<br />
    以前，这个时候，mrcool 就会很欢乐的在我耳边嗡嗡：“莫生气，人生就像一场戏，因为有缘来相聚……”，一脸贱相。<br />
<br />
    另外，感谢……赐予我一个愿意包容我这种臭脾气的老婆。也感谢有朋友，愿意直白的告诉我我的缺点，因为有你们这些垫脚石，我才能更清楚的读懂自己，完善自己，爬得更高，尿&#8203;得更远。谢谢。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[读资治通鉴 2011-11-17]]></title>
			<link>http://boxcounter.com/showthread.php?tid=75</link>
			<pubDate>Thu, 17 Nov 2011 07:30:42 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=75</guid>
			<description><![CDATA[<blockquote><cite>Quote:</cite>皇太子柔仁好儒，见上所用多文法吏，以刑绳下，常侍燕从容言：“陛下持刑太深，宜用儒生。”帝作色曰：“汉家自有制度，本以霸王道杂之；奈何纯任德教，用周政乎！且俗儒不&#8203;过时宜，好是古非今，使人眩于名实，不知所守，何足委任！”乃叹曰：“乱我家者太子也！”</blockquote>
<br />
这段评价真精辟。汉宣帝是个明白人啊，挑头“遵儒”的汉武帝更是个明白人。可法儒并重，但不可纯儒。历史已经证明了这一点。]]></description>
			<content:encoded><![CDATA[<blockquote><cite>Quote:</cite>皇太子柔仁好儒，见上所用多文法吏，以刑绳下，常侍燕从容言：“陛下持刑太深，宜用儒生。”帝作色曰：“汉家自有制度，本以霸王道杂之；奈何纯任德教，用周政乎！且俗儒不&#8203;过时宜，好是古非今，使人眩于名实，不知所守，何足委任！”乃叹曰：“乱我家者太子也！”</blockquote>
<br />
这段评价真精辟。汉宣帝是个明白人啊，挑头“遵儒”的汉武帝更是个明白人。可法儒并重，但不可纯儒。历史已经证明了这一点。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[SEH分析笔记（X64篇）]]></title>
			<link>http://boxcounter.com/showthread.php?tid=74</link>
			<pubDate>Fri, 04 Nov 2011 18:52:24 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=74</guid>
			<description><![CDATA[SEH分析笔记（X64篇）<br />
	v1.0.0<br />
	boxcounter<br />
<br />
	历史：<br />
	v1.0.0, 2011-11-4：最初版本。<br />
<br />
	[不介意转载，但请注明出处 <a href="http://www.boxcounter.com" target="_blank">www.boxcounter.com</a> <br />
	附件里有本文的原始稿，一样的内容，更好的高亮和排版。<br />
	本文的部分代码可能会因为论坛的自动换行变得很乱，需要的朋友手动复制到自己的代码编辑器就可以正常显示了]<br />
<br />
	在之前的《SEH分析笔记（X86篇）》中，我借助 wrk1.2 介绍了 x86 下 windows 系统内核中的 SEH 实现。这次我们来看看 x64 位 windows 系统内核中 SEH 的实现。<br />
	本文需要大家熟悉 x64 位系统的一些特性，比如调用约定、Prolog 和 Epilog。可以通过这几篇文章熟悉一下:<br />
	<a href="http://msdn.microsoft.com/en-us/library/ms235286.aspx" target="_blank">Overview of x64 Calling Conventions</a>, MSDN<br />
	<a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx" target="_blank">The history of calling conventions, part 5: amd64</a> , The Old New Thing<br />
	<a href="http://msdn.microsoft.com/en-us/magazine/cc300794.aspx" target="_blank">Everything You Need To Know To Start Programming 64-Bit Windows Systems</a>, Matt Pietrek<br />
<br />
	首先回顾一下前一篇文章。<br />
	在 x86 windows 中，函数通过以下几个步骤来参与 SEH ：<br />
	1. 在自身的栈空间中分配并初始化一个 EXCEPTION_REGISTRATION(_RECORD) 结构体。<br />
	2. 将该 EXCEPTION_REGISTRATION(_RECORD) 挂入当前线程的异常链表。<br />
<br />
	当某函数触发异常时，系统首先会通过调用 KiDispatchException 来给内核调试器一个机会，如果内核调试器没有处理该异常，则该机会被转给 RtlDispatchException，这个函数就开始分发该异常。分发过程为：<br />
	从当前线程的异常链表头开始遍历，对于每一个 SEH 注册信息（即 EXCEPTION_REGISTRATION(_RECORD)），调用其 Handler。根据 Handler 的返回值做相应的后续处理：<br />
		1. 返回 ExceptionContinueExecution，表示 Handler 已经修复了异常触发点，从异常触发点继续执行。<br />
		2. 返回 ExceptionContinueSearch，表示该 Handler 没有处理该异常，继续遍历异常链表。<br />
		3. Handler 没有修复异常触发点，但是却能处理该异常（某个 __except 过滤代码返回 EXCEPTION_EXECUTE_HANDLER）。这种情况下，处理完该异常后就从异常解决代码（__except 代码块）继续执行，Handler 不会返回。<br />
	以上是简略的 x86 SEH 流程，其中省略了很多细节，比如展开、错误处理、ExceptionNestedException 和 ExceptionCollidedUnwind 等等。<br />
<br />
	之所以在这里重温这个流程，是因为 x64 中 SEH 的流程总体思路也是如此，只是细节上做了一些修改。但这并不表示熟悉 x86 SEH 就能很轻松的掌握 x64 SEH。<br />
<br />
	本文分为四个部分：“异常注册”、“异常分发”、“展开、解决”和“ExceptionNestedException 和 ExceptionCollidedUnwind”。依然以 MSC 的增强版为分析对象。分析环境为：WDK 7600.16385.1，内置的 cl 的版本是15.00.30729.207，link 的版本是9.00.30729.207，测试虚拟机系统为 amd64 WinXP + wrk1.2。<br />
	<br />
	在讲述之前，需要先定义几个名词，以简化后续的讲述。<br />
<br />
	RVA —— 熟悉 PE 格式的朋友都懂的，表示某个绝对地址相对于所在模块的基地址的偏移。<br />
	EXCEPT_POINT —— 异常触发点。<br />
	EXCEPT_FILTER —— __except 小括号内的异常过滤代码。<br />
	EXCEPT_HANDLER —— __except 大括号内的异常解决代码。<br />
	FINALLY_HANDLER —— __finally 大括号内的代码。<br />
<br />
	以下面的伪码为例，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *((ULONG*)NULL) = 0; <br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;12 __finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;13 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;15 {</code></div></div>
	EXCEPT_POINT 指的是行5中的代码。<br />
	EXCEPT_FILTER 指的是行7中的“(STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER”。<br />
	EXCEPT_HANDLER 指的是行8到行10中所有的代码。<br />
	FINALLY_HANDLER 指的是行13到行15中所有的代码。<br />
<br />
<br />
	<span style="font-weight: bold;">一、异常注册</span><br />
<br />
	在 x64 windows 中，异常注册信息发生了巨大的改变。x86 中异常注册信息是在函数执行过程中在栈中分配并初始化的。x64 中变成这样：<br />
	异常注册信息不再是动态创建，而是编译过程中生成，链接时写入 PE+ 头中的 ExceptionDirectory（参考 winnt.h 中 IMAGE_RUNTIME_FUNCTION_ENTRY 的定义）。ExceptionDirectory 里包含几乎所有函数的栈操作、异常处理等信息。<br />
<br />
	来看看新异常注册信息的数据结构：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _RUNTIME_FUNCTION {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG BeginAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG EndAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG UnwindData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef enum _UNWIND_OP_CODES {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_PUSH_NONVOL = 0,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_LARGE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_SMALL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SET_FPREG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_NONVOL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_NONVOL_FAR,&nbsp;&nbsp; // 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SPARE_CODE1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SPARE_CODE2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 7<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_XMM128,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_XMM128_FAR,&nbsp;&nbsp; // 9<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_PUSH_MACHFRAME&nbsp;&nbsp;&nbsp;&nbsp; // 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_OP_CODES, *PUNWIND_OP_CODES;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef union _UNWIND_CODE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR CodeOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR UnwindOp : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR OpInfo : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;USHORT FrameOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_CODE, *PUNWIND_CODE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_NHANDLER 0x0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_EHANDLER 0x1<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_UHANDLER 0x2<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_CHAININFO 0x4<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_INFO {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Version : 3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Flags : 5;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR SizeOfProlog;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR CountOfCodes;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR FrameRegister : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR FrameOffset : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UNWIND_CODE UnwindCode[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// The unwind codes are followed by an optional DWORD aligned field that<br />
&nbsp;&nbsp;&nbsp;&nbsp;// contains the exception handler address or a function table entry if<br />
&nbsp;&nbsp;&nbsp;&nbsp;// chained unwind information is specified. If an exception handler address<br />
&nbsp;&nbsp;&nbsp;&nbsp;// is specified, then it is followed by the language specified exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;// handler data.<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;union {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ExceptionHandler;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ExceptionData[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_INFO, *PUNWIND_INFO;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _SCOPE_TABLE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG BeginAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG EndAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG HandlerAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG JumpTarget;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} ScopeRecord[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} SCOPE_TABLE, *PSCOPE_TABLE;</code></div></div>
	x64 中，MSC 为几乎所有的函数都登记了完备的信息，用来在展开过程中完整的回滚函数所做的栈、寄存器操作。登记的信息包括：<br />
	函数是否使用了 SEH、<br />
	函数使用的是什么组合的 SEH（__try/__except？__try/__finally？）、<br />
	函数申请了多少栈空间、<br />
	函数保存了哪些寄存器、<br />
	函数是否建立了栈帧，<br />
	等等，<br />
	同时也记录了这些操作的顺序（以保证回滚的时候不会乱套）。<br />
<br />
	这些信息就存储在 UNWIND_INFO 之中。<br />
	UNWIND_INFO 相当于 x86 下的 EXCEPTION_REGISTRATION。它的成员分别是：<br />
		Version —— 结构体的版本。<br />
		Flags —— 标志位，可以有这么几种取值：<br />
			UNW_FLAG_NHANDLER (0x0): 表示既没有 EXCEPT_FILTER 也没有 EXCEPT_HANDLER。<br />
			UNW_FLAG_EHANDLER (0x1): 表示该函数有 EXCEPT_FILTER &amp; EXCEPT_HANDLER。<br />
			UNW_FLAG_UHANDLER (0x2): 表示该函数有 FINALLY_HANDLER。<br />
			UNW_FLAG_CHAININFO (0x4): 表示该函数有多个 UNWIND_INFO，它们串接在一起（所谓的 chain）。<br />
		SizeOfProlog —— 表示该函数的 Prolog 指令的大小，单位是 byte。<br />
		CountOfCodes —— 表示当前 UNWIND_INFO 包含多少个 UNWIND_CODE 结构。<br />
		FrameRegister —— 如果函数建立了栈帧，它表示栈帧的索引（相对于 CONTEXT::RAX 的偏移，详情参考 RtlVirtualUnwind 源码）。否则该成员的值为0。<br />
		FrameOffset —— 表示 FrameRegister 距离函数最初栈顶（刚进入函数，还没有执行任何指令时的栈顶）的偏移，单位也是 byte。<br />
		UnwindCode —— 是一个 UNWIND_CODE 类型的数组。元素数量由 CountOfCodes 决定。<br />
	需要说明几点：<br />
		1. 如果 Flags 设置了 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER，那么在最后一个 UNWIND_CODE 之后存放着 ExceptionHandler（相当于 x86 EXCEPTION_REGISTRATION::handler）和 ExceptionData（相当于 x86 EXCEPTION_REGISTRATION::scopetable）。<br />
		2. UnwindCode 数组详细记录了函数修改栈、保存非易失性寄存器的指令。<br />
		3. MSDN 中有 UNWIND_INFO 和 UNWIND_CODE 的详细说明，推荐阅读。<br />
<br />
	那 UNWIND_INFO 是如何与其描述的函数关联起来的呢？答案是：通过一个 RUNTIME_FUNCTION 结构体。<br />
	RUNTIME_FUNCTION::BeginAddress 同 RUNTIME_FUNCTION::EndAddress 一起以 RVA 形式描述了函数的范围。<br />
	RUNTIME_FUNCTION::UnwindData 就是 UNWIND_INFO 了，它也是一个 RVA 值。<br />
<br />
	PE+ 中的 ExceptionDirectory 中存放着所有函数的 RUNTIME_FUNCTION，按 RUNTIME_FUNCTION::BeginAddress 升序排列。一旦触发异常，系统可以通过 EXCEPT_POINT 的 RVA 在 ExceptionDirectory 中二分查找到 RUNTIME_FUNCTION，进而找到 UNWIND_INFO。<br />
	<br />
	前面有提到，MSC 为几乎所有的函数都登记了完毕的信息，那是不是有一些特殊函数没有登记信息呢？<br />
	是的。x64 新增了一个概念，叫做“叶函数”。熟悉数据结构的朋友可能第一时间就联想到“叶节点”。没错，“叶函数”的含义跟“叶节点”很类似，叶函数不会有子函数，也就是说它不会再&#8203;调用任何函数。另外 x64 对这个概念额外加了一些要求：不修改栈指针（比如分配栈空间）、没有使用 SEH。总结下来就是：既不调用函数、又没有修改栈指针，也没有使用 SEH 的函数就叫做“叶函数”。<br />
	叶函数可以没有登记信息，原因很简单，它根本就没信息需要登记~<br />
<br />
	还有一个 SCOPE_TABLE 结构，熟悉 x86 SEH 的朋友应该很眼熟 :-)，它等同于 x86 SEH 中的 REGISTRATIOIN_RECORD::scopetable 的类型。其成员有：<br />
		Count —— 表示 ScopeRecord 数组的大小。<br />
		ScopeRecord —— 等同于 x86 中的 scopetable_entry 成员。其中，<br />
			BeginAddress 和 EndAddress 表示某个 __try 保护域的范围。<br />
			HandlerAddress 和 JumpTarget 表示 EXCEPTION_FILTER、EXCEPT_HANDLER 和 FINALLY_HANDLER。具体对应情况为：<br />
				对于 __try/__except 组合，HandlerAddress 代表 EXCEPT_FILTER，JumpTarget 代表 EXCEPT_HANDLER。<br />
				对于 __try/__finally 组合，HandlerAddress 代表 FINALLY_HANDLER，JumpTarget 等于 0。<br />
			这四个域通常都是 RVA，但当 EXCEPT_FILTER 简单地返回或等于 EXCEPTION_EXECUTE_HANDLER 时，HandlerAddress 可能直接等于 EXCEPTION_EXECUTE_HANDLER，而不再是一个 RVA。<br />
<br />
	我们可以通过 windbg 中的 .fnent 命令来查看某个函数的异常注册信息。比如，<br />
<br />
	1   kd&gt; .fnent passThrough!SehTest<br />
	2   Debugger function entry 00000000`00778210 for:<br />
	3   d:\workspace\code\mycode\r0\passthrough\passthrough.c(51)<br />
	4   (fffffadf`f140f020)   PassThrough!SehTest   |  (fffffadf`f140f0c0)   PassThrough!Caller2<br />
	5   Exact matches:<br />
	6       PassThrough!SehTest (void)<br />
	7   <br />
	8   BeginAddress      = 00000000`00001020<br />
	9   EndAddress        = 00000000`000010b2<br />
	10  UnwindInfoAddress = 00000000`00002668<br />
	11  <br />
	12  Unwind info at fffffadf`f1410668, 10 bytes<br />
	13    version 1, flags 1, prolog 4, codes 1<br />
	14    handler routine: PassThrough!_C_specific_handler (fffffadf`f140f4ce), data 3<br />
	15    00: offs 4, unwind op 2, op info 4	UWOP_ALLOC_SMALL.<br />
<br />
	行8到行10描述的是 RUNTIME_FUNCTION。<br />
	行12到行15描述的是 UNWIND_INFO。<br />
<br />
	对于叶函数，输出是这样的，<br />
<br />
	kd&gt; .fnent passthrough!LeafTest<br />
	No function entry for fffffadf`f240c080<br />
<br />
	到这里，异常注册就讲完了，我们认识了相关的数据结构和定位方法。下面我们进入异常分发流程。<br />
<br />
<br />
	二、异常分发<br />
<br />
	x64 异常分发过程使用的仍然是 KiDispatchException、RtlDispatchException、RtlpExecuteHandlerForException 等函数。<br />
<br />
	其中，KiDispatchException 中有关内核异常部分的代码完全没有变化，这里我偷懒直接拷贝《SEH分析笔记（X86篇）》中的部分描述，<br />
<br />
	原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;KiDispatchException (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PKEXCEPTION_FRAME ExceptionFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PKTRAP_FRAME TrapFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN KPROCESSOR_MODE PreviousMode,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN BOOLEAN FirstChance<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	对于内核异常，它的处理步骤如下：<br />
		如果 FirstChance 为 TRUE，那么,<br />
			1. 首先将该异常传达给内核调试器（KD），如果 KD 处理了该异常，那么函数返回。<br />
			2. KD 没有处理，调用 RtlDispatchException 进行异常分发。如果分发成功，RtlDispatchExcetpion 返回 TRUE，或者根本不返回。<br />
			3. RtlDispatchException 分发失败，那么再给 KD 一次处理机会，如果还是没有处理，那么 BUGCHECK。<br />
		如果 FirstChance 为 FALSE，那么将该异常传达给 KD，如果 KD 没有处理，那么 BUGCHECK。<br />
	它的源码实现位于 &#36;WRK-v1.2\base\ntos\ke\amd64\exceptn.c:430。<br />
<br />
	RtlDispatchException 发生了一些改变。<br />
	从之前描述的异常注册信息的数据结构可以发现，x64 中已经不存在异常注册链这个概念了（虽然 _NT_TIB 结构体中还保留了 ExceptionList 域）。那 x64 中 RtlDispatchException 是如何遍历异常注册信息的呢？前面虽然有提到如何通过 EXCEPT_POINT 找到 UNWIND_INFO 结构，但是假如这个 UNWIND_INFO 没有处理该异常，如何继续遍历呢？<br />
<br />
	在解答这个问题之前，我们先来认识一个新函数和相关的数据结构，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_SIZE 12<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_HISTORY_TABLE_ENTRY {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ImageBase;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_NONE 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_GLOBAL 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_LOCAL 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_HISTORY_TABLE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Search;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 LowAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 HighAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlLookupFunctionEntry (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ControlPc,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PULONG64 ImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	RtlLookupFunctionEntry 的功能是查找指定地址所在函数的 RUNTIME_FUNCTION 和所在模块的基地址。它的参数分为为，<br />
		ControlPc —— 需要查找的指令地址，<br />
		ImageBase —— 返回的模块基地址，<br />
		HistoryTable —— 用于加速查找。<br />
<br />
	工作流程：<br />
	RtlLookupFunctionEntry 在搜索的过程会根据是否传入 HistoryTable 而采取不同的搜索方法：<br />
		如果传入 HistoryTable，则根据 HistoryTable-&gt;Search 表示的搜索方式在表中进行搜索：<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_NONE，那么不在 HistoryTable 中进行搜索。<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_GLOBAL，则首先在全局表 RtlpUnwindHistoryTable 开始搜索，如果搜索到，则结束搜索，函数返回。否则再在 HistoryTable 中搜索。<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_LOCAL，那么在 HistoryTable 中搜索。<br />
		如果上述过程中没有搜索到需要的结果，那么找到模块基地址，从模块的 PE+ 头结构中解析出 RUNTIME_FUNCTION。如果搜索方式为 UNWIND_HISTORY_TABLE_NONE，还会将解决加入到 HistoryTable。<br />
<br />
	之前的描述中 RtlDispatchException 定位 EXCEPT_POINT 所对应的 RUNTIME_FUNCTION 就是通过调用 RtlLookupFunctionEntry 实现的。<br />
<br />
	回到刚才的问题，如何推动遍历呢？为了解决这个问题，x64 又引进了一个新函数。现在我们有请 x64 SEH 核心成员 RtlVirtualUnwind 登场~<br />
<br />
	先来看看它的原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;PEXCEPTION_ROUTINE<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlVirtualUnwind (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG HandlerType,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ControlPc,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PRUNTIME_FUNCTION FunctionEntry,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PVOID *HandlerData,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PULONG64 EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	它的主要功能是：<br />
		根据传入的 ControlPc 和 ContextRecord 等参数虚拟（模拟）展开该函数，并返回该函数的一些信息，比如 HandlerData（SCOPE_TABLE）、EstablisherFrame（rsp 或 栈帧）。	<br />
	流程是：<br />
		1. 通过 FunctionEntry 和 ImageBase 找到 UNWIND_INFO。根据 UNWIND_INFO 中记录的信息，查找 EstablisherFrame（即栈帧或者 rsp）。<br />
		2. 根据 ControlPc 分如下两种情况展开：<br />
			a. ControlPc &gt;= EpilogOffset，即 ControlPc 在 Epilog 之中。那么把剩余的 Epilog 指令模拟执行完毕即可。<br />
			   所谓模拟是指，如果下一条 EpiLog 指令是“sub rsp, 0x32”，那么将 ContextRecord-&gt;rsp 减去0x32。并不是真正执行 sub 指令。<br />
			b. ControlPc &lt; EpilogOffset，那么把 Prolog 反向模拟回滚一遍即可。<br />
			   所谓反向回滚是指，如果 Prolog 的指令是<br />
			   mov   [RSP + 8], RCX<br />
			   push R15<br />
			   push R14<br />
			   push R13 <br />
			   那么反向回滚就是<br />
		          pop ContextRecord-&gt;R13 （实际上是从 ContextRecord-&gt;Rsp 指向的内存中取出值存入 ContextRecord-&gt;R13，然后 ContextRecord-&gt;Rsp 加上8。并不是真正执行 pop）<br />
		          pop ContextRecord-&gt;R14<br />
		          pop ContextRecord-&gt;R15<br />
		          mov ContextRecord-&gt;RCX, [ContextRecord-&gt;RSP+8]<br />
		   然后把 ContextRecord-&gt;Rip 修改为 ControlPc 所在函数的返回地址，即父函数中的某一处 call 的下一条指令。<br />
		   这样，ContextRecord 就被恢复成父函数在调用 ControlPc 所在函数之后的状态了。<br />
		3. 如果 HandlerType 包含 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER，那么将 UNWIND_INFO::ExceptionData 赋给传出参数 HandlerData，并返回 UNWIND_INFO::ExceptionRoutine。<br />
		   对于 MSC 编译器生成的模块，UNWIND_INFO::ExceptionRoutine 一般指向 nt!__C_specific_handler。UNWIND_INFO::ExceptionData 指向 ControlPc 所在函数的 SCOPE_TABLE。<br />
	RtlVirtualUnwind 的实现源码位于 &#36;WRK-v1.2\base\ntos\rtl\amd64\exdsptch.c:1202。<br />
<br />
	RtlVirtualUnwind 返回后，RtlDispatchException 就可以根据 ContextRecord-&gt;Rip 找到父函数对应的 RUNTIME_FUNCTION，进而找到 UNWIND_INFO。就这样推动整个遍历过程。<br />
	<br />
	这是一般情况，对于没有 UNWIND_INFO 的叶函数呢？<br />
	对于叶函数，RtlLookupFunctionEntry 返回 NULL，于是 RtlDispatchException 知道这是个叶函数，就找到该叶函数的父函数，从父函数继续遍历。也就是完全无视叶函数，因为叶函数对整个异常处理过程没有任何影响。<br />
	<br />
	RtlDispatchException 调用 UNWIND_INFO::ExceptionHandler 依然是通过 RtlpExecuteHandlerForException，其函数原型没有变化：<br />
	<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlpExecuteHandlerForException (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID DispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	该函数的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:84。<br />
	RtlpExecuteHandlerForException 的逻辑较 x86 版本没什么大变化，内部注册了一个异常处理函数 RtlpExceptionHandler。RtlpExceptionHandler 相当于 x86 中的 nt!ExecuteHandler2，其内部会返回 ExceptionNestedException 或 ExceptionContinueSearch。它的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:26。<br />
	<br />
	需要一提的是，最后一个参数 DispatchContext 的类型是 DISPATCHER_CONTEXT，相对于 x86 版本，它扩充了很多，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _DISPATCHER_CONTEXT {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ControlPc;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ImageBase;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 EstablisherFrame;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 TargetIp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PCONTEXT ContextRecord;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PEXCEPTION_ROUTINE LanguageHandler;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID HandlerData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PUNWIND_HISTORY_TABLE HistoryTable;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ScopeIndex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Fill0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;</code></div></div>
	成员分别为：<br />
		ControlPc —— 异常触发点。<br />
		ImagePase —— ControlPc 所在模块的基地址。<br />
		FunctionEntry —— ControlPc 所在函数的 RUNTIME_FUNCTION。<br />
		EstablisherFrame —— ControlPc 所在函数的栈帧（如果建立了栈帧）或 RSP。<br />
		TargetIp —— 解决异常的 EXCEPT_HANDLER 地址，该成员只在展开的过程中被使用。RtlpExecuteHandlerForException 没有使用它。<br />
		ContextRecord —— 供展开过程中使用，只有当展开过程中触发新异常（返回 ExceptionCollidedUnwind）时，才会被 RtlDispatchException 真正的使用到（参考 RtlDispatchException 处理 ExceptionCollidedUnwind 的代码）。<br />
		LanguageHandler —— ControlPc 所在函数的 UNWIND_INFO::ExceptionRoutine。<br />
		HandlerData —— ControlPc 所在函数的 UNWIND_INFO::ExceptionData。<br />
		ScopeIndex —— UNWIND_INFO::ExceptionData 中 SCOPE_TABLE::ScopeRecord 的索引，通常设置为0（注：请不要与 x86 中运行时不断改变的 EXCEPTION_REGISTRATION::trylevel 相混淆，ScopeIndex 不会在在函数执行过程中改变）<br />
		Fill0 —— 未用。<br />
<br />
	再看一下它的 .fnent 输出，<br />
<br />
	1  kd&gt; .fnent nt!RtlpExecuteHandlerForException<br />
	2  Debugger function entry 00000000`01458210 for:<br />
	3  (fffff800`008bd950)   nt!RtlpExecuteHandlerForException   |  (fffff800`008bd970)   nt!RtlpUnwindHandler<br />
	4  Exact matches:<br />
	5      nt!RtlpExecuteHandlerForException (void)<br />
	6  <br />
	7  BeginAddress      = 00000000`000bd950<br />
	8  EndAddress        = 00000000`000bd963<br />
	9  UnwindInfoAddress = 00000000`000dfeb8<br />
	10 <br />
	11 Unwind info at fffff800`008dfeb8, 10 bytes<br />
	12   version 1, flags 3, prolog 4, codes 1<br />
	13   handler routine: nt!RtlpExceptionHandler (fffff800`008bd920), data 0<br />
	14   00: offs 4, unwind op 2, op info 4	UWOP_ALLOC_SMALL.<br />
<br />
	行12中显示 flags 等于3，即	UNW_FLAG_EHANDLER (0x1) | UNW_FLAG_UHANDLER (0x2)，说明行13中显示的异常处理函数 nt!RtlpExceptionHandler 既负责解决异常，也负责展开。<br />
<br />
	RtlpExecuteHandlerForException 会调用 DISPATCHER_CONTEXT::LanguageHandler。对于 MSC 编译得到的模块，它是 nt!__C_specific_handler，我们来看看这个函数，<br />
<br />
	原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION <br />
&nbsp;&nbsp;&nbsp;&nbsp;__C_specific_handler (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD pExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID pEstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT pContext,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID pDispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	反汇编码：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>kd&gt; uf nt!__C_specific_handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d0 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+10h],rdx ; 在栈上保存 pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d5 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rsp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d8 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,88h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42df mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-8],rbx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42e3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-10h],rbp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42e7 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [r9]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rbp = pDispatcherContext-&gt;ControlPc<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42ea mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-18h],rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42ee mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-20h],rdi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42f2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-28h],r12<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42f6 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [r9+38h]&nbsp;&nbsp;; r12 = pDispatcherContext-&gt;HandlerData<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42fa mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-30h],r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42fe mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-38h],r14<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4302 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [r9+8]&nbsp;&nbsp;&nbsp;&nbsp;; r14 = pDispatcherContext-&gt;ImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4306 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-40h],r15<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a430a mov&nbsp;&nbsp;&nbsp;&nbsp; r13,r9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r13 = pDispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a430d sub&nbsp;&nbsp;&nbsp;&nbsp; rbp,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_OffsetInFunc = pDispatcherContext-&gt;ControlPc - pDispatcherContext-&gt;ImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4310 test&nbsp;&nbsp;&nbsp;&nbsp;byte ptr [rcx+4],66h&nbsp;&nbsp;&nbsp;&nbsp;; pExceptionRecord-&gt;ExceptionFlags, EXCEPTION_UNWIND (0x66)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4314 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rsi = pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4317 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r15 = pExceptionRecord<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a431a jne&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xf5 (fffff800`008a43c5)<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-------------------------------------------------------------------<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x50:<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4320 movsxd&nbsp;&nbsp;rdi,dword ptr [r9+48h]&nbsp;&nbsp;; l_ScopeIndex (rdi) = pDispatcherContext-&gt;ScopeIndex<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4324 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-58h],rcx ; [rax-58h] = pExceptionRecord，供给 GetExceptionCode(Information) 使用<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4328 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-50h],r8&nbsp;&nbsp;; [rax-50h] = pContext，供给 GetExceptionCode(Information) 使用<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a432c cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12]&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4330 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = l_ScopeIndex<br />
:&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4333 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x69:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4339 add&nbsp;&nbsp;&nbsp;&nbsp; rax,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 这里 *2，下面紧接着 *8，目的是跳过指定数目的 ScopeRecord（大小为16字节）<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a433c lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[r12+rax*8+0Ch] ; rbx = &amp;(pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x71:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 检查 ControlPc 处于哪个 __try 保护域，之步骤一<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4341 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-8] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4344 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
::&lt;&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4347 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x79:<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 检查 ControlPc 处于哪个 __try 保护域，之步骤二<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4349 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-4] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a434c cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
:::&lt;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a434f jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x81:<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 判断是否是 __try/__finally（JumpTarget 为 NULL）。如果是，那么跳转到下一个 ScopeRecord 继续遍历。<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4351 cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rbx+4],0 ; cmp pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget, NULL<br />
::::&lt;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4355 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x87:<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 到这里，已经找到与异常地址最匹配的 __try/__except<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4357 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4359 cmp&nbsp;&nbsp;&nbsp;&nbsp; eax,1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress, EXCEPTION_EXECUTE_HANDLER (0x1)<br />
:::::&lt;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a435c je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xa3 (fffff800`008a4373) ; 如果返回 EXCEPTION_EXECUTE_HANDLER 则跳转<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x8e:<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 是 __try/__except，且过滤域并不是 EXCEPTION_EXECUTE_HANDLER，执行 HandlerAddress <br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; （注：HandlerAddress 指向的函数仍有可能会返回 EXCEPTION_EXECUTE_HANDLER） <br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a435e lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+30h]<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4363 add&nbsp;&nbsp;&nbsp;&nbsp; rax,r14 ; rax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress + pDispatcherContext-&gt;ImageBase<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4366 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rsi ; rdx = pEstablisherFrame<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4369 call&nbsp;&nbsp;&nbsp;&nbsp;rax&nbsp;&nbsp;&nbsp;&nbsp; ; 调用 EXCEPT_FILTER<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436b test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax<br />
::::::&lt; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436d js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xee (fffff800`008a43be) ; 返回 EXCEPTION_CONTINUE_EXECUTION (-1) 则跳转<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x9f:<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436f test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax<br />
:::::::&lt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4371 jle&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xdd (fffff800`008a43ad) ; 返回 EXCEPTION_CONTINUE_SEARCH (0) 则跳转<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xa3:<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 返回的是 EXCEPTION_EXECUTE_HANDLER<br />
:::::&gt;:::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4373 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,dword ptr [rbx+4] ; ecx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4376 mov&nbsp;&nbsp;&nbsp;&nbsp; r8d,1<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a437c mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rsi ; rdx = pEstablisherFrame<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a437f add&nbsp;&nbsp;&nbsp;&nbsp; rcx,r14 ; rcx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4382 call&nbsp;&nbsp;&nbsp;&nbsp;nt!_NLG_Notify (fffff800`008b1460)<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4387 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [r13+40h] ; rax = pDispatcherContext-&gt;HistoryTable<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a438b mov&nbsp;&nbsp;&nbsp;&nbsp; edx,dword ptr [rbx+4]&nbsp;&nbsp; ; edx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a438e movsxd&nbsp;&nbsp;r9,dword ptr [r15]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = pExceptionRecord-&gt;ExceptionCode<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4391 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = pDispatcherContext-&gt;HistoryTable<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4396 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [r13+28h] ; rax = pDispatcherContext-&gt;ContextRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a439a add&nbsp;&nbsp;&nbsp;&nbsp; rdx,r14 ; rdx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a439d mov&nbsp;&nbsp;&nbsp;&nbsp; r8,r15&nbsp;&nbsp;; r8 = pExceptionRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a0 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rsi ; rcx = pEstablisherFrame<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],rax ; _ARG_5 = pDispatcherContext-&gt;ContextRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a8 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx (fffff800`00891e80) ; 这里不会返回<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; RtlUnwindEx(pEstablisherFrame, <br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pExceptionRecord,<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pExceptionRecord-&gt;ExceptionCode<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;ContextRecord,<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;HistoryTable)<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd:<br />
::&gt;&gt;&gt; :&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43ad inc&nbsp;&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp; ; l_ScopeIndex += 1<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43af add&nbsp;&nbsp;&nbsp;&nbsp; rbx,10h ; 调整到下一个 ScopeRecord::HandlerAddress<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b3 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: &lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b7 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x71 (fffff800`008a4341)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xe9:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; pDispatcherContext-&gt;HandlerData 遍历完毕<br />
::&lt;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b9 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
:::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xee:<br />
:::&nbsp;&nbsp; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43be xor&nbsp;&nbsp;&nbsp;&nbsp; eax,eax ; eax = ExceptionContinueExecution<br />
:::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c0 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x16b (fffff800`008a443b)<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------------------------------------------------------------------------------------<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xf5:<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 设置了 EXCEPTION_UNWIND，当前是展开过程<br />
&gt;:::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c5 movsxd&nbsp;&nbsp;rdi,dword ptr [r9+48h] ; l_ScopeIndex (rdi) = pDispatcherContext-&gt;ScopeIndex<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c9 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [r9+20h] ; rsi = pDispatcherContext-&gt;TargetIp<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43cd sub&nbsp;&nbsp;&nbsp;&nbsp; rsi,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rsi = pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43d0 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12]&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43d4 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = l_ScopeIndex<br />
 :::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43d7 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x109:<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43d9 add&nbsp;&nbsp;&nbsp;&nbsp; rax,rax ; <br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43dc lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[r12+rax*8+8] ; rbx = &amp;(pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x111:<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 检查 ControlPc 处于哪个 __try 保护域，之步骤一<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt; fffff800`008a43e1 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-4] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43e4 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43e7 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : <br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nt!__C_specific_handler+0x119:<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : ; 检查 ControlPc 处于哪个 __try 保护域，之步骤二<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43e9 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,dword ptr [rbx] ; ecx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43eb cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rcx ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43ee jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: <br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: nt!__C_specific_handler+0x120:<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: ; 到这里，已经找到与异常地址匹配的最内层（如果有多层） __try/__except<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43f0 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rax ; cmp pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::::&lt;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43f3 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x131 (fffff800`008a4401)<br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : <br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : nt!__C_specific_handler+0x125:<br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43f5 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rcx ; cmp pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43f8 ja&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x131 (fffff800`008a4401)<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: <br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: nt!__C_specific_handler+0x12a:<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: ; 如果标记了 EXCEPTION_TARGET_UNWIND，说明是最后一个需要局部展开的函数。但是该次局部展开只展开到 EXCEPT_HANDLER（不包含 EXCEPT_HANDLER），所以需要判断 TargetIp<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43fa test&nbsp;&nbsp;&nbsp;&nbsp;byte ptr [r15+4],20h ; test pExceptionRecord-&gt;ExceptionFlags, EXCEPTION_TARGET_UNWIND (0x20)<br />
 ::::::::&lt;&nbsp;&nbsp; : fffff800`008a43ff jne&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 :::::::::&nbsp;&nbsp; : <br />
 :::::::::&nbsp;&nbsp; : nt!__C_specific_handler+0x131:<br />
 ::::::&gt;&gt;:&nbsp;&nbsp; : fffff800`008a4401 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx+8] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
 ::::::&nbsp;&nbsp;:&nbsp;&nbsp; : fffff800`008a4404 test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax ; 判断 pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget 是否为 NULL，即是否是 __try/__finally<br />
 ::::::&nbsp;&nbsp;:&lt;&nbsp;&nbsp;: fffff800`008a4406 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x13f (fffff800`008a440f) ; 如果是 __try/__finally 则跳转<br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: <br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: nt!__C_specific_handler+0x138:<br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: fffff800`008a4408 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rax ; cmp pDispatcherContext-&gt;TargetIp, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
 ::::::&nbsp;&nbsp;::&lt; : fffff800`008a440b je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 ::::::&nbsp;&nbsp;::: : <br />
 ::::::&nbsp;&nbsp;::: : nt!__C_specific_handler+0x13d:<br />
 ::::::&nbsp;&nbsp;:::&lt;: fffff800`008a440d jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 ::::::&nbsp;&nbsp;::::: <br />
 ::::::&nbsp;&nbsp;::::: nt!__C_specific_handler+0x13f:<br />
 ::::::&nbsp;&nbsp;::::: ; 注意这里是先修改 pDispatcherContext-&gt;ScopeIndex，然后调用 EXCEPT_HANDLER。这样如果 EXCEPT_HANDLER 触发异常，后续展开就会跳过这个 EXCEPT_HANDLER。<br />
 ::::::&nbsp;&nbsp;:&gt;::: fffff800`008a440f mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+98h]<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4417 lea&nbsp;&nbsp;&nbsp;&nbsp; eax,[rdi+1]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; eax = l_ScopeIndex + 1<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a441a mov&nbsp;&nbsp;&nbsp;&nbsp; cl,1<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a441c mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [r13+48h],eax ; pDispatcherContext-&gt;ScopeIndex = eax<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4420 mov&nbsp;&nbsp;&nbsp;&nbsp; r8d,dword ptr [rbx+4]&nbsp;&nbsp; ; r8d = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[i].HandlerAddress<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4424 add&nbsp;&nbsp;&nbsp;&nbsp; r8,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[i].HandlerAddress + pDispatcherContext-&gt;ImageBase<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4427 call&nbsp;&nbsp;&nbsp;&nbsp;r8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 调用 __finally 处理块，会返回（注：对于 __try/__finally，HandlerAddress 保存的是 __finally 代码块的 RVA）<br />
 ::::::&nbsp;&nbsp;: ::: <br />
 ::::::&nbsp;&nbsp;: ::: nt!__C_specific_handler+0x15a:<br />
 ::::&gt;&gt;&nbsp;&nbsp;: :&gt;: fffff800`008a442a inc&nbsp;&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_ScopeIndex += 1<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : : fffff800`008a442c add&nbsp;&nbsp;&nbsp;&nbsp; rbx,10h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 调整到下一个 ScopeRecord::HandlerAddress<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : : fffff800`008a4430 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : &lt; fffff800`008a4434 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x111 (fffff800`008a43e1)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp; <br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp; nt!__C_specific_handler+0x166:<br />
 &gt;&gt;:&gt;&nbsp;&nbsp;&nbsp;&nbsp;&gt; &gt;&nbsp;&nbsp; fffff800`008a4436 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,1 ; eax = ExceptionContinueSearch (0n1)<br />
&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x16b:<br />
&nbsp;&nbsp; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a443b mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+48h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4440 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+50h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4445 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+58h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a444a mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [rsp+60h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a444f mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,qword ptr [rsp+68h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4454 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+70h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4459 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [rsp+78h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a445e mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+80h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4466 add&nbsp;&nbsp;&nbsp;&nbsp; rsp,88h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a446d ret</code></div></div>
	nt!__C_specific_handler 相当于 x86 中的 nt!_except_handler3。从上面的反汇编代码也可以看出它的逻辑跟 nt!_except_handler3 基本上一致。<br />
	函数代码不长。主要分为两个大分支，一个分支处理异常，一个分支处理展开（我用横线分隔开了）。<br />
<br />
	异常解决的代码负责遍历 SCOPE_TABLE，依次调用 SCOPE_TABLE::ScopeRecord.HandlerAddress 代表的 EXCEPT_FILTER，并针对返回值做出相应的处理：<br />
		1. 返回 EXCEPTION_CONTINUE_EXECUTION，说明异常已经被 EXCEPT_FILTER 修复。返回 ExceptionContinueExecution。<br />
		2. 返回 EXCEPTION_CONTINUE_SEARCH，继续遍历下一个 ScopeRecord。<br />
		3. 返回 EXCEPTION_EXECUTE_HANDLER，说明当前 ScopeRecord.JumpTarget 代表的 EXCEPT_HANDLER 可以处理该异常。那么调用 RtlUnwindEx 进行展开。<br />
<br />
	熟悉 x86 的朋友可能会疑惑：在 x86 中 nt!_except_handler3 先进行全局展开，然后对本函数自身进行不完全的局部展开，最后执行 EXCEPT_HANDLER。而在 nt!__C_specific_handler 中却找不到执行 EXCEPT_HANDLER 的指令，这是怎么回事？<br />
	实际上，x64 对这个流程做了一些调整，EXCEPT_HANDLER 不是由 nt!__C_specific_handler 直接调用，而是作为参数传给 RtlUnwindEx，RtlUnwindEx 处理完展开之后才执行 EXCEPT_HANDLER。后续我们在讲展开的时候会看到具体的方法。<br />
<br />
	__C_specific_handler 的展开分支，是对 SCOPE_TABLE 进行展开，逻辑很简单，不多讲了。<br />
<br />
	更详细的信息，请参考上面反汇编代码中我附的注释。<br />
<br />
	另外还需要说一下 SCOPE_TABLE。<br />
	在 x86 中，遍历 scopetable 时是通过运行时动态改变的 EXCEPTION_REGISTRATION::trylevel 来确定应该首先遍历哪一个 scopetable_entry。而 x64 中没有等同于 trylevel 的数据，有的朋友可能会说“SCOPE_TABLE 中不是有每个 __try 保护域的范围 RVA 吗？通过范围不就可以确定在哪个 __try 中触发了异常吗？”。<br />
	我们可以先试试这种方法，以下面这段伪码为例，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1 VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp; __try // 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp; __except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;9 <br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;__try // 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try // 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;__except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;21&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;22&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;23<br />
&nbsp;&nbsp;&nbsp;&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;__try // 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;25&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;27&nbsp;&nbsp;&nbsp;&nbsp;__finally()<br />
&nbsp;&nbsp;&nbsp;&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;29&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;30}</code></div></div>
	上述伪码中总共有4个 __try，按照 x86 中的方法，SCOPE_TABLE 的内容应该是顺序排列的，像这样：<br />
<br />
	SCOPE_TABLE::Count 等于4，<br />
	SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[1] 表示行10开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[2] 表示行12开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。<br />
<br />
	假设行14处触发了异常，遍历过程应该是这样，<br />
	首先检查 ScopeRecord[0]，发现其范围不包含 EXCEPT_POINT，继续下一个，<br />
	开始检查 ScopeRecord[1]，范围匹配了。<br />
	<br />
	那是不是该把异常交给 ScopeRecord[1] 处理呢？<br />
	不是！从伪码中可以很明显的看出，行14触发的异常应该首先由行12开始的 __try/__except，即 ScopeRecord[1] 处理。<br />
<br />
	可见这种方法是行不通的。<br />
	MSC 通过调整 SCOPE_TABLE::ScopeRecord 的排列顺序来解决这个问题：<br />
<br />
	SCOPE_TABLE::Count 等于4，<br />
	SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[1] 表示行12开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[2] 表示行10开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。<br />
<br />
	即对于嵌套的 __try/__except/__finally，ScopeRecord 的排列顺序是，最内层的 __try 排在前面，其次是次内层的，依次排到最外层。<br />
	这样就能正确的遍历 SCOPE_TABLE 了。<br />
<br />
	再用伪码完整的展示一下 SCOPE_TABLE 的布置，<br />
<br />
	SCOPE_TABLE::Count = 4。<br />
<br />
	SCOPE_TABLE::ScopeRecord[0].BeginAddress = RVA_L4; （行4的 RVA） // 第一个 __try<br />
	SCOPE_TABLE::ScopeRecord[0].EndAddress = RVA_L5;<br />
	SCOPE_TABLE::ScopeRecord[0].HandlerAddress = RVA_L6_EXCEPT_FILTER; （行6 __except 过滤代码首地址的 RVA）<br />
	SCOPE_TABLE::ScopeRecord[0].JumpTarget = RVA_L7; <br />
<br />
	SCOPE_TABLE::ScopeRecord[1].BeginAddress = RVA_L13;                 // 第三个 __try<br />
	SCOPE_TABLE::ScopeRecord[1].EndAddress = RVA_L15;<br />
	SCOPE_TABLE::ScopeRecord[1].HandlerAddress = RVA_L16_EXCEPT_FILTER; <br />
	SCOPE_TABLE::ScopeRecord[1].JumpTarget = RVA_L7; <br />
<br />
	SCOPE_TABLE::ScopeRecord[2].BeginAddress = RVA_L11;                 // 第二个 __try<br />
	SCOPE_TABLE::ScopeRecord[2].EndAddress = RVA_L19;<br />
	SCOPE_TABLE::ScopeRecord[2].HandlerAddress = RVA_L20_EXCEPT_FILTER;<br />
	SCOPE_TABLE::ScopeRecord[2].JumpTarget = RVA_L21; <br />
<br />
	SCOPE_TABLE::ScopeRecord[3].BeginAddress = RVA_L25;                 // 第四个 __try<br />
	SCOPE_TABLE::ScopeRecord[3].EndAddress = RVA_L26;<br />
	SCOPE_TABLE::ScopeRecord[3].HandlerAddress = RVA_L28;<br />
	SCOPE_TABLE::ScopeRecord[3].JumpTarget = 0; <br />
<br />
	我们再模拟一下 nt!__C_specific_handler 是如何遍历 SCOPE_TABLE 的：<br />
	1. 首先通过传入参数中的 pDispatcherContext-&gt;ControlPc 和 pDispatcherContext-&gt;ImageBase 计算出异常触发点的 RVA（简称 E_RVA）。参见 fffff800`008a430d 处的指令。<br />
	2. 通过 pDispatcherContext-&gt;ScopeIndex 确认是否需要遍历。如果需要遍历，则从它指定的 ScopeRecord 开始遍历。pDispatcherContext-&gt;ScopeIndex 一般都为0，只有返回 ExceptionCollidedUnwind 时，RtlDispatchException 才可能将它设置为其他值。<br />
	3. 通过比较 E_RVA 和 ScopeRecord[?].BeginAddress、ScopeRecord[?].EndAddress 来找到正确的处理函数，<br />
		首先 ScopeRecord[0] 范围不匹配，遍历下一个，<br />
		然后 ScopeRecord[1]，发现范围匹配，并且是 __try/__except 组合。于是调用 ScopeRecord[1].HandlerAddress，假设它返回的是 EXCEPTION_CONTINUE_SEARCH，那么继续遍历下一个，<br />
		这次是 ScopeRecord[2]，发现范围匹配，并且是 __try/__except 组合。于是调用 ScopeRecord[2].HandlerAddress，假设它返回的是 EXCEPTION_EXECUTE_HANDLER，那么说明找到了解决方案。<br />
	4. 调用 RtlUnwindEx，把 ScopeRecord[2].JumpTarget 对应的绝对地址作为 TargetIp 参数传给它。RtlUnwindEx 全局展开完毕后执行 TargetIp。<br />
<br />
	到这里，异常分发就大致讲述完毕。接下来是关于展开和解决的内容。<br />
<br />
<br />
	<span style="font-weight: bold;">三、展开、解决</span><br />
<br />
	x64 中展开使用的函数有 RtlVirtualUnwind、RtlUnwindEx 和 RtlpExecuteHandlerForUnwind。其中 RtlVirtualUnwind 已经讲了，我们来看看余下的两个。<br />
<br />
	首先是 RtlUnwindEx，原型如下：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlUnwindEx (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID TargetFrame OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID TargetIp OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID ReturnValue,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PCONTEXT OriginalContext,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	参数分别是：<br />
		TargetFrame —— 目标帧，即最后一个需要展开的帧。<br />
		TargetIp —— 前面有讲过，它就是 ScopeRecord[?].JumpTarget 代表的地址，即 EXCEPT_HANDLER。<br />
		ExceptionRecord —— 异常信息。<br />
		ReturnValue —— 传递给 TargetIp 的返回值，分析过程中没发现它有什么用处。<br />
		OriginalContext —— 虽然被声明为 IN，但是实际上 RtlUnwindEx 并没有使用它内部的数据，<br />
		HistoryTable —— 用于加速查找 RUNTIME_FUNCTION。<br />
<br />
	主要功能是：<br />
		从自身开始展开，到 TargetFrame 停止。然后跳转到 TargetIp 继续执行。<br />
	流程：<br />
		1. 申请一个类型为 CONTEXT 的局部变量 l_Context，调用 RtlCaptureContext 将当前自身的环境复制到 l_Context。<br />
		2. 通过 RtlVirtualUnwind 对 l_Context 进行模拟展开，推动遍历。对每个遍历到的 UNWIND_INFO，检查 UNWIND_INFO::Flags 是否包含 UNW_FLAG_UHANDLER。如果包含，则调用 UNWIND_INFO::ExceptionHandler 进行局部展开。否则继续遍历下一个。<br />
		   循环本步骤，直到展开到 TargetFrame，即到达解决异常的 EXCEPT_HANDLER 所在的函数（简称为 ExceptionHandlerFunc）了。<br />
		3. 这时 l_Context 内已经是从 RtlUnwindEx 完整展开到 EXCEPT_HANDLER 的环境了。即此时 l_Context 已经是 ExceptionHandlerFunc 的执行环境了。<br />
		   调用 RtlRestoreContext，用 l_Context 替换当前线程的执行环境，于是就跳转到 EXCEPT_HANDLER 继续执行。<br />
	这样就完美的从触发异常的环境跳到了新的环境中。<br />
<br />
	这个过程有点类似这种手法：<br />
		1. 将某台机器的系统 ghost 到一个 bak.gho 文件。<br />
		2. 把 bak.gho 恢复到一台临时机器，然后对这台临时机器做一些调整。调整完毕后制作一个临时机器的 bak_mod.gho。<br />
		3. 将 bak_mod.gho 恢复到原来那台机器。<br />
<br />
	这个流程很重要，我手绘了一副图帮助理解，<br />
	<br />
	伪码：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus(STATUS_INVALID_PARAMETER);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
<br />
	图：<br />
	1. 异常解决流程，从 EXCEPT_POINT 到 RtlUnwindEx，途中已经找到能够解决该异常的 EXCEPT_HANDLER 了（以参数 TargetIp 表示），当前线程状态为 ThreadContext<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+</code></div></div>
	<br />
	2. RtlUnwindEx 将当前自身状态复制到 ThreadContext_Copy 中<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext_Copy &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+</code></div></div>
	<br />
	3. 用 ThreadContext_Copy 进行展开，一直展开到异常触发点停止。<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+<br />
| .....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^展 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|开 |-&gt; ThreadContext_Copy &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+</code></div></div>
	<br />
	4. 将 ThreadContext_Copy.Rip 设置为 TargetIp，以 ThreadContext_Copy 为参数调用 RtlpRestoreContext。跳转到 TargetIp 继续执行。<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| EXCEPT_HANDLER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|-&gt; ThreadContext (ThreadContext.Rip = TargetIp)<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+</code></div></div>
	这样就完成了展开和执行 EXCEPT_HANDLER 的工作。<br />
<br />
	RtlpExecuteHandlerForUnwind 没有什么改变，原型依旧：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlpExecuteHandlerForUnwind (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID DispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	它会注册一个异常处理函数 RtlpUnwindHandle，当触发新异常时 RtlpUnwindHandler 会返回 ExceptionCollidedUnwind。关于 ExceptionCollidedUnwind，我们后面还会详细讲述。<br />
	RtlpExecuteHandlerForUnwind 的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:199。<br />
	RtlpUnwindHandle 的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:136。<br />
<br />
	到这里，我们讲完了展开的逻辑。接下来我们要讲述两个比较特殊的返回值： ExceptionNestedException 和 ExceptionCollidedUnwind。<br />
<br />
<br />
	四、ExceptionNestedException 和 ExceptionCollidedUnwind<br />
<br />
	之所以专门讲述这两个返回值，是因为在分析过程中，我感觉常规情况的 SEH 流程理解起来并不困难，难理解的是这两种不一般的情况。它们不一般之处在于：在处理异常的过程中又触发了新的异常。<br />
	先来讲一下这两个返回值的含义：<br />
	ExceptionNestedException —— 在异常分发过程中触发新的异常，比如执行 EXCEPT_FILTER 时触发异常。<br />
	ExceptionCollidedUnwind —— 在展开过程中触发新的异常，比如执行 FINALLY_HANDLER 时触发异常。<br />
<br />
	首先来讲讲 ExceptionNestedException，以如下伪码为例：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(ExRaiseStatus(), EXCEPTION_CONTINUE_SEARCH) // EXCEPT_FILTER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ // EXCEPT_HANDLER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;10 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 <br />
&nbsp;&nbsp;&nbsp;&nbsp;12 VOID Caller()<br />
&nbsp;&nbsp;&nbsp;&nbsp;13 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp; __try<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SehTest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp; __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp; { // EXCEPT_HANDLER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;21 }</code></div></div>
	上述代码会两次触发异常，第一次是行5的 ExRaiseStatus，第二次是行7的 ExRaiseStatus。为了方便区分，我将它们分别标记为 EXCEPT_POINT#1、EXCEPT_POINT#2。<br />
	我们来看一下这两个异常的处理流程：<br />
<br />
	1. ExRaiseStatus#1 会创建保存 EXCEPT_POINT#1 触发时的状态 Context#1，并构建一个 EXCEPTION_RECORD，然后将他们作为参数来调用 RtlDispatchException#1。（注：这种方式的的触发点是 ExRaiseStatus 内部，而非 SehTest 的第5行。即Context#1 记录的异常触发点是 ExRaiseStatus#1 内部）<br />
<br />
	2. RtlDispatchException#1 根据 Context#1 首先找到 EXCEPT_POINT#1 所在函数 ExRaiseStatus#1 的 UNWIND_INFO，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
<br />
	3. RtlDispatchException#1 遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionHandler，即 __C_specific_handler&#36;2。__C_specific_handler&#36;2 遍历 SehTest 的 SCOPE_TABLE，发现唯一的一个 ScopeRecord。于是执行 ScopeRecord[0].HandlerAddress，即行7的 SehTest::EXCEPT_FILTER_1#1。此时的调用栈如下（竖线后的内容为函数的 UNWIND_INFO::Flags 和 UNWIND_INFO::ExceptionHandler，其中 Flags 缩写为 E、U、N）：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(6)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(7)&nbsp;&nbsp;EXCEPT_FILTER_1#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N</code></div></div>
<br />
	4. EXCEPT_FILTER#1 触发 EXCEPT_POINT#2。同步骤1类似，ExRaiseStatus 会调用 RtlDispatchException#2，这个过程中同样会创建保存 EXCEPT_POINT#2 的状态，我们称之为 Context#2。<br />
<br />
	5. RtlDispatchException#2 根据 Context#2 找到了 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
<br />
	6. RtlDispatchException#2 遍历到 EXCEPT_FILTER_1#1，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。（注：EXCEPT_FILTER 虽然代码形式上从属于 SehTest 函数，但实际上它是一个单独的函数，有自己的 UNWIND_INFO，跟 SEH 的 UNWIND_INFO 并不是同一个）<br />
<br />
	7. RtlDispatchException#2 遍历到 __C_specific_handler&#36;2、RltpExecuteHandlerForException#1、RtlDispatchException#1、E&#8203;xRaiseStatus#1，这些函数要么被标记为 UNW_FLAG_NHANDLER，要么 UNWIND_INFO::ExceptionHandler 返回 ExcetpionNestedException，结果都是继续遍历，所以不再一一讲述。继续遍历下一个。<br />
<br />
	8. RtlDispatchException#2 遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionRoutine，即 __C_specific_handler&#36;2，发现范围匹配，于是调用 EXCEPT_FILTER_1#1，于是又触发异常，这次是 #3 异常。此时的调用栈如下：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(6)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(7)&nbsp;&nbsp;EXCEPT_FILTER_1#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(8)&nbsp;&nbsp;ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(9)&nbsp;&nbsp;RtlDispatchException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(10) RtlpExecuteHandlerForException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;10<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(11) __C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(12) EXCEPT_FILTER_1#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(13) ExRaiseStatus#3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N</code></div></div>
	9. #3 异常的处理流程同 #2 的处理流程类似，也会再遍历到 __C_specific_handler&#36;2，也会再调用 EXCEPT_FILTER_1，于是会触发 #4 异常、#5 异常等等。最终内核栈溢出，BSOD。<br />
<br />
	以上就是 ExceptionNestedException 的产生以及处理的流程。过程中还有一些细节操作，为了描述简洁，我没有在上述过程中一一讲述。<br />
<br />
<br />
	再来看看 ExceptionCollidedUnwind。它比 ExceptionNestedException 更复杂一些，我们以如下伪码为例，<br />
		<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ // FINALLY_HANDLER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;12 <br />
&nbsp;&nbsp;&nbsp;&nbsp;13 VOID Caller()<br />
&nbsp;&nbsp;&nbsp;&nbsp;14 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp; __try<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SehTest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp; __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp; { // EXCEPT_HANDLER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;21&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;22 }</code></div></div>
	伪码中也有两处触发异常的地方，第一次在行5，第二次在行9。也分别标记为 EXCEPT_POINT#1 和 EXCEPT_POINT#2。处理流程：<br />
	<br />
	1. ExRaiseStatus#1 创建保存 EXCEPT_POINT#1 的状态 Context#1，并构建一个 EXCEPTION_RECORD，然后将他们作为参数来调用 RtlDispatchException#1。<br />
<br />
	2. RtlDispatchException#1 根据 Context#1 开始遍历：<br />
		首先遍历到 EXCEPT_POINT#1 所在函数 ExRaiseStatus，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是遍历下一个。<br />
		然后遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_UHANDLER，于是继续遍历下一个。<br />
		然后遍历到 Caller，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionRoutine 即 __C_specific_handler。__C_specific_handler 发现可以处理该异常，于是以 EXCEPT_HANDLER_2 为 TargetIp 参数调用 RtlUnwindEx。<br />
<br />
	3. RtlUnwindEx 从自身开始展开，展开到 SehTest，执行 FINALLY_HANDLER_1 时触发新异常。此时调用栈为：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | U&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)&nbsp;&nbsp;__C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)&nbsp;&nbsp;RtlUnwindEx#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)&nbsp;&nbsp;RtlpExecuteHandlerForUnwind#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpUnwindHandler&#36;8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (9)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (10) FINALLY_HANDLER_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (11) ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N</code></div></div>
	   需要说明的是，调用栈(7) RtlUnwindEx 创建并初始化了一个 DISPATCHER_CONTEXT 变量（后续称之为 pDispatcherContextForUnwind），并作为参数传递给调用栈(8) RltpExecuteHandlerForUnwind，后者在调用(9) __C_specific_handler&#36;2 之前将 pDispatcherContextForUnwind 保存在自己的栈中。此时 pDispatcherContextForUnwind 的内容表示的是调用栈(2) SehTest 的情况。后续步骤会用到这个 pDispatcherContextForUnwind。<br />
	<br />
	4. (11) ExRaiseStatus#2 将 EXCEPT_POINT#2 触发时的状态保存到 Context#2，然后调用 RtlDispatchException#2 进行 EXCEPT_POINT#2 的分发。<br />
	<br />
	5. RtlDispatchException#2 根据 Context#2 开始遍历，<br />
		首先遍历到 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是遍历下一个。<br />
		然后遍历到 FINALLY_HANDLER_1（同前面提到的 EXCEPT_FILTER 一样，FINALLY_HANDLER 实际上也是一个单独的函数，有自己的 RUNTIME_FUNCTION 和 UNWIND_INFO），发现其 UNWIND_INFO::Flags 为	UNW_FLAG_NHANDLER，于是遍历下一个。<br />
	   	然后遍历到(9) __C_specific_handler&#36;2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
		然后遍历到(8) RtlpExecuteHandlerForUnwind#1，发现其 UNWIND_INFO::Flags 包含 UNW_FLAG_EHANDLER。于是调用其 UNWIND_INFO::ExceptionRoutine 即 RtlpUnwindHandler&#36;8。RtlpUnwindHandler&#36;8 会取出步骤3中所提到的 pDispatcherContextForUnwind，将其内容拷贝到自己的传出参数（参考 RtlpUnwindHandler 的函数原型）pDispatcherContext 中，然后返回 ExceptionCollidedUnwind。<br />
<br />
	6. RtlDispatchException#2 收到 ExceptionCollidedUnwind 后，从传回来的 pDispatchContext 中取出诸如 ControlPc、EstablisherFrame 等值（如步骤3所说，此时这些值反应的是(2) SehTest 的状态），用这些值来继续遍历。<br />
		首先遍历到(2) SehTest，调用 RtlpExecuteHandlerForException#2，进而调用 __C_specific_handler&#36;2，但是发现 pDispatcherContext-&gt;ScopeIndex（步骤(9)中在调用(10) FINALLY_HANDLER_1 之前+1了，参考 __C_specific_handler 反汇编码）等于 pDispatcherContext-&gt;HandlerData-&gt;Count。于是继续遍历。<br />
		然后遍历到(1) Caller，调用 RtlpExecuteHandlerForException#2，进而调用 __C_specific_handler&#36;1，发现它可以处理 #2 异常，于是以 EXCEPT_HANDLER#2 为 TargetIp 参数调用 RtlUnwindEx。此时调用栈如下：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | U&nbsp;&nbsp;&amp; __C_specific_handler&#36;2，但没有 EXCEPT_HANDLER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler&#36;6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)&nbsp;&nbsp;__C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)&nbsp;&nbsp;RtlUnwindEx#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)&nbsp;&nbsp;RtlpExecuteHandlerForUnwind#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpUnwindHandler&#36;8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (9)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (10) FINALLY_HANDLER#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (11) ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (12) RtlDispatchException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (13) RtlpExecuteHandlerForException#2&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (14) __C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (15) RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N</code></div></div>
	7. (17) RtlUnwindEx 展开完毕后，通过 RtlRestoreContext 跳转到 EXCEPT_HANDLER#2 继续执行。<br />
<br />
	在上述过程中，我们可以发现，遍历过程中 RtlDispatchException 等系统函数被频繁遍历到。于是就有了前面提到的全局展开历史表 RtlpUnwindHistoryTable，这个表中存放着 RtlDispatchException、RtlUnwindEx 等函数的 RUNTIME_FUNCTION 和 ImageBase 信息，这样就不用每次都去解析 PE+ 中的 ExceptionDirectory，实现了加速。<br />
<br />
<br />
	到这里，我们就讲完了 x64 SEH 的实现。可以发现，x64 和 x86 的 SEH 思想或者说框架是一样的：<br />
	1. RtlDispatchException 和 RtlUnwindEx 都对异常注册信息进行遍历。前者是为了分发异常而遍历，后者是为了展开而遍历。<br />
	2. MSC 提供的异常处理函数按照“异常解决”和“展开”两个分支，对 SCOPE_TABLE/scopetable 进行遍历。前者是为了找到 EXCEPT_FILTER &amp; EXCEPT_HANDLER，后者是为了找到 FINALLY_HANDLER。<br />
	3. RtlDispatchException 和 RtlUnwindEx 借助 MSC 提供的异常处理函数这个桥梁，配合处理异常。<br />
	主要的改变有两点：<br />
	1. RtlDispatchException 和 RtlUnwindEx 通过调用 RtlVirtualUnwind 推动遍历。<br />
	2. 所有的非叶函数都参与到 SEH，尽管大部分的函数都没有使用到 SEH。<br />
<br />
	以上我们主要讲述的是 x64 SEH 的内部实现。对于使用者，也有一个好消息，我们来看看，<br />
	<br />
	C 代码：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus(STATUS_INVALID_PARAMETER);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
	反汇编码：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; uf passthrough!SehTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest:<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100020 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,38h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100024 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C000000Dh<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100029 call&nbsp;&nbsp;&nbsp;&nbsp;qword ptr [PassThrough!_imp_ExRaiseStatus (fffffadf`f1101050)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110002f lea&nbsp;&nbsp;&nbsp;&nbsp; r8,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100500)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100036 mov&nbsp;&nbsp;&nbsp;&nbsp; edx,39h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110003b lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100540)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100042 call&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!DbgPrint (fffffadf`f11004a6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100047 jmp&nbsp;&nbsp;&nbsp;&nbsp; PassThrough!SehTest+0x42 (fffffadf`f1100062)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x42:<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100062 lea&nbsp;&nbsp;&nbsp;&nbsp; r8,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100500)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100069 mov&nbsp;&nbsp;&nbsp;&nbsp; edx,42h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110006e lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100570)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100075 call&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!DbgPrint (fffffadf`f11004a6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110007a add&nbsp;&nbsp;&nbsp;&nbsp; rsp,38h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110007e ret</code></div></div>
	我们发现 SehTest 内部完全没有任何 SEH 的踪迹，不像 x86 那样会有创建、销毁 EXCEPTION_REGISTRATION_RECORD 和调整 EXCEPTION_REGISTRATION_RECORD::trylevel 等操作。<br />
	这样的好处就是使用者无需再担心性能损耗，可以放心大胆的使用 SEH 机制了。<br />
<br />
<br />
	附录一<br />
<br />
	为了方便自己分析，我写了一个简单的 windbg 扩展，提供了几个 x64 seh 常用功能：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;!boxr.unwindinfo&nbsp;&nbsp;&nbsp;&nbsp;module-name&nbsp;&nbsp;&nbsp;&nbsp;unwindinfo_addr<br />
&nbsp;&nbsp;&nbsp;&nbsp;功能：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用于查询指定 UNWIND_INFO 结构的详细信息。<br />
&nbsp;&nbsp;&nbsp;&nbsp;参数说明：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module-name —— 待查询的 UNWIND_INFO 结构对应函数的模块名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unwindinfo_addr —— UNWIND_INFO 结构的绝对地址</code></div></div>
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;!boxr.rtfn&nbsp;&nbsp;&nbsp;&nbsp;option&nbsp;&nbsp;&nbsp;&nbsp;module&nbsp;&nbsp;&nbsp;&nbsp;runtimefunction_addr<br />
&nbsp;&nbsp;&nbsp;&nbsp;功能：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用于查询指定 RUNTIME_FUNCTION 结构的详细信息。（rtfn 表示 RunTime_FunctioN）<br />
&nbsp;&nbsp;&nbsp;&nbsp;参数说明：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option —— 参数选项，目前支持两种：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/a 表示 module 参数为模块基地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/n 表示 module 参数为模块名称<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module —— RUNTIME_FUNCTION 结构对应函数所在的模块，具体形式根据 option 而定。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;runtimefunction_addr —— 需要查询的 RUNTIME_FUNCTION 结构体的绝对地址。支持 @rax 操作方式，但不支持复杂的组合，比如 @rax+8。</code></div></div>
	使用的方法是：用 .extpath+ 命令将 boxr.dll 所在的目录添加到 windbg 的搜索路径中，然后就可以使用了。需要卸载时就 .unload。<br />
<br />
	简单说明一下这两个命令。<br />
<br />
	比如我们要查看下面这个函数的 UNWIND_INFO 信息：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollidedUnwind();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
	<br />
	操作步骤：<br />
	1. 使用 .fnent 命令获得 SehTest 的基本信息，<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; .fnent passthrough!SehTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Debugger function entry 00000000`00758210 for:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadf`f135d080)&nbsp;&nbsp; PassThrough!SehTest&nbsp;&nbsp; |&nbsp;&nbsp;(fffffadf`f135d180)&nbsp;&nbsp; PassThrough!LeafTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exact matches:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest (void)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 00000000`00001080<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 00000000`00001175<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnwindInfoAddress = 00000000`000026b8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unwind info at fffffadf`f135e6b8, 10 bytes<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version 1, flags 3, prolog 4, codes 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler routine: PassThrough!_C_specific_handler (fffffadf`f135d5de), data 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00: offs 4, unwind op 2, op info 4&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_SMALL.</code></div></div>
	2. 使用 !boxr.unwindinfo 查询详细信息，<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; !boxr.unwindinfo passthrough fffffadf`f135e6b8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_UNWIND_INFO for fffffadff135e6b8 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EU<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionRoutine:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!_C_specific_handler (fffffadf`f135d5de)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeTable:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Count: 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff135e6c8)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x4 (fffffadf`f135d084)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x1e (fffffadf`f135d09e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest&#36;filt&#36;0 (fffffadf`f135d8a0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x1e (fffffadf`f135d09e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[省略中间3个 ScopeRecord 成员]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[5]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff135e718)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x8b (fffffadf`f135d10b)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0xd7 (fffffadf`f135d157)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest&#36;filt&#36;5 (fffffadf`f135d960)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0xd7 (fffffadf`f135d157)</code></div></div>
	!boxr.rtfn 的用法也类似，比如：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; !box.rtfn /n passThrough @rax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_RUNTIME_FUNCTION for fffffadff1113000 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind (fffffadf`f1110020)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x38 (fffffadf`f1110058)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnwindData:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffffadff1111688<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_UNWIND_INFO for fffffadff1111688 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;U<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionRoutine:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!_C_specific_handler (fffffadf`f11104ee)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeTable:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Count: 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff1111698)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x4 (fffffadf`f1110024)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x10 (fffffadf`f1110030)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind&#36;fin&#36;0 (fffffadf`f1110750)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0</code></div></div>
	需要说明的是，我写这个扩展的目的仅仅是为了分析 x64 SEH 过程中能轻松的查看相关数据结构的详细信息，所以并没有在这个扩展上花很多时间。其代码是从 MS 例子代码的基础上增加了我需要的功能。应该有一些 BUG，但是对我来说不重要，已经满足我的需要了。源码也放在附件里，方便分析的朋友根据自己的需要进行修改。<br />
	另外有一个疑问：我编译的 x64 wrk1.2 内核无法对 .c代码进行源码调试，对 .asm 代码倒是可以，这是为什么？我看了一下编译选项，没看出什么猫腻。有经验的朋友分享一下吧，感谢 :-)<br />
<br />
<br />
	<span style="font-weight: bold;">附录二 RtlUnwindEx 的反汇编代码和注释</span><br />
<br />
	由于无法源码调试，只好把它反汇编出来加上注释……<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlUnwindEx (<br />
/* rcx&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID pEstablisherFrame OPTIONAL,<br />
/* rdx&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID pJumpTargetIp OPTIONAL,<br />
/* r8&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; IN PEXCEPTION_RECORD pExceptionRecord OPTIONAL,<br />
/* r9&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID ReturnValue,<br />
/* rsp+28 */&nbsp;&nbsp;&nbsp;&nbsp; IN PCONTEXT pOriginalContext,<br />
/* rsp+30 */&nbsp;&nbsp;&nbsp;&nbsp; IN PUNWIND_HISTORY_TABLE pHistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kd&gt; uf nt!RtlUnwindEx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e70 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],r9<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e75 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+18h],r8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e7a mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+10h],rdx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e7f mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rsp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e82 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,678h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e89 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-8],rbx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e8d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-10h],rbp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e91 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-18h],rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e95 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+6A0h] ; rsi = pOriginalContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e9d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-20h],rdi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea1 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-28h],r12<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea5 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-40h],r15<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea9 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,rcx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eac mov&nbsp;&nbsp;&nbsp;&nbsp; r15,rdx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eaf lea&nbsp;&nbsp;&nbsp;&nbsp; rdx,[rsp+40h] ; rsp+40 为 l_HighLimit<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eb4 lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+50h] ; rsp+50 为 l_LowLimit<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eb9 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,r8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ebc mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ebf lea&nbsp;&nbsp;&nbsp;&nbsp; r12,[rax-518h] ; r12 = &amp;l_Context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ec6 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpGetStackLimits (fffff800`00890da0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ecb mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ece call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlCaptureContext (fffff800`008bd150)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ed3 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891edb test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ede je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x74 (fffff800`00891ee4)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x70:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee0 mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [rax+4],1 ; pHistoryTable-&gt;Search = UNWIND_HISTORY_TABLE_GLOBAL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x74:<br />
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee4 xor&nbsp;&nbsp;&nbsp;&nbsp; ecx,ecx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ee6 test&nbsp;&nbsp;&nbsp;&nbsp;rbx,rbx ; 判断 pExceptionRecord 是否为 NULL<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee9 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xbc (fffff800`00891f2c)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x7b:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; pExceptionRecord 等于 NULL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891eeb mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsi+0F8h]&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ef2 lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[rsp+0C0h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rbx = &amp;l_ExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891efa mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0C0h],0C0000027h ; l_ExceptionRecord.ExceptionCode = STATUS_UNWIND (0xC0000027)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f05 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0D0h],rax&nbsp;&nbsp;; l_ExceptionRecord.ExceptionAddress = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f0d mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h]&nbsp;&nbsp;; rax = pHistoryTable<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f15 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+690h],rbx&nbsp;&nbsp;; [r8-home] = &amp;l_ExceptionRecord ????<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f1d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0C8h],rcx&nbsp;&nbsp;; l_ExceptionRecord.ExceptionRecord = NULL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f25 mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0D8h],ecx&nbsp;&nbsp;; l_ExceptionRecord.NumberParameters = 0<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0xbc:<br />
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f2c mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h]&nbsp;&nbsp;; rbx = &amp;[rcx-home]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f34 mov&nbsp;&nbsp;&nbsp;&nbsp; esi,2 ; l_ExceptionFlags(esi) = EXCEPTION_UNWINDING (2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f39 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,6 ; ecx = EXCEPTION_EXIT_UNWIND (6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f3e test&nbsp;&nbsp;&nbsp;&nbsp;rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f41 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+648h],r13 ; 保存 r13 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f49 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+640h],r14 ; 保存 r14<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f51 cmove&nbsp;&nbsp; esi,ecx ; if (NULL == pEstablisherFrame) { l_ExceptionFlags = EXCEPTION_EXIT_UNWIND (6) }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f54 xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f58 xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f5c xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xf0:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt; fffff800`00891f60 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rdi+0F8h] ; r13 = pOriginalContext-&gt;Rip<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f67 lea&nbsp;&nbsp;&nbsp;&nbsp; rdx,[rsp+60h] ; rdx = &amp;l_pImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f6c mov&nbsp;&nbsp;&nbsp;&nbsp; r8,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pHistoryTable<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f6f mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f72 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+68h],r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f77 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlLookupFunctionEntry (fffff800`00890e60)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_pFunctionEntry = RtlLookupFunctionEntry(pOriginalContext-&gt;Rip, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;l_pImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pHistoryTable)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f7c test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax ; 判断 l_pFunctionEntry (eax) 是否为 NULL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f7f mov&nbsp;&nbsp;&nbsp;&nbsp; r14,rax ; r14 = l_pFunctionEntry<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f82 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3ab (fffff800`0089221b)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x118:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f88 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rdi ; rdx = pOriginalContext<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f8b mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r12 ; rcx = &amp;l_Context<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f8e call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlpCopyContext(&amp;l_Context, pOriginalContext)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f93 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+60h] ; rdx = l_pImageBase<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f98 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+38h],0&nbsp;&nbsp; ; _ARG_8 = 0<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fa1 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+680h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;[rcx-home]，这里被用作局部变量 l_pEstablisherFrame 空间<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fa9 mov&nbsp;&nbsp;&nbsp;&nbsp; r9,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = l_pFunctionEntry<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fac mov&nbsp;&nbsp;&nbsp;&nbsp; r8,r13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891faf mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+30h],rax ; _ARG7 = &amp;l_pEstablisherFrame<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fb4 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+58h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = &amp;l_pHandlerData<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fb9 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ecx = UNW_FLAG_UHANDLER (2)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fbe mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = &amp;l_pHandlerData<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fc3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],r12 ; _ARG_5 = &amp;l_Context<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fc8 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlVirtualUnwind (fffff800`00891380)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_pExceptionRoutine = RtlVirtualUnwind(UNW_FLAG_UHANDLER,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_pImageBase,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pOriginalContext-&gt;Rip,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_pFunctionEntry,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_Context,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pHandlerData,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pEstablisherFrame,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL);<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fcd mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fd5 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rcx = l_pExceptionRoutine<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fd8 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+48h],rax<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fdd test&nbsp;&nbsp;&nbsp;&nbsp;bl,7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 检查 l_pEstablisherFrame 是否对齐<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891fe0 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x176:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891fe6 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+50h]&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_LowLimit<br />
..&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891feb jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x184 (fffff800`00891ff4)<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x17d:<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fed cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+40h]&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_HighLimit<br />
...&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ff2 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x1d3 (fffff800`00892043)<br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x184:<br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ; 检查 l_pEstablisherFrame 是否合法<br />
..&gt;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ff4 mov&nbsp;&nbsp;&nbsp;&nbsp; cl,byte ptr gs:[20DEh]&nbsp;&nbsp; ; cl = _KPCR-&gt;DpcRoutineActive<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ffc test&nbsp;&nbsp;&nbsp;&nbsp;cl,cl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 判断当前是否在执行 DPC<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ffe jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1) ; 如果是在执行 DPC 则失败？??<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x194:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892004 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892009 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl-&gt;Previous.StackBase<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089200d test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 判断 l_KernelStackCtrl-&gt;Previous.StackBase 是否为 NULL<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892010 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1a6:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892016 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rcx-20h]&nbsp;&nbsp;; rdx = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089201a mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892022 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892025 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1bb:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089202b cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackBase<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089202e jae&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1c4:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892034 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892039 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089203e mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl-&gt;Previous.StackBase<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1d3:<br />
.. &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892043 test&nbsp;&nbsp;&nbsp;&nbsp;rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL<br />
.. &lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892046 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x1e1 (fffff800`00892051)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1d8:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892048 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089204b jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1e1:<br />
.. &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892051 test&nbsp;&nbsp;&nbsp;&nbsp;rcx,rcx ; 判断 l_pExceptionRoutine 是否为 NULL<br />
..&nbsp;&nbsp;&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892054 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x39b (fffff800`0089220b)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x1ea:<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089205a mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+58h] ; r13 = l_pHandlerData<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089205f mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+90h],r15 ; [rsp+90] = pJumpTargetIp<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892067 xor&nbsp;&nbsp;&nbsp;&nbsp; r15d,r15d<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089206a xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089206d xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x200:<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&gt; . fffff800`00892070 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . . fffff800`00892073 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x208 (fffff800`00892078)<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x205:<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . fffff800`00892075 or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,20h ; l_ExceptionFlags |= EXCEPTION_TARGET_UNWIND (0x20)<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x208:<br />
..&nbsp;&nbsp;.&gt;&nbsp;&nbsp; . . fffff800`00892078 mov&nbsp;&nbsp;&nbsp;&nbsp; r10,qword ptr [rsp+690h] ; r10 = &amp;l_ExceptionRecord<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892080 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+698h] ; rax = ReturnValue<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892088 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0A0h],rcx ; l_DispatcherContext.LanguageHandler = l_pExceptionRoutine<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892090 mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [r10+4],esi&nbsp;&nbsp;&nbsp;&nbsp;; l_ExceptionRecord.ExceptionFlags = l_ExceptionFlags<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892094 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+78h],rax&nbsp;&nbsp;; pOriginalContext-&gt;Rax = ReturnValue<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892098 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+68h]&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`0089209d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+70h],rax&nbsp;&nbsp;; l_DispatcherContext.ControlPc = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920a2 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+60h]&nbsp;&nbsp;; rax = l_pImageBase<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920a7 lea&nbsp;&nbsp;&nbsp;&nbsp; r9,[rsp+70h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r9 = &amp;l_DispatcherContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ac mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+78h],rax&nbsp;&nbsp;; l_DispatcherContext.ImageBase = l_pImageBase<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920b1 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920b9 mov&nbsp;&nbsp;&nbsp;&nbsp; r8,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r8 = pOriginalContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920bc mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rbx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920bf mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rcx = &amp;l_ExceptionRecord<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920c2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+80h],r14&nbsp;&nbsp; ; l_DispatcherContext.FunctionEntry = l_pFunctionEntry<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ca mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0B0h],rax&nbsp;&nbsp;; l_DispatcherContext.HistoryTable = pHistoryTable<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920d2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+88h],rbx&nbsp;&nbsp; ; l_DispatcherContext.EstablisherFrame = l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920da mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+98h],rdi&nbsp;&nbsp; ; l_DispatcherContext.ContextRecord = pOriginalContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920e2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0A8h],r13&nbsp;&nbsp;; l_DispatcherContext.HandlerData = l_pHandlerData<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ea mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0B8h],r15d ; l_DispatcherContext.ScopeIndex = 0<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920f2 and&nbsp;&nbsp;&nbsp;&nbsp; esi,0FFFFFF9Fh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; l_ExceptionFlags &amp;= ~(EXCEPTION_TARGET_UNWIND|EXCEPTION_COLLIDED_UNWIND)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920f5 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpExecuteHandlerForUnwind (fffff800`008bd9d0)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlpExecuteHandlerForUnwind(&amp;l_ExceptionRecord,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l_pEstablisherFrame,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pOriginalContext,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;l_DispatcherContext);<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920fa dec&nbsp;&nbsp;&nbsp;&nbsp; eax<br />
..&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . . fffff800`008920fc je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x368 (fffff800`008921d8) ; 如果返回 ExceptionContinueSearch 则跳转<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x292:<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . fffff800`00892102 cmp&nbsp;&nbsp;&nbsp;&nbsp; eax,2 ; cmp eax, ExceptionCollidedUnwind (3 - 1)<br />
..&nbsp;&nbsp;..&lt;&nbsp;&nbsp;. . fffff800`00892105 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x426 (fffff800`00892296)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . <br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . nt!RtlUnwindEx+0x29b:<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ; ExceptionCollidedUnwind 的情况<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089210b mov&nbsp;&nbsp;&nbsp;&nbsp; r8,qword ptr [rsp+70h]&nbsp;&nbsp; ; r8 = l_DispatcherContext.ControlPc<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892110 mov&nbsp;&nbsp;&nbsp;&nbsp; r10,qword ptr [rsp+78h]&nbsp;&nbsp;; r10 = l_DispatcherContext.ImageBase<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892115 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+98h]&nbsp;&nbsp;; rdx = l_DispatcherContext.ContextRecord<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089211d mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+6A0h] ; rcx = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892125 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+80h]&nbsp;&nbsp;; r14 = l_DispatcherContext.FunctionEntry<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089212d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+68h],r8<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892132 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+60h],r10<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892137 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlpCopyContext(pOriginalContext, l_DispatcherContext.ContextRecord);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089213c mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089213f mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdi = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892142 lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+160h] ; rcx = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089214a lea&nbsp;&nbsp;&nbsp;&nbsp; r12,[rsp+160h] ; r12 = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892152 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlpCopyContext(&amp;l_Context, pOriginalContext);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892157 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+38h],0&nbsp;&nbsp; ; _ARG_8 = NULL<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892160 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+680h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;l_pEstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892168 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+30h],rax ; _ARG_7 = &amp;l_pEstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089216d lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+58h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = &amp;l_pHandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892172 mov&nbsp;&nbsp;&nbsp;&nbsp; r9,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = l_DispatcherContext.FunctionEntry<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892175 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = &amp;l_pHandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089217a lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+160h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892182 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,r10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rdx = l_DispatcherContext.ImageBase<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892185 xor&nbsp;&nbsp;&nbsp;&nbsp; ecx,ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ecx = UNW_FLAG_NHANDLER (0)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892187 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],rax ; _ARG_5 = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089218c call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlVirtualUnwind (fffff800`00891380)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlVirtualUnwind(UNW_FLAG_NHANDLER,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.ImageBase,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.ControlPc,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.FunctionEntry,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_Context,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pHandlerData,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pEstablisherFrame,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892191 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+88h]&nbsp;&nbsp; ; rbx = l_DispatcherContext.EstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892199 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+0A0h]&nbsp;&nbsp;; rcx = l_DispatcherContext.LanguageHandler<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921a1 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+0A8h]&nbsp;&nbsp;; r13 = l_DispatcherContext.HandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921a9 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+0B0h]&nbsp;&nbsp;; rax = l_DispatcherContext.HistoryTable<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921b1 mov&nbsp;&nbsp;&nbsp;&nbsp; r15d,dword ptr [rsp+0B8h] ; r15d = l_DispatcherContext.ScopeIndex<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921b9 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+680h],rbx&nbsp;&nbsp;; l_pEstablisherFrame = l_DispatcherContext.EstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921c1 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+48h],rcx&nbsp;&nbsp; ; l_pExceptionRoutine = l_DispatcherContext.LanguageHandler<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921c6 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+58h],r13&nbsp;&nbsp; ; l_pHandlerData = l_DispatcherContext.HandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921cb mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+6A8h],rax&nbsp;&nbsp;; pHistoryTable = l_DispatcherContext.HistoryTable<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921d3 or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,40h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND (40)<br />
..&nbsp;&nbsp;...&lt; . . fffff800`008921d6 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x382 (fffff800`008921f2)<br />
..&nbsp;&nbsp;.... . . <br />
..&nbsp;&nbsp;.... . . nt!RtlUnwindEx+0x368:<br />
..&nbsp;&nbsp;.&gt;.. . . fffff800`008921d8 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame<br />
..&nbsp;&nbsp;. ..&lt;. . fffff800`008921db je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x37d (fffff800`008921ed)<br />
..&nbsp;&nbsp;. .... . <br />
..&nbsp;&nbsp;. .... . nt!RtlUnwindEx+0x36d:<br />
..&nbsp;&nbsp;. .... . fffff800`008921dd mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
..&nbsp;&nbsp;. .... . fffff800`008921e2 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = pOriginalContext<br />
..&nbsp;&nbsp;. .... . fffff800`008921e5 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,r12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rdi = &amp;l_Context<br />
..&nbsp;&nbsp;. .... . fffff800`008921e8 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r12 = pOriginalContext<br />
..&nbsp;&nbsp;. .v.. . fffff800`008921eb jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x382 (fffff800`008921f2)<br />
..&nbsp;&nbsp;. .... . <br />
..&nbsp;&nbsp;. .... . nt!RtlUnwindEx+0x37d:<br />
..&nbsp;&nbsp;. ..&gt;. . fffff800`008921ed mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
..&nbsp;&nbsp;. .. . . <br />
..&nbsp;&nbsp;. .. . . nt!RtlUnwindEx+0x382:<br />
..&nbsp;&nbsp;. .&gt; . . fffff800`008921f2 test&nbsp;&nbsp;&nbsp;&nbsp;sil,40h&nbsp;&nbsp;; test sil, EXCEPTION_COLLIDED_UNWIND (40)<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&lt; . fffff800`008921f6 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x200 (fffff800`00892070)<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x38c:<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`008921fc mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+68h]&nbsp;&nbsp;; r13 = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892201 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+688h] ; r15 = pJumpTargetIp<br />
..&nbsp;&nbsp;. .&lt;&nbsp;&nbsp; . fffff800`00892209 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;. ..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;. ..&nbsp;&nbsp; . nt!RtlUnwindEx+0x39b:<br />
..&nbsp;&nbsp;&gt; ..&nbsp;&nbsp; . fffff800`0089220b cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp&nbsp;&nbsp;; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame<br />
..&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`0089220e je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3a0:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892210 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi ; rax = &amp;l_Context<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892213 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,r12 ; rdi = pOriginalContext<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892216 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,rax ; r12 = &amp;l_Context<br />
..&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`00892219 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3ab:<br />
&gt;.&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089221b mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rdi+98h]&nbsp;&nbsp;; rcx = pOriginalContext-&gt;Rsp<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892222 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rsp[0]<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892225 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+0F8h],rax ; pOriginalContext-&gt;Rip = pOriginalContext-&gt;Rsp[0]<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089222c lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rcx+8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rsp + 8<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892230 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+98h],rax&nbsp;&nbsp;; pOriginalContext-&gt;Rsp = pOriginalContext-&gt;Rsp + 8 （跳过返回值）<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; .<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3c7:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&gt;&nbsp;&nbsp; . fffff800`00892237 test&nbsp;&nbsp;&nbsp;&nbsp;bl,7 ; 检查 l_DispatcherContext.EstablisherFrame 是否对齐<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`0089223a jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3cc:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089223c cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+50h] ; cmp l_DispatcherContext.EstablisherFrame, l_LowLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&lt;&nbsp;&nbsp;. fffff800`00892241 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3da (fffff800`0089224a)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. nt!RtlUnwindEx+0x3d3:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. fffff800`00892243 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+40h] ; cmp l_DispatcherContext.EstablisherFrame, l_HighLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&lt; . fffff800`00892248 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x414 (fffff800`00892284)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.... . <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.... . nt!RtlUnwindEx+0x3da:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&gt;. . fffff800`0089224a mov&nbsp;&nbsp;&nbsp;&nbsp; al,byte ptr gs:[20DEh] ; al = _KPCR-&gt;DpcRoutineActive<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. . . fffff800`00892252 test&nbsp;&nbsp;&nbsp;&nbsp;al,al<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. .&lt;. fffff800`00892254 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x43c (fffff800`008922ac)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x3e6:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892256 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089225b mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089225f test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. .&lt;. fffff800`00892262 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x43c (fffff800`008922ac)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x3f4:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892264 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rcx-20h]&nbsp;&nbsp;; rdx = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892268 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892270 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt; ... fffff800`00892273 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x405:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892275 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt; ... fffff800`00892278 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x40a:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089227a mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089227f mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x414:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. &gt;.. fffff800`00892284 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. &lt;.. fffff800`00892287 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x449 (fffff800`008922b9)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x419:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892289 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..^ fffff800`00892291 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xf0 (fffff800`00891f60)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..&nbsp;&nbsp;<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..&nbsp;&nbsp;nt!RtlUnwindEx+0x426:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&gt;. ..&nbsp;&nbsp;fffff800`00892296 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C0000026h ; ecx = STATUS_INVALID_DISPOSITION<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`0089229b call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a0 int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;nt!RtlUnwindEx+0x431:<br />
 &gt;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a1 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C0000028h ; ecx = STATUS_BAD_STACK<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a6 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922ab int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;nt!RtlUnwindEx+0x43c:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&gt;&nbsp;&nbsp;fffff800`008922ac mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&nbsp;&nbsp; nt!RtlUnwindEx+0x444:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt; .&nbsp;&nbsp; fffff800`008922b4 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; fffff800`008922b7 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x479 (fffff800`008922e9)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; <br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; nt!RtlUnwindEx+0x449:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp; fffff800`008922b9 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+698h]&nbsp;&nbsp;; rax = ReturnValue<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922c1 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+690h]&nbsp;&nbsp;; rbx = pExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922c9 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+78h],rax&nbsp;&nbsp; ; pOriginalContext-&gt;Rax, ReturnValue<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922cd cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rbx],80000029h ; cmp pExceptionRecord-&gt;ExceptionCode, STATUS_UNWIND_CONSOLIDATE<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922d3 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x46c (fffff800`008922dc)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x465:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922d5 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+0F8h],r15 ; pOriginalContext-&gt;Rip, pJumpTargetIp<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x46c:<br />
.&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922dc mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rbx ; rdx = pExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922df mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rdi ; rcx = pOriginalContext<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922e2 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRestoreContext (fffff800`008bd290)<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922e7 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x4a0 (fffff800`00892310)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x479:<br />
&gt;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922e9 cmp&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rdi+0F8h] ; pOriginalContext-&gt;Rip<br />
 .&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f0 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x48d (fffff800`008922fd)<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x482:<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f2 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C00000FFh ; ecx = STATUS_BAD_FUNCTION_TABLE<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f7 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922fc int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x48d:<br />
 .&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922fd mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+690h] ; rcx = pExceptionRecord<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892305 xor&nbsp;&nbsp;&nbsp;&nbsp; r8d,r8d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8d = 0<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892308 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = pOriginalContext<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`0089230b call&nbsp;&nbsp;&nbsp;&nbsp;nt!ZwRaiseException (fffff800`008b9b80)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ZwRaiseException(pExceptionRecord, pOriginalContext, FALSE);<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x4a0:<br />
 &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892310 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+638h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892318 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+640h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892320 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+648h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892328 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [rsp+650h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892330 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,qword ptr [rsp+658h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892338 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+660h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892340 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [rsp+668h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892348 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+670h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892350 add&nbsp;&nbsp;&nbsp;&nbsp; rsp,678h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892357 ret</code></div></div>
<br />
	<span style="font-weight: bold;">参考资料</span><br />
<br />
	[1] wrk 源码<br />
	[2] Improving Automated Analysis of Windows x64 Binaries, skape<br />
	[3] Programming against the x64 exception handling support, Skywing<br />
	[4] Exceptional Behavior - x64 Structured Exception Handling, The NT Insider<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".zip" />&nbsp;&nbsp;<a href="attachment.php?aid=12" target="_blank">SEH分析笔记（x64篇）_v1.0.0.zip</a> (Size: 398.19 KB / Downloads: 121)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[SEH分析笔记（X64篇）<br />
	v1.0.0<br />
	boxcounter<br />
<br />
	历史：<br />
	v1.0.0, 2011-11-4：最初版本。<br />
<br />
	[不介意转载，但请注明出处 <a href="http://www.boxcounter.com" target="_blank">www.boxcounter.com</a> <br />
	附件里有本文的原始稿，一样的内容，更好的高亮和排版。<br />
	本文的部分代码可能会因为论坛的自动换行变得很乱，需要的朋友手动复制到自己的代码编辑器就可以正常显示了]<br />
<br />
	在之前的《SEH分析笔记（X86篇）》中，我借助 wrk1.2 介绍了 x86 下 windows 系统内核中的 SEH 实现。这次我们来看看 x64 位 windows 系统内核中 SEH 的实现。<br />
	本文需要大家熟悉 x64 位系统的一些特性，比如调用约定、Prolog 和 Epilog。可以通过这几篇文章熟悉一下:<br />
	<a href="http://msdn.microsoft.com/en-us/library/ms235286.aspx" target="_blank">Overview of x64 Calling Conventions</a>, MSDN<br />
	<a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx" target="_blank">The history of calling conventions, part 5: amd64</a> , The Old New Thing<br />
	<a href="http://msdn.microsoft.com/en-us/magazine/cc300794.aspx" target="_blank">Everything You Need To Know To Start Programming 64-Bit Windows Systems</a>, Matt Pietrek<br />
<br />
	首先回顾一下前一篇文章。<br />
	在 x86 windows 中，函数通过以下几个步骤来参与 SEH ：<br />
	1. 在自身的栈空间中分配并初始化一个 EXCEPTION_REGISTRATION(_RECORD) 结构体。<br />
	2. 将该 EXCEPTION_REGISTRATION(_RECORD) 挂入当前线程的异常链表。<br />
<br />
	当某函数触发异常时，系统首先会通过调用 KiDispatchException 来给内核调试器一个机会，如果内核调试器没有处理该异常，则该机会被转给 RtlDispatchException，这个函数就开始分发该异常。分发过程为：<br />
	从当前线程的异常链表头开始遍历，对于每一个 SEH 注册信息（即 EXCEPTION_REGISTRATION(_RECORD)），调用其 Handler。根据 Handler 的返回值做相应的后续处理：<br />
		1. 返回 ExceptionContinueExecution，表示 Handler 已经修复了异常触发点，从异常触发点继续执行。<br />
		2. 返回 ExceptionContinueSearch，表示该 Handler 没有处理该异常，继续遍历异常链表。<br />
		3. Handler 没有修复异常触发点，但是却能处理该异常（某个 __except 过滤代码返回 EXCEPTION_EXECUTE_HANDLER）。这种情况下，处理完该异常后就从异常解决代码（__except 代码块）继续执行，Handler 不会返回。<br />
	以上是简略的 x86 SEH 流程，其中省略了很多细节，比如展开、错误处理、ExceptionNestedException 和 ExceptionCollidedUnwind 等等。<br />
<br />
	之所以在这里重温这个流程，是因为 x64 中 SEH 的流程总体思路也是如此，只是细节上做了一些修改。但这并不表示熟悉 x86 SEH 就能很轻松的掌握 x64 SEH。<br />
<br />
	本文分为四个部分：“异常注册”、“异常分发”、“展开、解决”和“ExceptionNestedException 和 ExceptionCollidedUnwind”。依然以 MSC 的增强版为分析对象。分析环境为：WDK 7600.16385.1，内置的 cl 的版本是15.00.30729.207，link 的版本是9.00.30729.207，测试虚拟机系统为 amd64 WinXP + wrk1.2。<br />
	<br />
	在讲述之前，需要先定义几个名词，以简化后续的讲述。<br />
<br />
	RVA —— 熟悉 PE 格式的朋友都懂的，表示某个绝对地址相对于所在模块的基地址的偏移。<br />
	EXCEPT_POINT —— 异常触发点。<br />
	EXCEPT_FILTER —— __except 小括号内的异常过滤代码。<br />
	EXCEPT_HANDLER —— __except 大括号内的异常解决代码。<br />
	FINALLY_HANDLER —— __finally 大括号内的代码。<br />
<br />
	以下面的伪码为例，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *((ULONG*)NULL) = 0; <br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;12 __finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;13 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;15 {</code></div></div>
	EXCEPT_POINT 指的是行5中的代码。<br />
	EXCEPT_FILTER 指的是行7中的“(STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER”。<br />
	EXCEPT_HANDLER 指的是行8到行10中所有的代码。<br />
	FINALLY_HANDLER 指的是行13到行15中所有的代码。<br />
<br />
<br />
	<span style="font-weight: bold;">一、异常注册</span><br />
<br />
	在 x64 windows 中，异常注册信息发生了巨大的改变。x86 中异常注册信息是在函数执行过程中在栈中分配并初始化的。x64 中变成这样：<br />
	异常注册信息不再是动态创建，而是编译过程中生成，链接时写入 PE+ 头中的 ExceptionDirectory（参考 winnt.h 中 IMAGE_RUNTIME_FUNCTION_ENTRY 的定义）。ExceptionDirectory 里包含几乎所有函数的栈操作、异常处理等信息。<br />
<br />
	来看看新异常注册信息的数据结构：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _RUNTIME_FUNCTION {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG BeginAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG EndAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG UnwindData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef enum _UNWIND_OP_CODES {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_PUSH_NONVOL = 0,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_LARGE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_SMALL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SET_FPREG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_NONVOL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_NONVOL_FAR,&nbsp;&nbsp; // 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SPARE_CODE1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SPARE_CODE2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 7<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_XMM128,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_SAVE_XMM128_FAR,&nbsp;&nbsp; // 9<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UWOP_PUSH_MACHFRAME&nbsp;&nbsp;&nbsp;&nbsp; // 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_OP_CODES, *PUNWIND_OP_CODES;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef union _UNWIND_CODE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR CodeOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR UnwindOp : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR OpInfo : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;USHORT FrameOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_CODE, *PUNWIND_CODE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_NHANDLER 0x0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_EHANDLER 0x1<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_UHANDLER 0x2<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNW_FLAG_CHAININFO 0x4<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_INFO {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Version : 3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Flags : 5;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR SizeOfProlog;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR CountOfCodes;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR FrameRegister : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR FrameOffset : 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UNWIND_CODE UnwindCode[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;// The unwind codes are followed by an optional DWORD aligned field that<br />
&nbsp;&nbsp;&nbsp;&nbsp;// contains the exception handler address or a function table entry if<br />
&nbsp;&nbsp;&nbsp;&nbsp;// chained unwind information is specified. If an exception handler address<br />
&nbsp;&nbsp;&nbsp;&nbsp;// is specified, then it is followed by the language specified exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;// handler data.<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;union {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ExceptionHandler;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ExceptionData[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_INFO, *PUNWIND_INFO;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _SCOPE_TABLE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG BeginAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG EndAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG HandlerAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG JumpTarget;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} ScopeRecord[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} SCOPE_TABLE, *PSCOPE_TABLE;</code></div></div>
	x64 中，MSC 为几乎所有的函数都登记了完备的信息，用来在展开过程中完整的回滚函数所做的栈、寄存器操作。登记的信息包括：<br />
	函数是否使用了 SEH、<br />
	函数使用的是什么组合的 SEH（__try/__except？__try/__finally？）、<br />
	函数申请了多少栈空间、<br />
	函数保存了哪些寄存器、<br />
	函数是否建立了栈帧，<br />
	等等，<br />
	同时也记录了这些操作的顺序（以保证回滚的时候不会乱套）。<br />
<br />
	这些信息就存储在 UNWIND_INFO 之中。<br />
	UNWIND_INFO 相当于 x86 下的 EXCEPTION_REGISTRATION。它的成员分别是：<br />
		Version —— 结构体的版本。<br />
		Flags —— 标志位，可以有这么几种取值：<br />
			UNW_FLAG_NHANDLER (0x0): 表示既没有 EXCEPT_FILTER 也没有 EXCEPT_HANDLER。<br />
			UNW_FLAG_EHANDLER (0x1): 表示该函数有 EXCEPT_FILTER &amp; EXCEPT_HANDLER。<br />
			UNW_FLAG_UHANDLER (0x2): 表示该函数有 FINALLY_HANDLER。<br />
			UNW_FLAG_CHAININFO (0x4): 表示该函数有多个 UNWIND_INFO，它们串接在一起（所谓的 chain）。<br />
		SizeOfProlog —— 表示该函数的 Prolog 指令的大小，单位是 byte。<br />
		CountOfCodes —— 表示当前 UNWIND_INFO 包含多少个 UNWIND_CODE 结构。<br />
		FrameRegister —— 如果函数建立了栈帧，它表示栈帧的索引（相对于 CONTEXT::RAX 的偏移，详情参考 RtlVirtualUnwind 源码）。否则该成员的值为0。<br />
		FrameOffset —— 表示 FrameRegister 距离函数最初栈顶（刚进入函数，还没有执行任何指令时的栈顶）的偏移，单位也是 byte。<br />
		UnwindCode —— 是一个 UNWIND_CODE 类型的数组。元素数量由 CountOfCodes 决定。<br />
	需要说明几点：<br />
		1. 如果 Flags 设置了 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER，那么在最后一个 UNWIND_CODE 之后存放着 ExceptionHandler（相当于 x86 EXCEPTION_REGISTRATION::handler）和 ExceptionData（相当于 x86 EXCEPTION_REGISTRATION::scopetable）。<br />
		2. UnwindCode 数组详细记录了函数修改栈、保存非易失性寄存器的指令。<br />
		3. MSDN 中有 UNWIND_INFO 和 UNWIND_CODE 的详细说明，推荐阅读。<br />
<br />
	那 UNWIND_INFO 是如何与其描述的函数关联起来的呢？答案是：通过一个 RUNTIME_FUNCTION 结构体。<br />
	RUNTIME_FUNCTION::BeginAddress 同 RUNTIME_FUNCTION::EndAddress 一起以 RVA 形式描述了函数的范围。<br />
	RUNTIME_FUNCTION::UnwindData 就是 UNWIND_INFO 了，它也是一个 RVA 值。<br />
<br />
	PE+ 中的 ExceptionDirectory 中存放着所有函数的 RUNTIME_FUNCTION，按 RUNTIME_FUNCTION::BeginAddress 升序排列。一旦触发异常，系统可以通过 EXCEPT_POINT 的 RVA 在 ExceptionDirectory 中二分查找到 RUNTIME_FUNCTION，进而找到 UNWIND_INFO。<br />
	<br />
	前面有提到，MSC 为几乎所有的函数都登记了完毕的信息，那是不是有一些特殊函数没有登记信息呢？<br />
	是的。x64 新增了一个概念，叫做“叶函数”。熟悉数据结构的朋友可能第一时间就联想到“叶节点”。没错，“叶函数”的含义跟“叶节点”很类似，叶函数不会有子函数，也就是说它不会再&#8203;调用任何函数。另外 x64 对这个概念额外加了一些要求：不修改栈指针（比如分配栈空间）、没有使用 SEH。总结下来就是：既不调用函数、又没有修改栈指针，也没有使用 SEH 的函数就叫做“叶函数”。<br />
	叶函数可以没有登记信息，原因很简单，它根本就没信息需要登记~<br />
<br />
	还有一个 SCOPE_TABLE 结构，熟悉 x86 SEH 的朋友应该很眼熟 :-)，它等同于 x86 SEH 中的 REGISTRATIOIN_RECORD::scopetable 的类型。其成员有：<br />
		Count —— 表示 ScopeRecord 数组的大小。<br />
		ScopeRecord —— 等同于 x86 中的 scopetable_entry 成员。其中，<br />
			BeginAddress 和 EndAddress 表示某个 __try 保护域的范围。<br />
			HandlerAddress 和 JumpTarget 表示 EXCEPTION_FILTER、EXCEPT_HANDLER 和 FINALLY_HANDLER。具体对应情况为：<br />
				对于 __try/__except 组合，HandlerAddress 代表 EXCEPT_FILTER，JumpTarget 代表 EXCEPT_HANDLER。<br />
				对于 __try/__finally 组合，HandlerAddress 代表 FINALLY_HANDLER，JumpTarget 等于 0。<br />
			这四个域通常都是 RVA，但当 EXCEPT_FILTER 简单地返回或等于 EXCEPTION_EXECUTE_HANDLER 时，HandlerAddress 可能直接等于 EXCEPTION_EXECUTE_HANDLER，而不再是一个 RVA。<br />
<br />
	我们可以通过 windbg 中的 .fnent 命令来查看某个函数的异常注册信息。比如，<br />
<br />
	1   kd&gt; .fnent passThrough!SehTest<br />
	2   Debugger function entry 00000000`00778210 for:<br />
	3   d:\workspace\code\mycode\r0\passthrough\passthrough.c(51)<br />
	4   (fffffadf`f140f020)   PassThrough!SehTest   |  (fffffadf`f140f0c0)   PassThrough!Caller2<br />
	5   Exact matches:<br />
	6       PassThrough!SehTest (void)<br />
	7   <br />
	8   BeginAddress      = 00000000`00001020<br />
	9   EndAddress        = 00000000`000010b2<br />
	10  UnwindInfoAddress = 00000000`00002668<br />
	11  <br />
	12  Unwind info at fffffadf`f1410668, 10 bytes<br />
	13    version 1, flags 1, prolog 4, codes 1<br />
	14    handler routine: PassThrough!_C_specific_handler (fffffadf`f140f4ce), data 3<br />
	15    00: offs 4, unwind op 2, op info 4	UWOP_ALLOC_SMALL.<br />
<br />
	行8到行10描述的是 RUNTIME_FUNCTION。<br />
	行12到行15描述的是 UNWIND_INFO。<br />
<br />
	对于叶函数，输出是这样的，<br />
<br />
	kd&gt; .fnent passthrough!LeafTest<br />
	No function entry for fffffadf`f240c080<br />
<br />
	到这里，异常注册就讲完了，我们认识了相关的数据结构和定位方法。下面我们进入异常分发流程。<br />
<br />
<br />
	二、异常分发<br />
<br />
	x64 异常分发过程使用的仍然是 KiDispatchException、RtlDispatchException、RtlpExecuteHandlerForException 等函数。<br />
<br />
	其中，KiDispatchException 中有关内核异常部分的代码完全没有变化，这里我偷懒直接拷贝《SEH分析笔记（X86篇）》中的部分描述，<br />
<br />
	原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;KiDispatchException (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PKEXCEPTION_FRAME ExceptionFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PKTRAP_FRAME TrapFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN KPROCESSOR_MODE PreviousMode,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN BOOLEAN FirstChance<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	对于内核异常，它的处理步骤如下：<br />
		如果 FirstChance 为 TRUE，那么,<br />
			1. 首先将该异常传达给内核调试器（KD），如果 KD 处理了该异常，那么函数返回。<br />
			2. KD 没有处理，调用 RtlDispatchException 进行异常分发。如果分发成功，RtlDispatchExcetpion 返回 TRUE，或者根本不返回。<br />
			3. RtlDispatchException 分发失败，那么再给 KD 一次处理机会，如果还是没有处理，那么 BUGCHECK。<br />
		如果 FirstChance 为 FALSE，那么将该异常传达给 KD，如果 KD 没有处理，那么 BUGCHECK。<br />
	它的源码实现位于 &#36;WRK-v1.2\base\ntos\ke\amd64\exceptn.c:430。<br />
<br />
	RtlDispatchException 发生了一些改变。<br />
	从之前描述的异常注册信息的数据结构可以发现，x64 中已经不存在异常注册链这个概念了（虽然 _NT_TIB 结构体中还保留了 ExceptionList 域）。那 x64 中 RtlDispatchException 是如何遍历异常注册信息的呢？前面虽然有提到如何通过 EXCEPT_POINT 找到 UNWIND_INFO 结构，但是假如这个 UNWIND_INFO 没有处理该异常，如何继续遍历呢？<br />
<br />
	在解答这个问题之前，我们先来认识一个新函数和相关的数据结构，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_SIZE 12<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_HISTORY_TABLE_ENTRY {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ImageBase;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_NONE 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_GLOBAL 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;#define UNWIND_HISTORY_TABLE_LOCAL 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _UNWIND_HISTORY_TABLE {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UCHAR Search;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 LowAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 HighAddress;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];<br />
&nbsp;&nbsp;&nbsp;&nbsp;} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlLookupFunctionEntry (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ControlPc,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PULONG64 ImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	RtlLookupFunctionEntry 的功能是查找指定地址所在函数的 RUNTIME_FUNCTION 和所在模块的基地址。它的参数分为为，<br />
		ControlPc —— 需要查找的指令地址，<br />
		ImageBase —— 返回的模块基地址，<br />
		HistoryTable —— 用于加速查找。<br />
<br />
	工作流程：<br />
	RtlLookupFunctionEntry 在搜索的过程会根据是否传入 HistoryTable 而采取不同的搜索方法：<br />
		如果传入 HistoryTable，则根据 HistoryTable-&gt;Search 表示的搜索方式在表中进行搜索：<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_NONE，那么不在 HistoryTable 中进行搜索。<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_GLOBAL，则首先在全局表 RtlpUnwindHistoryTable 开始搜索，如果搜索到，则结束搜索，函数返回。否则再在 HistoryTable 中搜索。<br />
			如果搜索方式为 UNWIND_HISTORY_TABLE_LOCAL，那么在 HistoryTable 中搜索。<br />
		如果上述过程中没有搜索到需要的结果，那么找到模块基地址，从模块的 PE+ 头结构中解析出 RUNTIME_FUNCTION。如果搜索方式为 UNWIND_HISTORY_TABLE_NONE，还会将解决加入到 HistoryTable。<br />
<br />
	之前的描述中 RtlDispatchException 定位 EXCEPT_POINT 所对应的 RUNTIME_FUNCTION 就是通过调用 RtlLookupFunctionEntry 实现的。<br />
<br />
	回到刚才的问题，如何推动遍历呢？为了解决这个问题，x64 又引进了一个新函数。现在我们有请 x64 SEH 核心成员 RtlVirtualUnwind 登场~<br />
<br />
	先来看看它的原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;PEXCEPTION_ROUTINE<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlVirtualUnwind (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG HandlerType,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN ULONG64 ControlPc,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PRUNTIME_FUNCTION FunctionEntry,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PVOID *HandlerData,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUT PULONG64 EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	它的主要功能是：<br />
		根据传入的 ControlPc 和 ContextRecord 等参数虚拟（模拟）展开该函数，并返回该函数的一些信息，比如 HandlerData（SCOPE_TABLE）、EstablisherFrame（rsp 或 栈帧）。	<br />
	流程是：<br />
		1. 通过 FunctionEntry 和 ImageBase 找到 UNWIND_INFO。根据 UNWIND_INFO 中记录的信息，查找 EstablisherFrame（即栈帧或者 rsp）。<br />
		2. 根据 ControlPc 分如下两种情况展开：<br />
			a. ControlPc &gt;= EpilogOffset，即 ControlPc 在 Epilog 之中。那么把剩余的 Epilog 指令模拟执行完毕即可。<br />
			   所谓模拟是指，如果下一条 EpiLog 指令是“sub rsp, 0x32”，那么将 ContextRecord-&gt;rsp 减去0x32。并不是真正执行 sub 指令。<br />
			b. ControlPc &lt; EpilogOffset，那么把 Prolog 反向模拟回滚一遍即可。<br />
			   所谓反向回滚是指，如果 Prolog 的指令是<br />
			   mov   [RSP + 8], RCX<br />
			   push R15<br />
			   push R14<br />
			   push R13 <br />
			   那么反向回滚就是<br />
		          pop ContextRecord-&gt;R13 （实际上是从 ContextRecord-&gt;Rsp 指向的内存中取出值存入 ContextRecord-&gt;R13，然后 ContextRecord-&gt;Rsp 加上8。并不是真正执行 pop）<br />
		          pop ContextRecord-&gt;R14<br />
		          pop ContextRecord-&gt;R15<br />
		          mov ContextRecord-&gt;RCX, [ContextRecord-&gt;RSP+8]<br />
		   然后把 ContextRecord-&gt;Rip 修改为 ControlPc 所在函数的返回地址，即父函数中的某一处 call 的下一条指令。<br />
		   这样，ContextRecord 就被恢复成父函数在调用 ControlPc 所在函数之后的状态了。<br />
		3. 如果 HandlerType 包含 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER，那么将 UNWIND_INFO::ExceptionData 赋给传出参数 HandlerData，并返回 UNWIND_INFO::ExceptionRoutine。<br />
		   对于 MSC 编译器生成的模块，UNWIND_INFO::ExceptionRoutine 一般指向 nt!__C_specific_handler。UNWIND_INFO::ExceptionData 指向 ControlPc 所在函数的 SCOPE_TABLE。<br />
	RtlVirtualUnwind 的实现源码位于 &#36;WRK-v1.2\base\ntos\rtl\amd64\exdsptch.c:1202。<br />
<br />
	RtlVirtualUnwind 返回后，RtlDispatchException 就可以根据 ContextRecord-&gt;Rip 找到父函数对应的 RUNTIME_FUNCTION，进而找到 UNWIND_INFO。就这样推动整个遍历过程。<br />
	<br />
	这是一般情况，对于没有 UNWIND_INFO 的叶函数呢？<br />
	对于叶函数，RtlLookupFunctionEntry 返回 NULL，于是 RtlDispatchException 知道这是个叶函数，就找到该叶函数的父函数，从父函数继续遍历。也就是完全无视叶函数，因为叶函数对整个异常处理过程没有任何影响。<br />
	<br />
	RtlDispatchException 调用 UNWIND_INFO::ExceptionHandler 依然是通过 RtlpExecuteHandlerForException，其函数原型没有变化：<br />
	<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlpExecuteHandlerForException (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID DispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	该函数的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:84。<br />
	RtlpExecuteHandlerForException 的逻辑较 x86 版本没什么大变化，内部注册了一个异常处理函数 RtlpExceptionHandler。RtlpExceptionHandler 相当于 x86 中的 nt!ExecuteHandler2，其内部会返回 ExceptionNestedException 或 ExceptionContinueSearch。它的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:26。<br />
	<br />
	需要一提的是，最后一个参数 DispatchContext 的类型是 DISPATCHER_CONTEXT，相对于 x86 版本，它扩充了很多，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;typedef struct _DISPATCHER_CONTEXT {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ControlPc;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 ImageBase;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRUNTIME_FUNCTION FunctionEntry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 EstablisherFrame;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG64 TargetIp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PCONTEXT ContextRecord;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PEXCEPTION_ROUTINE LanguageHandler;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID HandlerData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PUNWIND_HISTORY_TABLE HistoryTable;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG ScopeIndex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG Fill0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;</code></div></div>
	成员分别为：<br />
		ControlPc —— 异常触发点。<br />
		ImagePase —— ControlPc 所在模块的基地址。<br />
		FunctionEntry —— ControlPc 所在函数的 RUNTIME_FUNCTION。<br />
		EstablisherFrame —— ControlPc 所在函数的栈帧（如果建立了栈帧）或 RSP。<br />
		TargetIp —— 解决异常的 EXCEPT_HANDLER 地址，该成员只在展开的过程中被使用。RtlpExecuteHandlerForException 没有使用它。<br />
		ContextRecord —— 供展开过程中使用，只有当展开过程中触发新异常（返回 ExceptionCollidedUnwind）时，才会被 RtlDispatchException 真正的使用到（参考 RtlDispatchException 处理 ExceptionCollidedUnwind 的代码）。<br />
		LanguageHandler —— ControlPc 所在函数的 UNWIND_INFO::ExceptionRoutine。<br />
		HandlerData —— ControlPc 所在函数的 UNWIND_INFO::ExceptionData。<br />
		ScopeIndex —— UNWIND_INFO::ExceptionData 中 SCOPE_TABLE::ScopeRecord 的索引，通常设置为0（注：请不要与 x86 中运行时不断改变的 EXCEPTION_REGISTRATION::trylevel 相混淆，ScopeIndex 不会在在函数执行过程中改变）<br />
		Fill0 —— 未用。<br />
<br />
	再看一下它的 .fnent 输出，<br />
<br />
	1  kd&gt; .fnent nt!RtlpExecuteHandlerForException<br />
	2  Debugger function entry 00000000`01458210 for:<br />
	3  (fffff800`008bd950)   nt!RtlpExecuteHandlerForException   |  (fffff800`008bd970)   nt!RtlpUnwindHandler<br />
	4  Exact matches:<br />
	5      nt!RtlpExecuteHandlerForException (void)<br />
	6  <br />
	7  BeginAddress      = 00000000`000bd950<br />
	8  EndAddress        = 00000000`000bd963<br />
	9  UnwindInfoAddress = 00000000`000dfeb8<br />
	10 <br />
	11 Unwind info at fffff800`008dfeb8, 10 bytes<br />
	12   version 1, flags 3, prolog 4, codes 1<br />
	13   handler routine: nt!RtlpExceptionHandler (fffff800`008bd920), data 0<br />
	14   00: offs 4, unwind op 2, op info 4	UWOP_ALLOC_SMALL.<br />
<br />
	行12中显示 flags 等于3，即	UNW_FLAG_EHANDLER (0x1) | UNW_FLAG_UHANDLER (0x2)，说明行13中显示的异常处理函数 nt!RtlpExceptionHandler 既负责解决异常，也负责展开。<br />
<br />
	RtlpExecuteHandlerForException 会调用 DISPATCHER_CONTEXT::LanguageHandler。对于 MSC 编译得到的模块，它是 nt!__C_specific_handler，我们来看看这个函数，<br />
<br />
	原型：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION <br />
&nbsp;&nbsp;&nbsp;&nbsp;__C_specific_handler (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD pExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID pEstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT pContext,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID pDispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	反汇编码：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>kd&gt; uf nt!__C_specific_handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d0 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+10h],rdx ; 在栈上保存 pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d5 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rsp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42d8 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,88h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42df mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-8],rbx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42e3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-10h],rbp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42e7 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [r9]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rbp = pDispatcherContext-&gt;ControlPc<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42ea mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-18h],rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42ee mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-20h],rdi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42f2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-28h],r12<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42f6 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [r9+38h]&nbsp;&nbsp;; r12 = pDispatcherContext-&gt;HandlerData<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42fa mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-30h],r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a42fe mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-38h],r14<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4302 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [r9+8]&nbsp;&nbsp;&nbsp;&nbsp;; r14 = pDispatcherContext-&gt;ImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4306 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-40h],r15<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a430a mov&nbsp;&nbsp;&nbsp;&nbsp; r13,r9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r13 = pDispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a430d sub&nbsp;&nbsp;&nbsp;&nbsp; rbp,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_OffsetInFunc = pDispatcherContext-&gt;ControlPc - pDispatcherContext-&gt;ImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4310 test&nbsp;&nbsp;&nbsp;&nbsp;byte ptr [rcx+4],66h&nbsp;&nbsp;&nbsp;&nbsp;; pExceptionRecord-&gt;ExceptionFlags, EXCEPTION_UNWIND (0x66)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4314 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rsi = pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4317 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r15 = pExceptionRecord<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a431a jne&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xf5 (fffff800`008a43c5)<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-------------------------------------------------------------------<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x50:<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4320 movsxd&nbsp;&nbsp;rdi,dword ptr [r9+48h]&nbsp;&nbsp;; l_ScopeIndex (rdi) = pDispatcherContext-&gt;ScopeIndex<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4324 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-58h],rcx ; [rax-58h] = pExceptionRecord，供给 GetExceptionCode(Information) 使用<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4328 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-50h],r8&nbsp;&nbsp;; [rax-50h] = pContext，供给 GetExceptionCode(Information) 使用<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a432c cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12]&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4330 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = l_ScopeIndex<br />
:&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4333 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x69:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4339 add&nbsp;&nbsp;&nbsp;&nbsp; rax,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 这里 *2，下面紧接着 *8，目的是跳过指定数目的 ScopeRecord（大小为16字节）<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a433c lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[r12+rax*8+0Ch] ; rbx = &amp;(pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x71:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 检查 ControlPc 处于哪个 __try 保护域，之步骤一<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4341 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-8] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4344 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
::&lt;&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4347 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x79:<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 检查 ControlPc 处于哪个 __try 保护域，之步骤二<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4349 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-4] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
:::&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a434c cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
:::&lt;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a434f jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x81:<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 判断是否是 __try/__finally（JumpTarget 为 NULL）。如果是，那么跳转到下一个 ScopeRecord 继续遍历。<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4351 cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rbx+4],0 ; cmp pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget, NULL<br />
::::&lt;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4355 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd (fffff800`008a43ad)<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x87:<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 到这里，已经找到与异常地址最匹配的 __try/__except<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4357 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress<br />
:::::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4359 cmp&nbsp;&nbsp;&nbsp;&nbsp; eax,1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; cmp pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress, EXCEPTION_EXECUTE_HANDLER (0x1)<br />
:::::&lt;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a435c je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xa3 (fffff800`008a4373) ; 如果返回 EXCEPTION_EXECUTE_HANDLER 则跳转<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x8e:<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 是 __try/__except，且过滤域并不是 EXCEPTION_EXECUTE_HANDLER，执行 HandlerAddress <br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; （注：HandlerAddress 指向的函数仍有可能会返回 EXCEPTION_EXECUTE_HANDLER） <br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a435e lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+30h]<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4363 add&nbsp;&nbsp;&nbsp;&nbsp; rax,r14 ; rax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].HandlerAddress + pDispatcherContext-&gt;ImageBase<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4366 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rsi ; rdx = pEstablisherFrame<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4369 call&nbsp;&nbsp;&nbsp;&nbsp;rax&nbsp;&nbsp;&nbsp;&nbsp; ; 调用 EXCEPT_FILTER<br />
::::::&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436b test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax<br />
::::::&lt; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436d js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xee (fffff800`008a43be) ; 返回 EXCEPTION_CONTINUE_EXECUTION (-1) 则跳转<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x9f:<br />
::::::: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a436f test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax<br />
:::::::&lt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4371 jle&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xdd (fffff800`008a43ad) ; 返回 EXCEPTION_CONTINUE_SEARCH (0) 则跳转<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xa3:<br />
:::::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 返回的是 EXCEPTION_EXECUTE_HANDLER<br />
:::::&gt;:::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4373 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,dword ptr [rbx+4] ; ecx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4376 mov&nbsp;&nbsp;&nbsp;&nbsp; r8d,1<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a437c mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rsi ; rdx = pEstablisherFrame<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a437f add&nbsp;&nbsp;&nbsp;&nbsp; rcx,r14 ; rcx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4382 call&nbsp;&nbsp;&nbsp;&nbsp;nt!_NLG_Notify (fffff800`008b1460)<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4387 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [r13+40h] ; rax = pDispatcherContext-&gt;HistoryTable<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a438b mov&nbsp;&nbsp;&nbsp;&nbsp; edx,dword ptr [rbx+4]&nbsp;&nbsp; ; edx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a438e movsxd&nbsp;&nbsp;r9,dword ptr [r15]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = pExceptionRecord-&gt;ExceptionCode<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4391 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = pDispatcherContext-&gt;HistoryTable<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a4396 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [r13+28h] ; rax = pDispatcherContext-&gt;ContextRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a439a add&nbsp;&nbsp;&nbsp;&nbsp; rdx,r14 ; rdx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a439d mov&nbsp;&nbsp;&nbsp;&nbsp; r8,r15&nbsp;&nbsp;; r8 = pExceptionRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a0 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rsi ; rcx = pEstablisherFrame<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],rax ; _ARG_5 = pDispatcherContext-&gt;ContextRecord<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43a8 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx (fffff800`00891e80) ; 这里不会返回<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; RtlUnwindEx(pEstablisherFrame, <br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext-&gt;ImageBase<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pExceptionRecord,<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pExceptionRecord-&gt;ExceptionCode<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;ContextRecord,<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDispatcherContext-&gt;HistoryTable)<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::::: :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xdd:<br />
::&gt;&gt;&gt; :&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43ad inc&nbsp;&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp; ; l_ScopeIndex += 1<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43af add&nbsp;&nbsp;&nbsp;&nbsp; rbx,10h ; 调整到下一个 ScopeRecord::HandlerAddress<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b3 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
::&nbsp;&nbsp;&nbsp;&nbsp;: &lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b7 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x71 (fffff800`008a4341)<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xe9:<br />
::&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; pDispatcherContext-&gt;HandlerData 遍历完毕<br />
::&lt;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43b9 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
:::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
:::&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0xee:<br />
:::&nbsp;&nbsp; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43be xor&nbsp;&nbsp;&nbsp;&nbsp; eax,eax ; eax = ExceptionContinueExecution<br />
:::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c0 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x16b (fffff800`008a443b)<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------------------------------------------------------------------------------------<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0xf5:<br />
::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 设置了 EXCEPTION_UNWIND，当前是展开过程<br />
&gt;:::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c5 movsxd&nbsp;&nbsp;rdi,dword ptr [r9+48h] ; l_ScopeIndex (rdi) = pDispatcherContext-&gt;ScopeIndex<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43c9 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [r9+20h] ; rsi = pDispatcherContext-&gt;TargetIp<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43cd sub&nbsp;&nbsp;&nbsp;&nbsp; rsi,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rsi = pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43d0 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12]&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
 :::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a43d4 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = l_ScopeIndex<br />
 :::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43d7 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x109:<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43d9 add&nbsp;&nbsp;&nbsp;&nbsp; rax,rax ; <br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008a43dc lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[r12+rax*8+8] ; rbx = &amp;(pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x111:<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 检查 ControlPc 处于哪个 __try 保护域，之步骤一<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt; fffff800`008a43e1 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx-4] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43e4 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rax ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43e7 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : <br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nt!__C_specific_handler+0x119:<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : ; 检查 ControlPc 处于哪个 __try 保护域，之步骤二<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43e9 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,dword ptr [rbx] ; ecx = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43eb cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rcx ; cmp l_OffsetInFunc, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43ee jae&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: <br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: nt!__C_specific_handler+0x120:<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: ; 到这里，已经找到与异常地址匹配的最内层（如果有多层） __try/__except<br />
 ::::::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43f0 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rax ; cmp pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].BeginAddress<br />
 ::::::&lt;&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43f3 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x131 (fffff800`008a4401)<br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : <br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : nt!__C_specific_handler+0x125:<br />
 :::::::&nbsp;&nbsp;&nbsp;&nbsp; : fffff800`008a43f5 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rcx ; cmp pDispatcherContext-&gt;TargetIp - pDispatcherContext-&gt;ImageBase, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].EndAddress<br />
 :::::::&lt;&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43f8 ja&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x131 (fffff800`008a4401)<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: <br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: nt!__C_specific_handler+0x12a:<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: ; 如果标记了 EXCEPTION_TARGET_UNWIND，说明是最后一个需要局部展开的函数。但是该次局部展开只展开到 EXCEPT_HANDLER（不包含 EXCEPT_HANDLER），所以需要判断 TargetIp<br />
 ::::::::&nbsp;&nbsp;&nbsp;&nbsp;: fffff800`008a43fa test&nbsp;&nbsp;&nbsp;&nbsp;byte ptr [r15+4],20h ; test pExceptionRecord-&gt;ExceptionFlags, EXCEPTION_TARGET_UNWIND (0x20)<br />
 ::::::::&lt;&nbsp;&nbsp; : fffff800`008a43ff jne&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 :::::::::&nbsp;&nbsp; : <br />
 :::::::::&nbsp;&nbsp; : nt!__C_specific_handler+0x131:<br />
 ::::::&gt;&gt;:&nbsp;&nbsp; : fffff800`008a4401 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [rbx+8] ; eax = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
 ::::::&nbsp;&nbsp;:&nbsp;&nbsp; : fffff800`008a4404 test&nbsp;&nbsp;&nbsp;&nbsp;eax,eax ; 判断 pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget 是否为 NULL，即是否是 __try/__finally<br />
 ::::::&nbsp;&nbsp;:&lt;&nbsp;&nbsp;: fffff800`008a4406 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x13f (fffff800`008a440f) ; 如果是 __try/__finally 则跳转<br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: <br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: nt!__C_specific_handler+0x138:<br />
 ::::::&nbsp;&nbsp;::&nbsp;&nbsp;: fffff800`008a4408 cmp&nbsp;&nbsp;&nbsp;&nbsp; rsi,rax ; cmp pDispatcherContext-&gt;TargetIp, pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[l_ScopeIndex].JumpTarget<br />
 ::::::&nbsp;&nbsp;::&lt; : fffff800`008a440b je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x166 (fffff800`008a4436)<br />
 ::::::&nbsp;&nbsp;::: : <br />
 ::::::&nbsp;&nbsp;::: : nt!__C_specific_handler+0x13d:<br />
 ::::::&nbsp;&nbsp;:::&lt;: fffff800`008a440d jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x15a (fffff800`008a442a)<br />
 ::::::&nbsp;&nbsp;::::: <br />
 ::::::&nbsp;&nbsp;::::: nt!__C_specific_handler+0x13f:<br />
 ::::::&nbsp;&nbsp;::::: ; 注意这里是先修改 pDispatcherContext-&gt;ScopeIndex，然后调用 EXCEPT_HANDLER。这样如果 EXCEPT_HANDLER 触发异常，后续展开就会跳过这个 EXCEPT_HANDLER。<br />
 ::::::&nbsp;&nbsp;:&gt;::: fffff800`008a440f mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+98h]<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4417 lea&nbsp;&nbsp;&nbsp;&nbsp; eax,[rdi+1]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; eax = l_ScopeIndex + 1<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a441a mov&nbsp;&nbsp;&nbsp;&nbsp; cl,1<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a441c mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [r13+48h],eax ; pDispatcherContext-&gt;ScopeIndex = eax<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4420 mov&nbsp;&nbsp;&nbsp;&nbsp; r8d,dword ptr [rbx+4]&nbsp;&nbsp; ; r8d = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[i].HandlerAddress<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4424 add&nbsp;&nbsp;&nbsp;&nbsp; r8,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pDispatcherContext-&gt;HandlerData-&gt;ScopeRecord[i].HandlerAddress + pDispatcherContext-&gt;ImageBase<br />
 ::::::&nbsp;&nbsp;: ::: fffff800`008a4427 call&nbsp;&nbsp;&nbsp;&nbsp;r8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 调用 __finally 处理块，会返回（注：对于 __try/__finally，HandlerAddress 保存的是 __finally 代码块的 RVA）<br />
 ::::::&nbsp;&nbsp;: ::: <br />
 ::::::&nbsp;&nbsp;: ::: nt!__C_specific_handler+0x15a:<br />
 ::::&gt;&gt;&nbsp;&nbsp;: :&gt;: fffff800`008a442a inc&nbsp;&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_ScopeIndex += 1<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : : fffff800`008a442c add&nbsp;&nbsp;&nbsp;&nbsp; rbx,10h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 调整到下一个 ScopeRecord::HandlerAddress<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : : fffff800`008a4430 cmp&nbsp;&nbsp;&nbsp;&nbsp; edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext-&gt;HandlerData-&gt;Count<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: : &lt; fffff800`008a4434 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!__C_specific_handler+0x111 (fffff800`008a43e1)<br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp; <br />
 ::::&nbsp;&nbsp;&nbsp;&nbsp;: :&nbsp;&nbsp; nt!__C_specific_handler+0x166:<br />
 &gt;&gt;:&gt;&nbsp;&nbsp;&nbsp;&nbsp;&gt; &gt;&nbsp;&nbsp; fffff800`008a4436 mov&nbsp;&nbsp;&nbsp;&nbsp; eax,1 ; eax = ExceptionContinueSearch (0n1)<br />
&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!__C_specific_handler+0x16b:<br />
&nbsp;&nbsp; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a443b mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+48h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4440 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+50h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4445 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+58h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a444a mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [rsp+60h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a444f mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,qword ptr [rsp+68h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4454 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+70h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4459 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [rsp+78h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a445e mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+80h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a4466 add&nbsp;&nbsp;&nbsp;&nbsp; rsp,88h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008a446d ret</code></div></div>
	nt!__C_specific_handler 相当于 x86 中的 nt!_except_handler3。从上面的反汇编代码也可以看出它的逻辑跟 nt!_except_handler3 基本上一致。<br />
	函数代码不长。主要分为两个大分支，一个分支处理异常，一个分支处理展开（我用横线分隔开了）。<br />
<br />
	异常解决的代码负责遍历 SCOPE_TABLE，依次调用 SCOPE_TABLE::ScopeRecord.HandlerAddress 代表的 EXCEPT_FILTER，并针对返回值做出相应的处理：<br />
		1. 返回 EXCEPTION_CONTINUE_EXECUTION，说明异常已经被 EXCEPT_FILTER 修复。返回 ExceptionContinueExecution。<br />
		2. 返回 EXCEPTION_CONTINUE_SEARCH，继续遍历下一个 ScopeRecord。<br />
		3. 返回 EXCEPTION_EXECUTE_HANDLER，说明当前 ScopeRecord.JumpTarget 代表的 EXCEPT_HANDLER 可以处理该异常。那么调用 RtlUnwindEx 进行展开。<br />
<br />
	熟悉 x86 的朋友可能会疑惑：在 x86 中 nt!_except_handler3 先进行全局展开，然后对本函数自身进行不完全的局部展开，最后执行 EXCEPT_HANDLER。而在 nt!__C_specific_handler 中却找不到执行 EXCEPT_HANDLER 的指令，这是怎么回事？<br />
	实际上，x64 对这个流程做了一些调整，EXCEPT_HANDLER 不是由 nt!__C_specific_handler 直接调用，而是作为参数传给 RtlUnwindEx，RtlUnwindEx 处理完展开之后才执行 EXCEPT_HANDLER。后续我们在讲展开的时候会看到具体的方法。<br />
<br />
	__C_specific_handler 的展开分支，是对 SCOPE_TABLE 进行展开，逻辑很简单，不多讲了。<br />
<br />
	更详细的信息，请参考上面反汇编代码中我附的注释。<br />
<br />
	另外还需要说一下 SCOPE_TABLE。<br />
	在 x86 中，遍历 scopetable 时是通过运行时动态改变的 EXCEPTION_REGISTRATION::trylevel 来确定应该首先遍历哪一个 scopetable_entry。而 x64 中没有等同于 trylevel 的数据，有的朋友可能会说“SCOPE_TABLE 中不是有每个 __try 保护域的范围 RVA 吗？通过范围不就可以确定在哪个 __try 中触发了异常吗？”。<br />
	我们可以先试试这种方法，以下面这段伪码为例，<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1 VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp; __try // 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp; __except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;9 <br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;__try // 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try // 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;__except()<br />
&nbsp;&nbsp;&nbsp;&nbsp;21&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;22&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;23<br />
&nbsp;&nbsp;&nbsp;&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;__try // 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;25&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;27&nbsp;&nbsp;&nbsp;&nbsp;__finally()<br />
&nbsp;&nbsp;&nbsp;&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;29&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;30}</code></div></div>
	上述伪码中总共有4个 __try，按照 x86 中的方法，SCOPE_TABLE 的内容应该是顺序排列的，像这样：<br />
<br />
	SCOPE_TABLE::Count 等于4，<br />
	SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[1] 表示行10开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[2] 表示行12开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。<br />
<br />
	假设行14处触发了异常，遍历过程应该是这样，<br />
	首先检查 ScopeRecord[0]，发现其范围不包含 EXCEPT_POINT，继续下一个，<br />
	开始检查 ScopeRecord[1]，范围匹配了。<br />
	<br />
	那是不是该把异常交给 ScopeRecord[1] 处理呢？<br />
	不是！从伪码中可以很明显的看出，行14触发的异常应该首先由行12开始的 __try/__except，即 ScopeRecord[1] 处理。<br />
<br />
	可见这种方法是行不通的。<br />
	MSC 通过调整 SCOPE_TABLE::ScopeRecord 的排列顺序来解决这个问题：<br />
<br />
	SCOPE_TABLE::Count 等于4，<br />
	SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[1] 表示行12开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[2] 表示行10开始的 __try/__except，<br />
	SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。<br />
<br />
	即对于嵌套的 __try/__except/__finally，ScopeRecord 的排列顺序是，最内层的 __try 排在前面，其次是次内层的，依次排到最外层。<br />
	这样就能正确的遍历 SCOPE_TABLE 了。<br />
<br />
	再用伪码完整的展示一下 SCOPE_TABLE 的布置，<br />
<br />
	SCOPE_TABLE::Count = 4。<br />
<br />
	SCOPE_TABLE::ScopeRecord[0].BeginAddress = RVA_L4; （行4的 RVA） // 第一个 __try<br />
	SCOPE_TABLE::ScopeRecord[0].EndAddress = RVA_L5;<br />
	SCOPE_TABLE::ScopeRecord[0].HandlerAddress = RVA_L6_EXCEPT_FILTER; （行6 __except 过滤代码首地址的 RVA）<br />
	SCOPE_TABLE::ScopeRecord[0].JumpTarget = RVA_L7; <br />
<br />
	SCOPE_TABLE::ScopeRecord[1].BeginAddress = RVA_L13;                 // 第三个 __try<br />
	SCOPE_TABLE::ScopeRecord[1].EndAddress = RVA_L15;<br />
	SCOPE_TABLE::ScopeRecord[1].HandlerAddress = RVA_L16_EXCEPT_FILTER; <br />
	SCOPE_TABLE::ScopeRecord[1].JumpTarget = RVA_L7; <br />
<br />
	SCOPE_TABLE::ScopeRecord[2].BeginAddress = RVA_L11;                 // 第二个 __try<br />
	SCOPE_TABLE::ScopeRecord[2].EndAddress = RVA_L19;<br />
	SCOPE_TABLE::ScopeRecord[2].HandlerAddress = RVA_L20_EXCEPT_FILTER;<br />
	SCOPE_TABLE::ScopeRecord[2].JumpTarget = RVA_L21; <br />
<br />
	SCOPE_TABLE::ScopeRecord[3].BeginAddress = RVA_L25;                 // 第四个 __try<br />
	SCOPE_TABLE::ScopeRecord[3].EndAddress = RVA_L26;<br />
	SCOPE_TABLE::ScopeRecord[3].HandlerAddress = RVA_L28;<br />
	SCOPE_TABLE::ScopeRecord[3].JumpTarget = 0; <br />
<br />
	我们再模拟一下 nt!__C_specific_handler 是如何遍历 SCOPE_TABLE 的：<br />
	1. 首先通过传入参数中的 pDispatcherContext-&gt;ControlPc 和 pDispatcherContext-&gt;ImageBase 计算出异常触发点的 RVA（简称 E_RVA）。参见 fffff800`008a430d 处的指令。<br />
	2. 通过 pDispatcherContext-&gt;ScopeIndex 确认是否需要遍历。如果需要遍历，则从它指定的 ScopeRecord 开始遍历。pDispatcherContext-&gt;ScopeIndex 一般都为0，只有返回 ExceptionCollidedUnwind 时，RtlDispatchException 才可能将它设置为其他值。<br />
	3. 通过比较 E_RVA 和 ScopeRecord[?].BeginAddress、ScopeRecord[?].EndAddress 来找到正确的处理函数，<br />
		首先 ScopeRecord[0] 范围不匹配，遍历下一个，<br />
		然后 ScopeRecord[1]，发现范围匹配，并且是 __try/__except 组合。于是调用 ScopeRecord[1].HandlerAddress，假设它返回的是 EXCEPTION_CONTINUE_SEARCH，那么继续遍历下一个，<br />
		这次是 ScopeRecord[2]，发现范围匹配，并且是 __try/__except 组合。于是调用 ScopeRecord[2].HandlerAddress，假设它返回的是 EXCEPTION_EXECUTE_HANDLER，那么说明找到了解决方案。<br />
	4. 调用 RtlUnwindEx，把 ScopeRecord[2].JumpTarget 对应的绝对地址作为 TargetIp 参数传给它。RtlUnwindEx 全局展开完毕后执行 TargetIp。<br />
<br />
	到这里，异常分发就大致讲述完毕。接下来是关于展开和解决的内容。<br />
<br />
<br />
	<span style="font-weight: bold;">三、展开、解决</span><br />
<br />
	x64 中展开使用的函数有 RtlVirtualUnwind、RtlUnwindEx 和 RtlpExecuteHandlerForUnwind。其中 RtlVirtualUnwind 已经讲了，我们来看看余下的两个。<br />
<br />
	首先是 RtlUnwindEx，原型如下：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlUnwindEx (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID TargetFrame OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID TargetIp OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID ReturnValue,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PCONTEXT OriginalContext,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	参数分别是：<br />
		TargetFrame —— 目标帧，即最后一个需要展开的帧。<br />
		TargetIp —— 前面有讲过，它就是 ScopeRecord[?].JumpTarget 代表的地址，即 EXCEPT_HANDLER。<br />
		ExceptionRecord —— 异常信息。<br />
		ReturnValue —— 传递给 TargetIp 的返回值，分析过程中没发现它有什么用处。<br />
		OriginalContext —— 虽然被声明为 IN，但是实际上 RtlUnwindEx 并没有使用它内部的数据，<br />
		HistoryTable —— 用于加速查找 RUNTIME_FUNCTION。<br />
<br />
	主要功能是：<br />
		从自身开始展开，到 TargetFrame 停止。然后跳转到 TargetIp 继续执行。<br />
	流程：<br />
		1. 申请一个类型为 CONTEXT 的局部变量 l_Context，调用 RtlCaptureContext 将当前自身的环境复制到 l_Context。<br />
		2. 通过 RtlVirtualUnwind 对 l_Context 进行模拟展开，推动遍历。对每个遍历到的 UNWIND_INFO，检查 UNWIND_INFO::Flags 是否包含 UNW_FLAG_UHANDLER。如果包含，则调用 UNWIND_INFO::ExceptionHandler 进行局部展开。否则继续遍历下一个。<br />
		   循环本步骤，直到展开到 TargetFrame，即到达解决异常的 EXCEPT_HANDLER 所在的函数（简称为 ExceptionHandlerFunc）了。<br />
		3. 这时 l_Context 内已经是从 RtlUnwindEx 完整展开到 EXCEPT_HANDLER 的环境了。即此时 l_Context 已经是 ExceptionHandlerFunc 的执行环境了。<br />
		   调用 RtlRestoreContext，用 l_Context 替换当前线程的执行环境，于是就跳转到 EXCEPT_HANDLER 继续执行。<br />
	这样就完美的从触发异常的环境跳到了新的环境中。<br />
<br />
	这个过程有点类似这种手法：<br />
		1. 将某台机器的系统 ghost 到一个 bak.gho 文件。<br />
		2. 把 bak.gho 恢复到一台临时机器，然后对这台临时机器做一些调整。调整完毕后制作一个临时机器的 bak_mod.gho。<br />
		3. 将 bak_mod.gho 恢复到原来那台机器。<br />
<br />
	这个流程很重要，我手绘了一副图帮助理解，<br />
	<br />
	伪码：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus(STATUS_INVALID_PARAMETER);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
<br />
	图：<br />
	1. 异常解决流程，从 EXCEPT_POINT 到 RtlUnwindEx，途中已经找到能够解决该异常的 EXCEPT_HANDLER 了（以参数 TargetIp 表示），当前线程状态为 ThreadContext<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+</code></div></div>
	<br />
	2. RtlUnwindEx 将当前自身状态复制到 ThreadContext_Copy 中<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext_Copy &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+</code></div></div>
	<br />
	3. 用 ThreadContext_Copy 进行展开，一直展开到异常触发点停止。<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+<br />
| .....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|调 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlRaiseStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^展 |<br />
| RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|用 |-&gt; ThreadContext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlDispatchException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|开 |-&gt; ThreadContext_Copy &amp;<br />
| RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlpExecuteHandlerForException&nbsp;&nbsp;&nbsp;&nbsp;|方 |&nbsp;&nbsp; TargetIp = ExceptionHandler<br />
| __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | __C_specific_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|向 |<br />
| RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---------------------------------------+</code></div></div>
	<br />
	4. 将 ThreadContext_Copy.Rip 设置为 TargetIp，以 ThreadContext_Copy 为参数调用 RtlpRestoreContext。跳转到 TargetIp 继续执行。<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>+---------------------------------------+<br />
| ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
| EXCEPT_HANDLER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|-&gt; ThreadContext (ThreadContext.Rip = TargetIp)<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+---------------------------------------+</code></div></div>
	这样就完成了展开和执行 EXCEPT_HANDLER 的工作。<br />
<br />
	RtlpExecuteHandlerForUnwind 没有什么改变，原型依旧：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_DISPOSITION<br />
&nbsp;&nbsp;&nbsp;&nbsp;RtlpExecuteHandlerForUnwind (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PEXCEPTION_RECORD ExceptionRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN PVOID EstablisherFrame,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PCONTEXT ContextRecord,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN OUT PVOID DispatcherContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div>
	它会注册一个异常处理函数 RtlpUnwindHandle，当触发新异常时 RtlpUnwindHandler 会返回 ExceptionCollidedUnwind。关于 ExceptionCollidedUnwind，我们后面还会详细讲述。<br />
	RtlpExecuteHandlerForUnwind 的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:199。<br />
	RtlpUnwindHandle 的实现源码位于 &#36;\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:136。<br />
<br />
	到这里，我们讲完了展开的逻辑。接下来我们要讲述两个比较特殊的返回值： ExceptionNestedException 和 ExceptionCollidedUnwind。<br />
<br />
<br />
	四、ExceptionNestedException 和 ExceptionCollidedUnwind<br />
<br />
	之所以专门讲述这两个返回值，是因为在分析过程中，我感觉常规情况的 SEH 流程理解起来并不困难，难理解的是这两种不一般的情况。它们不一般之处在于：在处理异常的过程中又触发了新的异常。<br />
	先来讲一下这两个返回值的含义：<br />
	ExceptionNestedException —— 在异常分发过程中触发新的异常，比如执行 EXCEPT_FILTER 时触发异常。<br />
	ExceptionCollidedUnwind —— 在展开过程中触发新的异常，比如执行 FINALLY_HANDLER 时触发异常。<br />
<br />
	首先来讲讲 ExceptionNestedException，以如下伪码为例：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(ExRaiseStatus(), EXCEPTION_CONTINUE_SEARCH) // EXCEPT_FILTER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ // EXCEPT_HANDLER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;10 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 <br />
&nbsp;&nbsp;&nbsp;&nbsp;12 VOID Caller()<br />
&nbsp;&nbsp;&nbsp;&nbsp;13 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp; __try<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SehTest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp; __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp; { // EXCEPT_HANDLER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;21 }</code></div></div>
	上述代码会两次触发异常，第一次是行5的 ExRaiseStatus，第二次是行7的 ExRaiseStatus。为了方便区分，我将它们分别标记为 EXCEPT_POINT#1、EXCEPT_POINT#2。<br />
	我们来看一下这两个异常的处理流程：<br />
<br />
	1. ExRaiseStatus#1 会创建保存 EXCEPT_POINT#1 触发时的状态 Context#1，并构建一个 EXCEPTION_RECORD，然后将他们作为参数来调用 RtlDispatchException#1。（注：这种方式的的触发点是 ExRaiseStatus 内部，而非 SehTest 的第5行。即Context#1 记录的异常触发点是 ExRaiseStatus#1 内部）<br />
<br />
	2. RtlDispatchException#1 根据 Context#1 首先找到 EXCEPT_POINT#1 所在函数 ExRaiseStatus#1 的 UNWIND_INFO，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
<br />
	3. RtlDispatchException#1 遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionHandler，即 __C_specific_handler&#36;2。__C_specific_handler&#36;2 遍历 SehTest 的 SCOPE_TABLE，发现唯一的一个 ScopeRecord。于是执行 ScopeRecord[0].HandlerAddress，即行7的 SehTest::EXCEPT_FILTER_1#1。此时的调用栈如下（竖线后的内容为函数的 UNWIND_INFO::Flags 和 UNWIND_INFO::ExceptionHandler，其中 Flags 缩写为 E、U、N）：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(6)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(7)&nbsp;&nbsp;EXCEPT_FILTER_1#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N</code></div></div>
<br />
	4. EXCEPT_FILTER#1 触发 EXCEPT_POINT#2。同步骤1类似，ExRaiseStatus 会调用 RtlDispatchException#2，这个过程中同样会创建保存 EXCEPT_POINT#2 的状态，我们称之为 Context#2。<br />
<br />
	5. RtlDispatchException#2 根据 Context#2 找到了 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
<br />
	6. RtlDispatchException#2 遍历到 EXCEPT_FILTER_1#1，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。（注：EXCEPT_FILTER 虽然代码形式上从属于 SehTest 函数，但实际上它是一个单独的函数，有自己的 UNWIND_INFO，跟 SEH 的 UNWIND_INFO 并不是同一个）<br />
<br />
	7. RtlDispatchException#2 遍历到 __C_specific_handler&#36;2、RltpExecuteHandlerForException#1、RtlDispatchException#1、E&#8203;xRaiseStatus#1，这些函数要么被标记为 UNW_FLAG_NHANDLER，要么 UNWIND_INFO::ExceptionHandler 返回 ExcetpionNestedException，结果都是继续遍历，所以不再一一讲述。继续遍历下一个。<br />
<br />
	8. RtlDispatchException#2 遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionRoutine，即 __C_specific_handler&#36;2，发现范围匹配，于是调用 EXCEPT_FILTER_1#1，于是又触发异常，这次是 #3 异常。此时的调用栈如下：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(6)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(7)&nbsp;&nbsp;EXCEPT_FILTER_1#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(8)&nbsp;&nbsp;ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(9)&nbsp;&nbsp;RtlDispatchException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(10) RtlpExecuteHandlerForException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpExceptionHandler&#36;10<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(11) __C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(12) EXCEPT_FILTER_1#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(13) ExRaiseStatus#3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N</code></div></div>
	9. #3 异常的处理流程同 #2 的处理流程类似，也会再遍历到 __C_specific_handler&#36;2，也会再调用 EXCEPT_FILTER_1，于是会触发 #4 异常、#5 异常等等。最终内核栈溢出，BSOD。<br />
<br />
	以上就是 ExceptionNestedException 的产生以及处理的流程。过程中还有一些细节操作，为了描述简洁，我没有在上述过程中一一讲述。<br />
<br />
<br />
	再来看看 ExceptionCollidedUnwind。它比 ExceptionNestedException 更复杂一些，我们以如下伪码为例，<br />
		<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ // FINALLY_HANDLER_1<br />
&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;11 }<br />
&nbsp;&nbsp;&nbsp;&nbsp;12 <br />
&nbsp;&nbsp;&nbsp;&nbsp;13 VOID Caller()<br />
&nbsp;&nbsp;&nbsp;&nbsp;14 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp; __try<br />
&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SehTest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp; __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp; { // EXCEPT_HANDLER_2<br />
&nbsp;&nbsp;&nbsp;&nbsp;21&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;22 }</code></div></div>
	伪码中也有两处触发异常的地方，第一次在行5，第二次在行9。也分别标记为 EXCEPT_POINT#1 和 EXCEPT_POINT#2。处理流程：<br />
	<br />
	1. ExRaiseStatus#1 创建保存 EXCEPT_POINT#1 的状态 Context#1，并构建一个 EXCEPTION_RECORD，然后将他们作为参数来调用 RtlDispatchException#1。<br />
<br />
	2. RtlDispatchException#1 根据 Context#1 开始遍历：<br />
		首先遍历到 EXCEPT_POINT#1 所在函数 ExRaiseStatus，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是遍历下一个。<br />
		然后遍历到 SehTest，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_UHANDLER，于是继续遍历下一个。<br />
		然后遍历到 Caller，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER，于是调用其 UNWIND_INFO::ExceptionRoutine 即 __C_specific_handler。__C_specific_handler 发现可以处理该异常，于是以 EXCEPT_HANDLER_2 为 TargetIp 参数调用 RtlUnwindEx。<br />
<br />
	3. RtlUnwindEx 从自身开始展开，展开到 SehTest，执行 FINALLY_HANDLER_1 时触发新异常。此时调用栈为：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | U&nbsp;&nbsp;&amp; __C_specific_handler&#36;2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler&#36;5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)&nbsp;&nbsp;__C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)&nbsp;&nbsp;RtlUnwindEx#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)&nbsp;&nbsp;RtlpExecuteHandlerForUnwind#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpUnwindHandler&#36;8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (9)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (10) FINALLY_HANDLER_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (11) ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N</code></div></div>
	   需要说明的是，调用栈(7) RtlUnwindEx 创建并初始化了一个 DISPATCHER_CONTEXT 变量（后续称之为 pDispatcherContextForUnwind），并作为参数传递给调用栈(8) RltpExecuteHandlerForUnwind，后者在调用(9) __C_specific_handler&#36;2 之前将 pDispatcherContextForUnwind 保存在自己的栈中。此时 pDispatcherContextForUnwind 的内容表示的是调用栈(2) SehTest 的情况。后续步骤会用到这个 pDispatcherContextForUnwind。<br />
	<br />
	4. (11) ExRaiseStatus#2 将 EXCEPT_POINT#2 触发时的状态保存到 Context#2，然后调用 RtlDispatchException#2 进行 EXCEPT_POINT#2 的分发。<br />
	<br />
	5. RtlDispatchException#2 根据 Context#2 开始遍历，<br />
		首先遍历到 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是遍历下一个。<br />
		然后遍历到 FINALLY_HANDLER_1（同前面提到的 EXCEPT_FILTER 一样，FINALLY_HANDLER 实际上也是一个单独的函数，有自己的 RUNTIME_FUNCTION 和 UNWIND_INFO），发现其 UNWIND_INFO::Flags 为	UNW_FLAG_NHANDLER，于是遍历下一个。<br />
	   	然后遍历到(9) __C_specific_handler&#36;2，发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER，于是继续遍历。<br />
		然后遍历到(8) RtlpExecuteHandlerForUnwind#1，发现其 UNWIND_INFO::Flags 包含 UNW_FLAG_EHANDLER。于是调用其 UNWIND_INFO::ExceptionRoutine 即 RtlpUnwindHandler&#36;8。RtlpUnwindHandler&#36;8 会取出步骤3中所提到的 pDispatcherContextForUnwind，将其内容拷贝到自己的传出参数（参考 RtlpUnwindHandler 的函数原型）pDispatcherContext 中，然后返回 ExceptionCollidedUnwind。<br />
<br />
	6. RtlDispatchException#2 收到 ExceptionCollidedUnwind 后，从传回来的 pDispatchContext 中取出诸如 ControlPc、EstablisherFrame 等值（如步骤3所说，此时这些值反应的是(2) SehTest 的状态），用这些值来继续遍历。<br />
		首先遍历到(2) SehTest，调用 RtlpExecuteHandlerForException#2，进而调用 __C_specific_handler&#36;2，但是发现 pDispatcherContext-&gt;ScopeIndex（步骤(9)中在调用(10) FINALLY_HANDLER_1 之前+1了，参考 __C_specific_handler 反汇编码）等于 pDispatcherContext-&gt;HandlerData-&gt;Count。于是继续遍历。<br />
		然后遍历到(1) Caller，调用 RtlpExecuteHandlerForException#2，进而调用 __C_specific_handler&#36;1，发现它可以处理 #2 异常，于是以 EXCEPT_HANDLER#2 为 TargetIp 参数调用 RtlUnwindEx。此时调用栈如下：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| E&nbsp;&nbsp;&amp; __C_specific_handler&#36;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;&nbsp;SehTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | U&nbsp;&nbsp;&amp; __C_specific_handler&#36;2，但没有 EXCEPT_HANDLER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;&nbsp;ExRaiseStatus#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)&nbsp;&nbsp;RtlDispatchException#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)&nbsp;&nbsp;RtlpExecuteHandlerForException#1&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler&#36;6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)&nbsp;&nbsp;__C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)&nbsp;&nbsp;RtlUnwindEx#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)&nbsp;&nbsp;RtlpExecuteHandlerForUnwind#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | EU &amp; RtlpUnwindHandler&#36;8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (9)&nbsp;&nbsp;__C_specific_handler&#36;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (10) FINALLY_HANDLER#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (11) ExRaiseStatus#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (12) RtlDispatchException#2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (13) RtlpExecuteHandlerForException#2&nbsp;&nbsp;&nbsp;&nbsp;| EU &amp; RtlpExceptionHandler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (14) __C_specific_handler&#36;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| N<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (15) RtlUnwindEx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | N</code></div></div>
	7. (17) RtlUnwindEx 展开完毕后，通过 RtlRestoreContext 跳转到 EXCEPT_HANDLER#2 继续执行。<br />
<br />
	在上述过程中，我们可以发现，遍历过程中 RtlDispatchException 等系统函数被频繁遍历到。于是就有了前面提到的全局展开历史表 RtlpUnwindHistoryTable，这个表中存放着 RtlDispatchException、RtlUnwindEx 等函数的 RUNTIME_FUNCTION 和 ImageBase 信息，这样就不用每次都去解析 PE+ 中的 ExceptionDirectory，实现了加速。<br />
<br />
<br />
	到这里，我们就讲完了 x64 SEH 的实现。可以发现，x64 和 x86 的 SEH 思想或者说框架是一样的：<br />
	1. RtlDispatchException 和 RtlUnwindEx 都对异常注册信息进行遍历。前者是为了分发异常而遍历，后者是为了展开而遍历。<br />
	2. MSC 提供的异常处理函数按照“异常解决”和“展开”两个分支，对 SCOPE_TABLE/scopetable 进行遍历。前者是为了找到 EXCEPT_FILTER &amp; EXCEPT_HANDLER，后者是为了找到 FINALLY_HANDLER。<br />
	3. RtlDispatchException 和 RtlUnwindEx 借助 MSC 提供的异常处理函数这个桥梁，配合处理异常。<br />
	主要的改变有两点：<br />
	1. RtlDispatchException 和 RtlUnwindEx 通过调用 RtlVirtualUnwind 推动遍历。<br />
	2. 所有的非叶函数都参与到 SEH，尽管大部分的函数都没有使用到 SEH。<br />
<br />
	以上我们主要讲述的是 x64 SEH 的内部实现。对于使用者，也有一个好消息，我们来看看，<br />
	<br />
	C 代码：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExRaiseStatus(STATUS_INVALID_PARAMETER);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
	反汇编码：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; uf passthrough!SehTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest:<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100020 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,38h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100024 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C000000Dh<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100029 call&nbsp;&nbsp;&nbsp;&nbsp;qword ptr [PassThrough!_imp_ExRaiseStatus (fffffadf`f1101050)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110002f lea&nbsp;&nbsp;&nbsp;&nbsp; r8,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100500)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100036 mov&nbsp;&nbsp;&nbsp;&nbsp; edx,39h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110003b lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100540)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100042 call&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!DbgPrint (fffffadf`f11004a6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100047 jmp&nbsp;&nbsp;&nbsp;&nbsp; PassThrough!SehTest+0x42 (fffffadf`f1100062)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x42:<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100062 lea&nbsp;&nbsp;&nbsp;&nbsp; r8,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100500)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100069 mov&nbsp;&nbsp;&nbsp;&nbsp; edx,42h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110006e lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[PassThrough! ?? ::FNODOBFM::`string' (fffffadf`f1100570)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f1100075 call&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!DbgPrint (fffffadf`f11004a6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110007a add&nbsp;&nbsp;&nbsp;&nbsp; rsp,38h<br />
&nbsp;&nbsp;&nbsp;&nbsp;fffffadf`f110007e ret</code></div></div>
	我们发现 SehTest 内部完全没有任何 SEH 的踪迹，不像 x86 那样会有创建、销毁 EXCEPTION_REGISTRATION_RECORD 和调整 EXCEPTION_REGISTRATION_RECORD::trylevel 等操作。<br />
	这样的好处就是使用者无需再担心性能损耗，可以放心大胆的使用 SEH 机制了。<br />
<br />
<br />
	附录一<br />
<br />
	为了方便自己分析，我写了一个简单的 windbg 扩展，提供了几个 x64 seh 常用功能：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;!boxr.unwindinfo&nbsp;&nbsp;&nbsp;&nbsp;module-name&nbsp;&nbsp;&nbsp;&nbsp;unwindinfo_addr<br />
&nbsp;&nbsp;&nbsp;&nbsp;功能：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用于查询指定 UNWIND_INFO 结构的详细信息。<br />
&nbsp;&nbsp;&nbsp;&nbsp;参数说明：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module-name —— 待查询的 UNWIND_INFO 结构对应函数的模块名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unwindinfo_addr —— UNWIND_INFO 结构的绝对地址</code></div></div>
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;!boxr.rtfn&nbsp;&nbsp;&nbsp;&nbsp;option&nbsp;&nbsp;&nbsp;&nbsp;module&nbsp;&nbsp;&nbsp;&nbsp;runtimefunction_addr<br />
&nbsp;&nbsp;&nbsp;&nbsp;功能：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用于查询指定 RUNTIME_FUNCTION 结构的详细信息。（rtfn 表示 RunTime_FunctioN）<br />
&nbsp;&nbsp;&nbsp;&nbsp;参数说明：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option —— 参数选项，目前支持两种：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/a 表示 module 参数为模块基地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/n 表示 module 参数为模块名称<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module —— RUNTIME_FUNCTION 结构对应函数所在的模块，具体形式根据 option 而定。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;runtimefunction_addr —— 需要查询的 RUNTIME_FUNCTION 结构体的绝对地址。支持 @rax 操作方式，但不支持复杂的组合，比如 @rax+8。</code></div></div>
	使用的方法是：用 .extpath+ 命令将 boxr.dll 所在的目录添加到 windbg 的搜索路径中，然后就可以使用了。需要卸载时就 .unload。<br />
<br />
	简单说明一下这两个命令。<br />
<br />
	比如我们要查看下面这个函数的 UNWIND_INFO 信息：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;VOID SehTest()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollidedUnwind();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __try &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__finally<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __finally &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("%u [%s] __except &#92;n", __LINE__, __FILE__);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</code></div></div>
	<br />
	操作步骤：<br />
	1. 使用 .fnent 命令获得 SehTest 的基本信息，<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; .fnent passthrough!SehTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Debugger function entry 00000000`00758210 for:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadf`f135d080)&nbsp;&nbsp; PassThrough!SehTest&nbsp;&nbsp; |&nbsp;&nbsp;(fffffadf`f135d180)&nbsp;&nbsp; PassThrough!LeafTest<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exact matches:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest (void)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 00000000`00001080<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 00000000`00001175<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnwindInfoAddress = 00000000`000026b8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unwind info at fffffadf`f135e6b8, 10 bytes<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version 1, flags 3, prolog 4, codes 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler routine: PassThrough!_C_specific_handler (fffffadf`f135d5de), data 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00: offs 4, unwind op 2, op info 4&nbsp;&nbsp;&nbsp;&nbsp;UWOP_ALLOC_SMALL.</code></div></div>
	2. 使用 !boxr.unwindinfo 查询详细信息，<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; !boxr.unwindinfo passthrough fffffadf`f135e6b8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_UNWIND_INFO for fffffadff135e6b8 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EU<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionRoutine:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!_C_specific_handler (fffffadf`f135d5de)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeTable:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Count: 6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff135e6c8)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x4 (fffffadf`f135d084)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x1e (fffffadf`f135d09e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest&#36;filt&#36;0 (fffffadf`f135d8a0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x1e (fffffadf`f135d09e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[省略中间3个 ScopeRecord 成员]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[5]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff135e718)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0x8b (fffffadf`f135d10b)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0xd7 (fffffadf`f135d157)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest&#36;filt&#36;5 (fffffadf`f135d960)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!SehTest+0xd7 (fffffadf`f135d157)</code></div></div>
	!boxr.rtfn 的用法也类似，比如：<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kd&gt; !box.rtfn /n passThrough @rax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_RUNTIME_FUNCTION for fffffadff1113000 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind (fffffadf`f1110020)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x38 (fffffadf`f1110058)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnwindData:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffffadff1111688<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_UNWIND_INFO for fffffadff1111688 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;U<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionRoutine:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!_C_specific_handler (fffffadf`f11104ee)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeTable:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Count: 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScopeRecord[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(fffffadff1111698)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeginAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x4 (fffffadf`f1110024)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EndAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind+0x10 (fffffadf`f1110030)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAddress: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassThrough!CollidedUnwind&#36;fin&#36;0 (fffffadf`f1110750)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JumpTarget: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0</code></div></div>
	需要说明的是，我写这个扩展的目的仅仅是为了分析 x64 SEH 过程中能轻松的查看相关数据结构的详细信息，所以并没有在这个扩展上花很多时间。其代码是从 MS 例子代码的基础上增加了我需要的功能。应该有一些 BUG，但是对我来说不重要，已经满足我的需要了。源码也放在附件里，方便分析的朋友根据自己的需要进行修改。<br />
	另外有一个疑问：我编译的 x64 wrk1.2 内核无法对 .c代码进行源码调试，对 .asm 代码倒是可以，这是为什么？我看了一下编译选项，没看出什么猫腻。有经验的朋友分享一下吧，感谢 :-)<br />
<br />
<br />
	<span style="font-weight: bold;">附录二 RtlUnwindEx 的反汇编代码和注释</span><br />
<br />
	由于无法源码调试，只好把它反汇编出来加上注释……<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>VOID<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlUnwindEx (<br />
/* rcx&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID pEstablisherFrame OPTIONAL,<br />
/* rdx&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID pJumpTargetIp OPTIONAL,<br />
/* r8&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; IN PEXCEPTION_RECORD pExceptionRecord OPTIONAL,<br />
/* r9&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; IN PVOID ReturnValue,<br />
/* rsp+28 */&nbsp;&nbsp;&nbsp;&nbsp; IN PCONTEXT pOriginalContext,<br />
/* rsp+30 */&nbsp;&nbsp;&nbsp;&nbsp; IN PUNWIND_HISTORY_TABLE pHistoryTable OPTIONAL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kd&gt; uf nt!RtlUnwindEx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e70 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],r9<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e75 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+18h],r8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e7a mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+10h],rdx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e7f mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rsp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e82 sub&nbsp;&nbsp;&nbsp;&nbsp; rsp,678h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e89 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-8],rbx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e8d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-10h],rbp<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e91 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-18h],rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e95 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+6A0h] ; rsi = pOriginalContext<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891e9d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-20h],rdi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea1 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-28h],r12<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea5 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rax-40h],r15<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ea9 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,rcx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eac mov&nbsp;&nbsp;&nbsp;&nbsp; r15,rdx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eaf lea&nbsp;&nbsp;&nbsp;&nbsp; rdx,[rsp+40h] ; rsp+40 为 l_HighLimit<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eb4 lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+50h] ; rsp+50 为 l_LowLimit<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891eb9 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,r8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ebc mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ebf lea&nbsp;&nbsp;&nbsp;&nbsp; r12,[rax-518h] ; r12 = &amp;l_Context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ec6 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpGetStackLimits (fffff800`00890da0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ecb mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rsi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ece call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlCaptureContext (fffff800`008bd150)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ed3 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891edb test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ede je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x74 (fffff800`00891ee4)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x70:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee0 mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [rax+4],1 ; pHistoryTable-&gt;Search = UNWIND_HISTORY_TABLE_GLOBAL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x74:<br />
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee4 xor&nbsp;&nbsp;&nbsp;&nbsp; ecx,ecx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891ee6 test&nbsp;&nbsp;&nbsp;&nbsp;rbx,rbx ; 判断 pExceptionRecord 是否为 NULL<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ee9 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xbc (fffff800`00891f2c)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x7b:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; pExceptionRecord 等于 NULL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891eeb mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsi+0F8h]&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891ef2 lea&nbsp;&nbsp;&nbsp;&nbsp; rbx,[rsp+0C0h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rbx = &amp;l_ExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891efa mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0C0h],0C0000027h ; l_ExceptionRecord.ExceptionCode = STATUS_UNWIND (0xC0000027)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f05 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0D0h],rax&nbsp;&nbsp;; l_ExceptionRecord.ExceptionAddress = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f0d mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h]&nbsp;&nbsp;; rax = pHistoryTable<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f15 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+690h],rbx&nbsp;&nbsp;; [r8-home] = &amp;l_ExceptionRecord ????<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f1d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0C8h],rcx&nbsp;&nbsp;; l_ExceptionRecord.ExceptionRecord = NULL<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f25 mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0D8h],ecx&nbsp;&nbsp;; l_ExceptionRecord.NumberParameters = 0<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0xbc:<br />
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`00891f2c mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h]&nbsp;&nbsp;; rbx = &amp;[rcx-home]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f34 mov&nbsp;&nbsp;&nbsp;&nbsp; esi,2 ; l_ExceptionFlags(esi) = EXCEPTION_UNWINDING (2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f39 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,6 ; ecx = EXCEPTION_EXIT_UNWIND (6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f3e test&nbsp;&nbsp;&nbsp;&nbsp;rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f41 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+648h],r13 ; 保存 r13 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f49 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+640h],r14 ; 保存 r14<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f51 cmove&nbsp;&nbsp; esi,ecx ; if (NULL == pEstablisherFrame) { l_ExceptionFlags = EXCEPTION_EXIT_UNWIND (6) }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f54 xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f58 xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00891f5c xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xf0:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt; fffff800`00891f60 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rdi+0F8h] ; r13 = pOriginalContext-&gt;Rip<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f67 lea&nbsp;&nbsp;&nbsp;&nbsp; rdx,[rsp+60h] ; rdx = &amp;l_pImageBase<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f6c mov&nbsp;&nbsp;&nbsp;&nbsp; r8,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pHistoryTable<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f6f mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f72 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+68h],r13<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f77 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlLookupFunctionEntry (fffff800`00890e60)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_pFunctionEntry = RtlLookupFunctionEntry(pOriginalContext-&gt;Rip, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;l_pImageBase,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pHistoryTable)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f7c test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax ; 判断 l_pFunctionEntry (eax) 是否为 NULL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891f7f mov&nbsp;&nbsp;&nbsp;&nbsp; r14,rax ; r14 = l_pFunctionEntry<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f82 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3ab (fffff800`0089221b)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x118:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f88 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rdi ; rdx = pOriginalContext<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f8b mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r12 ; rcx = &amp;l_Context<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f8e call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlpCopyContext(&amp;l_Context, pOriginalContext)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f93 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+60h] ; rdx = l_pImageBase<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891f98 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+38h],0&nbsp;&nbsp; ; _ARG_8 = 0<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fa1 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+680h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;[rcx-home]，这里被用作局部变量 l_pEstablisherFrame 空间<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fa9 mov&nbsp;&nbsp;&nbsp;&nbsp; r9,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = l_pFunctionEntry<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fac mov&nbsp;&nbsp;&nbsp;&nbsp; r8,r13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8 = pOriginalContext-&gt;Rip<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891faf mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+30h],rax ; _ARG7 = &amp;l_pEstablisherFrame<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fb4 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+58h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = &amp;l_pHandlerData<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fb9 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ecx = UNW_FLAG_UHANDLER (2)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fbe mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = &amp;l_pHandlerData<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fc3 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],r12 ; _ARG_5 = &amp;l_Context<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fc8 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlVirtualUnwind (fffff800`00891380)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_pExceptionRoutine = RtlVirtualUnwind(UNW_FLAG_UHANDLER,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_pImageBase,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pOriginalContext-&gt;Rip,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_pFunctionEntry,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_Context,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pHandlerData,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pEstablisherFrame,<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL);<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fcd mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fd5 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rcx = l_pExceptionRoutine<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fd8 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+48h],rax<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fdd test&nbsp;&nbsp;&nbsp;&nbsp;bl,7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 检查 l_pEstablisherFrame 是否对齐<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891fe0 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x176:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891fe6 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+50h]&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_LowLimit<br />
..&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891feb jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x184 (fffff800`00891ff4)<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x17d:<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00891fed cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+40h]&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_HighLimit<br />
...&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ff2 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x1d3 (fffff800`00892043)<br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x184:<br />
....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ; 检查 l_pEstablisherFrame 是否合法<br />
..&gt;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ff4 mov&nbsp;&nbsp;&nbsp;&nbsp; cl,byte ptr gs:[20DEh]&nbsp;&nbsp; ; cl = _KPCR-&gt;DpcRoutineActive<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ffc test&nbsp;&nbsp;&nbsp;&nbsp;cl,cl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 判断当前是否在执行 DPC<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00891ffe jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1) ; 如果是在执行 DPC 则失败？??<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x194:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892004 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892009 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl-&gt;Previous.StackBase<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089200d test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 判断 l_KernelStackCtrl-&gt;Previous.StackBase 是否为 NULL<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892010 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1a6:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892016 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rcx-20h]&nbsp;&nbsp;; rdx = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089201a mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892022 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892025 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1bb:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089202b cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackBase<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089202e jae&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1c4:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892034 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892039 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089203e mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl-&gt;Previous.StackBase<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1d3:<br />
.. &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892043 test&nbsp;&nbsp;&nbsp;&nbsp;rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL<br />
.. &lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892046 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x1e1 (fffff800`00892051)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1d8:<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892048 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame<br />
.&lt; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`0089204b jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x431 (fffff800`008922a1)<br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . <br />
.. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . nt!RtlUnwindEx+0x1e1:<br />
.. &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . fffff800`00892051 test&nbsp;&nbsp;&nbsp;&nbsp;rcx,rcx ; 判断 l_pExceptionRoutine 是否为 NULL<br />
..&nbsp;&nbsp;&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892054 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x39b (fffff800`0089220b)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x1ea:<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089205a mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+58h] ; r13 = l_pHandlerData<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089205f mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+90h],r15 ; [rsp+90] = pJumpTargetIp<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892067 xor&nbsp;&nbsp;&nbsp;&nbsp; r15d,r15d<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089206a xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`0089206d xchg&nbsp;&nbsp;&nbsp;&nbsp;ax,ax<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x200:<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&gt; . fffff800`00892070 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . . fffff800`00892073 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x208 (fffff800`00892078)<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x205:<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . fffff800`00892075 or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,20h ; l_ExceptionFlags |= EXCEPTION_TARGET_UNWIND (0x20)<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x208:<br />
..&nbsp;&nbsp;.&gt;&nbsp;&nbsp; . . fffff800`00892078 mov&nbsp;&nbsp;&nbsp;&nbsp; r10,qword ptr [rsp+690h] ; r10 = &amp;l_ExceptionRecord<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892080 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+698h] ; rax = ReturnValue<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892088 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0A0h],rcx ; l_DispatcherContext.LanguageHandler = l_pExceptionRoutine<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892090 mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [r10+4],esi&nbsp;&nbsp;&nbsp;&nbsp;; l_ExceptionRecord.ExceptionFlags = l_ExceptionFlags<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892094 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+78h],rax&nbsp;&nbsp;; pOriginalContext-&gt;Rax = ReturnValue<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`00892098 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+68h]&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`0089209d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+70h],rax&nbsp;&nbsp;; l_DispatcherContext.ControlPc = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920a2 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+60h]&nbsp;&nbsp;; rax = l_pImageBase<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920a7 lea&nbsp;&nbsp;&nbsp;&nbsp; r9,[rsp+70h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r9 = &amp;l_DispatcherContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ac mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+78h],rax&nbsp;&nbsp;; l_DispatcherContext.ImageBase = l_pImageBase<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920b1 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920b9 mov&nbsp;&nbsp;&nbsp;&nbsp; r8,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r8 = pOriginalContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920bc mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rbx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920bf mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,r10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rcx = &amp;l_ExceptionRecord<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920c2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+80h],r14&nbsp;&nbsp; ; l_DispatcherContext.FunctionEntry = l_pFunctionEntry<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ca mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0B0h],rax&nbsp;&nbsp;; l_DispatcherContext.HistoryTable = pHistoryTable<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920d2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+88h],rbx&nbsp;&nbsp; ; l_DispatcherContext.EstablisherFrame = l_pEstablisherFrame<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920da mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+98h],rdi&nbsp;&nbsp; ; l_DispatcherContext.ContextRecord = pOriginalContext<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920e2 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+0A8h],r13&nbsp;&nbsp;; l_DispatcherContext.HandlerData = l_pHandlerData<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920ea mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rsp+0B8h],r15d ; l_DispatcherContext.ScopeIndex = 0<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920f2 and&nbsp;&nbsp;&nbsp;&nbsp; esi,0FFFFFF9Fh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; l_ExceptionFlags &amp;= ~(EXCEPTION_TARGET_UNWIND|EXCEPTION_COLLIDED_UNWIND)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920f5 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpExecuteHandlerForUnwind (fffff800`008bd9d0)<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlpExecuteHandlerForUnwind(&amp;l_ExceptionRecord,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l_pEstablisherFrame,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pOriginalContext,<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;l_DispatcherContext);<br />
..&nbsp;&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;. . fffff800`008920fa dec&nbsp;&nbsp;&nbsp;&nbsp; eax<br />
..&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . . fffff800`008920fc je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x368 (fffff800`008921d8) ; 如果返回 ExceptionContinueSearch 则跳转<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . <br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . nt!RtlUnwindEx+0x292:<br />
..&nbsp;&nbsp;..&nbsp;&nbsp; . . fffff800`00892102 cmp&nbsp;&nbsp;&nbsp;&nbsp; eax,2 ; cmp eax, ExceptionCollidedUnwind (3 - 1)<br />
..&nbsp;&nbsp;..&lt;&nbsp;&nbsp;. . fffff800`00892105 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x426 (fffff800`00892296)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . <br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . nt!RtlUnwindEx+0x29b:<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ; ExceptionCollidedUnwind 的情况<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089210b mov&nbsp;&nbsp;&nbsp;&nbsp; r8,qword ptr [rsp+70h]&nbsp;&nbsp; ; r8 = l_DispatcherContext.ControlPc<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892110 mov&nbsp;&nbsp;&nbsp;&nbsp; r10,qword ptr [rsp+78h]&nbsp;&nbsp;; r10 = l_DispatcherContext.ImageBase<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892115 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rsp+98h]&nbsp;&nbsp;; rdx = l_DispatcherContext.ContextRecord<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089211d mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+6A0h] ; rcx = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892125 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+80h]&nbsp;&nbsp;; r14 = l_DispatcherContext.FunctionEntry<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089212d mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+68h],r8<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892132 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+60h],r10<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892137 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlpCopyContext(pOriginalContext, l_DispatcherContext.ContextRecord);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089213c mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089213f mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,rcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdi = pOriginalContext<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892142 lea&nbsp;&nbsp;&nbsp;&nbsp; rcx,[rsp+160h] ; rcx = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089214a lea&nbsp;&nbsp;&nbsp;&nbsp; r12,[rsp+160h] ; r12 = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892152 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlpCopyContext (fffff800`00891080)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RtlpCopyContext(&amp;l_Context, pOriginalContext);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892157 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+38h],0&nbsp;&nbsp; ; _ARG_8 = NULL<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892160 lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+680h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;l_pEstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892168 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+30h],rax ; _ARG_7 = &amp;l_pEstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089216d lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+58h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = &amp;l_pHandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892172 mov&nbsp;&nbsp;&nbsp;&nbsp; r9,r14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r9 = l_DispatcherContext.FunctionEntry<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892175 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+28h],rax ; _ARG_6 = &amp;l_pHandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089217a lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rsp+160h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892182 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,r10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rdx = l_DispatcherContext.ImageBase<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892185 xor&nbsp;&nbsp;&nbsp;&nbsp; ecx,ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ecx = UNW_FLAG_NHANDLER (0)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892187 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+20h],rax ; _ARG_5 = &amp;l_Context<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`0089218c call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlVirtualUnwind (fffff800`00891380)<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; RtlVirtualUnwind(UNW_FLAG_NHANDLER,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.ImageBase,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.ControlPc,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l_DispatcherContext.FunctionEntry,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_Context,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pHandlerData,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;l_pEstablisherFrame,<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL);<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892191 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+88h]&nbsp;&nbsp; ; rbx = l_DispatcherContext.EstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`00892199 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+0A0h]&nbsp;&nbsp;; rcx = l_DispatcherContext.LanguageHandler<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921a1 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+0A8h]&nbsp;&nbsp;; r13 = l_DispatcherContext.HandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921a9 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+0B0h]&nbsp;&nbsp;; rax = l_DispatcherContext.HistoryTable<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921b1 mov&nbsp;&nbsp;&nbsp;&nbsp; r15d,dword ptr [rsp+0B8h] ; r15d = l_DispatcherContext.ScopeIndex<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921b9 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+680h],rbx&nbsp;&nbsp;; l_pEstablisherFrame = l_DispatcherContext.EstablisherFrame<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921c1 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+48h],rcx&nbsp;&nbsp; ; l_pExceptionRoutine = l_DispatcherContext.LanguageHandler<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921c6 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+58h],r13&nbsp;&nbsp; ; l_pHandlerData = l_DispatcherContext.HandlerData<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921cb mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+6A8h],rax&nbsp;&nbsp;; pHistoryTable = l_DispatcherContext.HistoryTable<br />
..&nbsp;&nbsp;...&nbsp;&nbsp;. . fffff800`008921d3 or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,40h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; l_ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND (40)<br />
..&nbsp;&nbsp;...&lt; . . fffff800`008921d6 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x382 (fffff800`008921f2)<br />
..&nbsp;&nbsp;.... . . <br />
..&nbsp;&nbsp;.... . . nt!RtlUnwindEx+0x368:<br />
..&nbsp;&nbsp;.&gt;.. . . fffff800`008921d8 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame<br />
..&nbsp;&nbsp;. ..&lt;. . fffff800`008921db je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x37d (fffff800`008921ed)<br />
..&nbsp;&nbsp;. .... . <br />
..&nbsp;&nbsp;. .... . nt!RtlUnwindEx+0x36d:<br />
..&nbsp;&nbsp;. .... . fffff800`008921dd mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
..&nbsp;&nbsp;. .... . fffff800`008921e2 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rax = pOriginalContext<br />
..&nbsp;&nbsp;. .... . fffff800`008921e5 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,r12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; rdi = &amp;l_Context<br />
..&nbsp;&nbsp;. .... . fffff800`008921e8 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,rax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; r12 = pOriginalContext<br />
..&nbsp;&nbsp;. .v.. . fffff800`008921eb jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x382 (fffff800`008921f2)<br />
..&nbsp;&nbsp;. .... . <br />
..&nbsp;&nbsp;. .... . nt!RtlUnwindEx+0x37d:<br />
..&nbsp;&nbsp;. ..&gt;. . fffff800`008921ed mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine<br />
..&nbsp;&nbsp;. .. . . <br />
..&nbsp;&nbsp;. .. . . nt!RtlUnwindEx+0x382:<br />
..&nbsp;&nbsp;. .&gt; . . fffff800`008921f2 test&nbsp;&nbsp;&nbsp;&nbsp;sil,40h&nbsp;&nbsp;; test sil, EXCEPTION_COLLIDED_UNWIND (40)<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&lt; . fffff800`008921f6 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x200 (fffff800`00892070)<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. <br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. nt!RtlUnwindEx+0x38c:<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`008921fc mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+68h]&nbsp;&nbsp;; r13 = pOriginalContext-&gt;Rip<br />
..&nbsp;&nbsp;. .&nbsp;&nbsp;&nbsp;&nbsp;. fffff800`00892201 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+688h] ; r15 = pJumpTargetIp<br />
..&nbsp;&nbsp;. .&lt;&nbsp;&nbsp; . fffff800`00892209 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;. ..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;. ..&nbsp;&nbsp; . nt!RtlUnwindEx+0x39b:<br />
..&nbsp;&nbsp;&gt; ..&nbsp;&nbsp; . fffff800`0089220b cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp&nbsp;&nbsp;; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame<br />
..&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`0089220e je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3a0:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892210 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,rdi ; rax = &amp;l_Context<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892213 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,r12 ; rdi = pOriginalContext<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892216 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,rax ; r12 = &amp;l_Context<br />
..&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`00892219 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x3c7 (fffff800`00892237)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
..&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3ab:<br />
&gt;.&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089221b mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rdi+98h]&nbsp;&nbsp;; rcx = pOriginalContext-&gt;Rsp<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892222 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rsp[0]<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892225 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+0F8h],rax ; pOriginalContext-&gt;Rip = pOriginalContext-&gt;Rsp[0]<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089222c lea&nbsp;&nbsp;&nbsp;&nbsp; rax,[rcx+8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rax = pOriginalContext-&gt;Rsp + 8<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`00892230 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+98h],rax&nbsp;&nbsp;; pOriginalContext-&gt;Rsp = pOriginalContext-&gt;Rsp + 8 （跳过返回值）<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; .<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3c7:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&gt;&nbsp;&nbsp; . fffff800`00892237 test&nbsp;&nbsp;&nbsp;&nbsp;bl,7 ; 检查 l_DispatcherContext.EstablisherFrame 是否对齐<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt;&nbsp;&nbsp; . fffff800`0089223a jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . nt!RtlUnwindEx+0x3cc:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;&nbsp; . fffff800`0089223c cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+50h] ; cmp l_DispatcherContext.EstablisherFrame, l_LowLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&lt;&nbsp;&nbsp;. fffff800`00892241 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x3da (fffff800`0089224a)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. nt!RtlUnwindEx+0x3d3:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;. fffff800`00892243 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+40h] ; cmp l_DispatcherContext.EstablisherFrame, l_HighLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;...&lt; . fffff800`00892248 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x414 (fffff800`00892284)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.... . <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.... . nt!RtlUnwindEx+0x3da:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;..&gt;. . fffff800`0089224a mov&nbsp;&nbsp;&nbsp;&nbsp; al,byte ptr gs:[20DEh] ; al = _KPCR-&gt;DpcRoutineActive<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. . . fffff800`00892252 test&nbsp;&nbsp;&nbsp;&nbsp;al,al<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. .&lt;. fffff800`00892254 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x43c (fffff800`008922ac)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x3e6:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892256 mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089225b mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089225f test&nbsp;&nbsp;&nbsp;&nbsp;rax,rax<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. .&lt;. fffff800`00892262 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x43c (fffff800`008922ac)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x3f4:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892264 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,qword ptr [rcx-20h]&nbsp;&nbsp;; rdx = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892268 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892270 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt; ... fffff800`00892273 jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x405:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892275 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.&lt; ... fffff800`00892278 jae&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x444 (fffff800`008922b4)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x40a:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089227a mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl-&gt;Previous.StackLimit<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`0089227f mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl-&gt;Previous.StackBase<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x414:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. &gt;.. fffff800`00892284 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. &lt;.. fffff800`00892287 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x449 (fffff800`008922b9)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... nt!RtlUnwindEx+0x419:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ... fffff800`00892289 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..^ fffff800`00892291 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0xf0 (fffff800`00891f60)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..&nbsp;&nbsp;<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;.. ..&nbsp;&nbsp;nt!RtlUnwindEx+0x426:<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&gt;. ..&nbsp;&nbsp;fffff800`00892296 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C0000026h ; ecx = STATUS_INVALID_DISPOSITION<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`0089229b call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a0 int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;<br />
 .&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;nt!RtlUnwindEx+0x431:<br />
 &gt;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a1 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C0000028h ; ecx = STATUS_BAD_STACK<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922a6 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;fffff800`008922ab int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . ..&nbsp;&nbsp;nt!RtlUnwindEx+0x43c:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&gt;&nbsp;&nbsp;fffff800`008922ac mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . .&nbsp;&nbsp; nt!RtlUnwindEx+0x444:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt; .&nbsp;&nbsp; fffff800`008922b4 cmp&nbsp;&nbsp;&nbsp;&nbsp; rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; fffff800`008922b7 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x479 (fffff800`008922e9)<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; <br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;&nbsp; nt!RtlUnwindEx+0x449:<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp; fffff800`008922b9 mov&nbsp;&nbsp;&nbsp;&nbsp; rax,qword ptr [rsp+698h]&nbsp;&nbsp;; rax = ReturnValue<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922c1 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+690h]&nbsp;&nbsp;; rbx = pExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922c9 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+78h],rax&nbsp;&nbsp; ; pOriginalContext-&gt;Rax, ReturnValue<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922cd cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [rbx],80000029h ; cmp pExceptionRecord-&gt;ExceptionCode, STATUS_UNWIND_CONSOLIDATE<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922d3 je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x46c (fffff800`008922dc)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x465:<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922d5 mov&nbsp;&nbsp;&nbsp;&nbsp; qword ptr [rdi+0F8h],r15 ; pOriginalContext-&gt;Rip, pJumpTargetIp<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x46c:<br />
.&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922dc mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rbx ; rdx = pExceptionRecord<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922df mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,rdi ; rcx = pOriginalContext<br />
.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922e2 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRestoreContext (fffff800`008bd290)<br />
.&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922e7 jmp&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x4a0 (fffff800`00892310)<br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x479:<br />
&gt;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`008922e9 cmp&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rdi+0F8h] ; pOriginalContext-&gt;Rip<br />
 .&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f0 jne&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x48d (fffff800`008922fd)<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x482:<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f2 mov&nbsp;&nbsp;&nbsp;&nbsp; ecx,0C00000FFh ; ecx = STATUS_BAD_FUNCTION_TABLE<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922f7 call&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlRaiseStatus (fffff800`00889df0)<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922fc int&nbsp;&nbsp;&nbsp;&nbsp; 3<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!RtlUnwindEx+0x48d:<br />
 .&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fffff800`008922fd mov&nbsp;&nbsp;&nbsp;&nbsp; rcx,qword ptr [rsp+690h] ; rcx = pExceptionRecord<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892305 xor&nbsp;&nbsp;&nbsp;&nbsp; r8d,r8d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; r8d = 0<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892308 mov&nbsp;&nbsp;&nbsp;&nbsp; rdx,rdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; rdx = pOriginalContext<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`0089230b call&nbsp;&nbsp;&nbsp;&nbsp;nt!ZwRaiseException (fffff800`008b9b80)<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ZwRaiseException(pExceptionRecord, pOriginalContext, FALSE);<br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
 .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nt!RtlUnwindEx+0x4a0:<br />
 &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892310 mov&nbsp;&nbsp;&nbsp;&nbsp; r15,qword ptr [rsp+638h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892318 mov&nbsp;&nbsp;&nbsp;&nbsp; r14,qword ptr [rsp+640h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892320 mov&nbsp;&nbsp;&nbsp;&nbsp; r13,qword ptr [rsp+648h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892328 mov&nbsp;&nbsp;&nbsp;&nbsp; r12,qword ptr [rsp+650h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892330 mov&nbsp;&nbsp;&nbsp;&nbsp; rdi,qword ptr [rsp+658h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892338 mov&nbsp;&nbsp;&nbsp;&nbsp; rsi,qword ptr [rsp+660h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892340 mov&nbsp;&nbsp;&nbsp;&nbsp; rbp,qword ptr [rsp+668h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892348 mov&nbsp;&nbsp;&nbsp;&nbsp; rbx,qword ptr [rsp+670h]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892350 add&nbsp;&nbsp;&nbsp;&nbsp; rsp,678h<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fffff800`00892357 ret</code></div></div>
<br />
	<span style="font-weight: bold;">参考资料</span><br />
<br />
	[1] wrk 源码<br />
	[2] Improving Automated Analysis of Windows x64 Binaries, skape<br />
	[3] Programming against the x64 exception handling support, Skywing<br />
	[4] Exceptional Behavior - x64 Structured Exception Handling, The NT Insider<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/zip.gif" border="0" alt=".zip" />&nbsp;&nbsp;<a href="attachment.php?aid=12" target="_blank">SEH分析笔记（x64篇）_v1.0.0.zip</a> (Size: 398.19 KB / Downloads: 121)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[我的手机史]]></title>
			<link>http://boxcounter.com/showthread.php?tid=73</link>
			<pubDate>Sat, 29 Oct 2011 22:20:04 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=73</guid>
			<description><![CDATA[boxcounter,<br />
2009, August 16<br />
<br />
时间：上上周，某个月黑风高夜，<br />
<br />
人物：我<br />
<br />
地点：某烧烤摊<br />
<br />
事件：LG8330翻盖轴断裂<br />
<br />
意义：正式宣告我的第三部手机扑街了，我的手机史就此掀开了新的篇章<br />
 <br />
这里展示下我单薄的手机史，直接上图：<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=6" target="_blank">手机1.jpg</a> (Size: 6.77 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
<br />
第一部，2004年，为了跟美女联系方便买的，最后美女走了，手机扔了。<br />
<br />
牌子是迪比特，感觉相当烂，用了一两个月就开始很卡了，按键延迟相当厉害。生产厂商貌似倒了。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=7" target="_blank">手机2.jpg</a> (Size: 64.18 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
第二部，2006年，大四那年来深圳进了公司，学校里有不少事需要联系，于是收了部Nokia1100，价格很实在，东西很超值，用了很久，反应依然如初。铃声音量相当劲&#8203;爆，可以用来对抗公交车上的山寨（播放？）机，目前仍在服役。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=8" target="_blank">手机3.jpg</a> (Size: 51.09 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment --><br />
第三部，2007年，Mr.Cool换了智能机，退役下来一部LG8330，落入我爪。<br />
<br />
做工扎实，经摔耐砸，功能丰富，支持3G，好用，让我对LG这个牌子的好感直线飙升。最后死于排线断裂，阿弥陀佛，永垂不朽<br />
<br />
单角度，多造型图：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=9" target="_blank">手机4.jpg</a> (Size: 52.88 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment --><br />
<br />
再来个两兄弟合影：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=10" target="_blank">手机5.jpg</a> (Size: 48.04 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment --><br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=11" target="_blank">手机6.jpg</a> (Size: 14.86 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
第四部，HTC Cruise 09，这个月收入囊中，目前正在使用，配置强劲，使用感觉良好，缺憾是还未完美解码。原简体ROM是XDA的脏ROM。<br />
<br />
感谢Mr.cool同志的强力推荐。顺便抖抖他的糗事，这哥们今年上半年已经折腾了四部手机了，目前在用的第5部，是我的老搭档1100，这厮对手机已经心灰意冷了，这部&#8203;HTC上上个月他刚掉了一部~<br />
<br />
 <br />
为了这部手机，我兴冲冲的杀到淫乱之都，结果发现价格比深圳的还贵。顺便打听了下E71，发现价格也很离谱，水货2270RMB，后来在深圳我看到行货貌似才2280，我&#8203;窘啊]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2009, August 16<br />
<br />
时间：上上周，某个月黑风高夜，<br />
<br />
人物：我<br />
<br />
地点：某烧烤摊<br />
<br />
事件：LG8330翻盖轴断裂<br />
<br />
意义：正式宣告我的第三部手机扑街了，我的手机史就此掀开了新的篇章<br />
 <br />
这里展示下我单薄的手机史，直接上图：<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=6" target="_blank">手机1.jpg</a> (Size: 6.77 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
<br />
第一部，2004年，为了跟美女联系方便买的，最后美女走了，手机扔了。<br />
<br />
牌子是迪比特，感觉相当烂，用了一两个月就开始很卡了，按键延迟相当厉害。生产厂商貌似倒了。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=7" target="_blank">手机2.jpg</a> (Size: 64.18 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
第二部，2006年，大四那年来深圳进了公司，学校里有不少事需要联系，于是收了部Nokia1100，价格很实在，东西很超值，用了很久，反应依然如初。铃声音量相当劲&#8203;爆，可以用来对抗公交车上的山寨（播放？）机，目前仍在服役。<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=8" target="_blank">手机3.jpg</a> (Size: 51.09 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment --><br />
第三部，2007年，Mr.Cool换了智能机，退役下来一部LG8330，落入我爪。<br />
<br />
做工扎实，经摔耐砸，功能丰富，支持3G，好用，让我对LG这个牌子的好感直线飙升。最后死于排线断裂，阿弥陀佛，永垂不朽<br />
<br />
单角度，多造型图：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=9" target="_blank">手机4.jpg</a> (Size: 52.88 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment --><br />
<br />
再来个两兄弟合影：<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=10" target="_blank">手机5.jpg</a> (Size: 48.04 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment --><br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=11" target="_blank">手机6.jpg</a> (Size: 14.86 KB / Downloads: 15)
<!-- end: postbit_attachments_attachment --><br />
第四部，HTC Cruise 09，这个月收入囊中，目前正在使用，配置强劲，使用感觉良好，缺憾是还未完美解码。原简体ROM是XDA的脏ROM。<br />
<br />
感谢Mr.cool同志的强力推荐。顺便抖抖他的糗事，这哥们今年上半年已经折腾了四部手机了，目前在用的第5部，是我的老搭档1100，这厮对手机已经心灰意冷了，这部&#8203;HTC上上个月他刚掉了一部~<br />
<br />
 <br />
为了这部手机，我兴冲冲的杀到淫乱之都，结果发现价格比深圳的还贵。顺便打听了下E71，发现价格也很离谱，水货2270RMB，后来在深圳我看到行货貌似才2280，我&#8203;窘啊]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[最近]]></title>
			<link>http://boxcounter.com/showthread.php?tid=72</link>
			<pubDate>Thu, 27 Oct 2011 08:22:03 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=72</guid>
			<description><![CDATA[boxcounter,<br />
2009, August 16<br />
<br />
最近有一件私事可喜可贺：哥终于学会游泳了~~<br />
 <br />
作为长江边上长大的娃，不会游泳这个问题经常被人揪出来B4，已成为我心中痛。 六月底抓着Mr.Cool去了几次泳池，这厮一点点的教，下水几次后，哥开始有点感觉了，然后就激情似火，一发不可收，天天都想着去泡水。在我的鼓动下，黄师父及其家黄王&#8203;氏也开始频繁出没于桃源村泳池，黄师父和娟姐小时候都在专业泳队里训练过，姿势很标准，于是我抓着他们，帮我纠正动作，据说现在哥们动作还凑合，挺蛙的。<br />
 <br />
         回想起来，其实游泳还算好学，只要你能找到合适的人教，自己也没心理障碍。建议旱鸭子初下水的时候配副泳镜，我个人感觉最开始学的时候会有些恐惧感，并不是来自怕被淹或者&#8203;呛水，而是因为闭上眼把头埋在水里，对周围情况完全不可知，产生的恐惧感。戴副泳镜就好多了，你不会游，至少能在浅水区里闭气扑腾个几米吧，在这几米的基础上，再抓个人教&#8203;教你换气就OK了。<br />
        <br />
         好吧，我承认上面那句话是想说给四妞的，上个月小三、四妞来深圳耍，本想带她们下水，好多看看白花花、黑乎乎的大腿，结果四妞死活不进泳池。带着小三去泳池，结果因为前一&#8203;天台风的问题，泳池没开，窘死了。<br />
 <br />
         写到这里，我怀念起四妞那件风华绝代的连衣短裙，风吹过，白花花的大腿，禁不住心猿意马。顺便拍拍马屁：四妞现在很有女人味，哪怕套着学生妹装~。小三也是，那件黄色连衣&#8203;裙很是风骚~<br />
 <br />
         前些天在小三的鼓动下，开了开心网，但是没时间打理，就全权交给她，照顾的很不错，值得表扬~  但是老是被倒插门给芙蓉姐，这让我很是头大，士可杀不可辱。还有小猪这个birdman，倒插门、挖煤，恶行令人发指，我唾弃你~<br />
 <br />
 <br />
         最近有几首歌我还蛮喜欢的：<br />
         《Red bean》 - 方大同                    （感谢邓挫）<br />
         《洛丽塔》     - 那谁                        （感谢四妞）<br />
         《阿飞的小蝴蝶》         - 萧敬腾<br />
         《打得火热》、《谢谢侬》 - 陈奕迅]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2009, August 16<br />
<br />
最近有一件私事可喜可贺：哥终于学会游泳了~~<br />
 <br />
作为长江边上长大的娃，不会游泳这个问题经常被人揪出来B4，已成为我心中痛。 六月底抓着Mr.Cool去了几次泳池，这厮一点点的教，下水几次后，哥开始有点感觉了，然后就激情似火，一发不可收，天天都想着去泡水。在我的鼓动下，黄师父及其家黄王&#8203;氏也开始频繁出没于桃源村泳池，黄师父和娟姐小时候都在专业泳队里训练过，姿势很标准，于是我抓着他们，帮我纠正动作，据说现在哥们动作还凑合，挺蛙的。<br />
 <br />
         回想起来，其实游泳还算好学，只要你能找到合适的人教，自己也没心理障碍。建议旱鸭子初下水的时候配副泳镜，我个人感觉最开始学的时候会有些恐惧感，并不是来自怕被淹或者&#8203;呛水，而是因为闭上眼把头埋在水里，对周围情况完全不可知，产生的恐惧感。戴副泳镜就好多了，你不会游，至少能在浅水区里闭气扑腾个几米吧，在这几米的基础上，再抓个人教&#8203;教你换气就OK了。<br />
        <br />
         好吧，我承认上面那句话是想说给四妞的，上个月小三、四妞来深圳耍，本想带她们下水，好多看看白花花、黑乎乎的大腿，结果四妞死活不进泳池。带着小三去泳池，结果因为前一&#8203;天台风的问题，泳池没开，窘死了。<br />
 <br />
         写到这里，我怀念起四妞那件风华绝代的连衣短裙，风吹过，白花花的大腿，禁不住心猿意马。顺便拍拍马屁：四妞现在很有女人味，哪怕套着学生妹装~。小三也是，那件黄色连衣&#8203;裙很是风骚~<br />
 <br />
         前些天在小三的鼓动下，开了开心网，但是没时间打理，就全权交给她，照顾的很不错，值得表扬~  但是老是被倒插门给芙蓉姐，这让我很是头大，士可杀不可辱。还有小猪这个birdman，倒插门、挖煤，恶行令人发指，我唾弃你~<br />
 <br />
 <br />
         最近有几首歌我还蛮喜欢的：<br />
         《Red bean》 - 方大同                    （感谢邓挫）<br />
         《洛丽塔》     - 那谁                        （感谢四妞）<br />
         《阿飞的小蝴蝶》         - 萧敬腾<br />
         《打得火热》、《谢谢侬》 - 陈奕迅]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[日记090315]]></title>
			<link>http://boxcounter.com/showthread.php?tid=71</link>
			<pubDate>Thu, 27 Oct 2011 08:20:17 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=71</guid>
			<description><![CDATA[boxcounter,<br />
2009, March 16<br />
<br />
    周六和wallace、BigC一起打篮球，之后被wallace带去喝粥，据说3元喝到饱，于是三人兴冲冲的杀过去，进门二话不说，每人一碗粥先，又上了些凉菜，酸、辣&#8203;、甜，夹杂在一起的感觉实在是爽。但重点还是粥，有甜粥荤粥，由于是3元任喝，于是我狂喝到肚子撑得不行才停，统计了下，一共灌了四碗，其中：小米粥2碗、八宝粥2碗。B&#8203;igC一边喝着甜粥，一边还念叨着：这样吃要长胖的，怎么办啊，结果到最后丫也喝了四碗~ 菜足粥饱去付账，结果发现俺们把身上所有的钱合在一起买了单之后，仅余一元，好险好险~~~<br />
<br />
    早上醒来，拿起那家粥店的外卖单搜寻午餐，突然上面赫然写着一道面食：红油抄手！ 于是中午又和这两位童鞋杀到这家粥店，我主吃抄手，没碰粥。BigC同志则很没出息的又喝了4碗~ 我觉得有一丝的歉意：这家老板也挺不容易的，遇到俺们这样的客户估计也只能背过身去偷偷抹泪。<br />
<br />
    菜足粥饱后，去找老肖同志，路上的公交车上，看见一对父子，儿子很小，大概小学2、3年级的样子，手上拿着一本旧旧的机器猫在读，过了几分钟，貌似读完了。合上书，盯着书&#8203;的封面满足的笑了。然后把书递给父亲，自己扭头看车窗外的风景。父亲接过书，看了看封面、又看了看封底，再翻了几页，合上了，貌似并不理解儿子为什么会喜欢。<br />
<br />
    我突然想起自己小时候，经常去租武侠看，押金10元、租金5角每天。大学之前我是没有零花钱的，只能眼巴巴的盼过年，把几张压岁的毛老爷子偷偷的藏起来，用来租书。父亲很&#8203;反对我看武侠，见一本就撕一本，平均下来，一年能撕5、6本。书没了，押金自然也打了漂。加上租金，算下来，前一年的压岁钱差不多勉强能撑到第二年过年。为了省租金，我会&#8203;尽快读完，疯狂的时候一天一本，现在回想起来，貌似还没有哪书能耗我多过一元的租金。这样时间长了，就养成了一目十行、过目就忘的本领。这也是我如今比较偏爱E文资料的原&#8203;因之一：技术资料都需要仔细琢磨，反复思考，如果是中文资料，我会习惯性的跳着看，经常看了半天不知道里面讲的是什么。于是就逼着自己看E文原著：E文没那么牛X，只能一&#8203;个单词一个单词的抠，一个分句一个分句的理解。这个习惯我是从大学开始养成的，在学校里看原著的时候被人发现了，要么被认为很牛B，要么被认为很装B。这里啰嗦这么久，只&#8203;是想顺便解释下。不过说回来，看了一些E文原著后，感觉国人的译著和原著相差还是蛮大的。<br />
    <br />
    <br />
    哦，忘了说，晚上回到桃源村，我又去光顾了那家粥店，本只想喝喝粥的，但是觉得光点粥不太好意思，于是点了份韭菜盒子，最后肚揣三碗八宝粥，惬意而归。心里琢磨着，以后找&#8203;媳妇，得好好调教下，至少得能煲一手好甜粥吧。<br />
<br />
    最后给我的朋友们提个醒：运动之前先热热身，拉伸下肌肉。前阵子打球，没热身就上场拼，晚上休息才发现腰扭伤了，现在还隐隐作痛的。]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2009, March 16<br />
<br />
    周六和wallace、BigC一起打篮球，之后被wallace带去喝粥，据说3元喝到饱，于是三人兴冲冲的杀过去，进门二话不说，每人一碗粥先，又上了些凉菜，酸、辣&#8203;、甜，夹杂在一起的感觉实在是爽。但重点还是粥，有甜粥荤粥，由于是3元任喝，于是我狂喝到肚子撑得不行才停，统计了下，一共灌了四碗，其中：小米粥2碗、八宝粥2碗。B&#8203;igC一边喝着甜粥，一边还念叨着：这样吃要长胖的，怎么办啊，结果到最后丫也喝了四碗~ 菜足粥饱去付账，结果发现俺们把身上所有的钱合在一起买了单之后，仅余一元，好险好险~~~<br />
<br />
    早上醒来，拿起那家粥店的外卖单搜寻午餐，突然上面赫然写着一道面食：红油抄手！ 于是中午又和这两位童鞋杀到这家粥店，我主吃抄手，没碰粥。BigC同志则很没出息的又喝了4碗~ 我觉得有一丝的歉意：这家老板也挺不容易的，遇到俺们这样的客户估计也只能背过身去偷偷抹泪。<br />
<br />
    菜足粥饱后，去找老肖同志，路上的公交车上，看见一对父子，儿子很小，大概小学2、3年级的样子，手上拿着一本旧旧的机器猫在读，过了几分钟，貌似读完了。合上书，盯着书&#8203;的封面满足的笑了。然后把书递给父亲，自己扭头看车窗外的风景。父亲接过书，看了看封面、又看了看封底，再翻了几页，合上了，貌似并不理解儿子为什么会喜欢。<br />
<br />
    我突然想起自己小时候，经常去租武侠看，押金10元、租金5角每天。大学之前我是没有零花钱的，只能眼巴巴的盼过年，把几张压岁的毛老爷子偷偷的藏起来，用来租书。父亲很&#8203;反对我看武侠，见一本就撕一本，平均下来，一年能撕5、6本。书没了，押金自然也打了漂。加上租金，算下来，前一年的压岁钱差不多勉强能撑到第二年过年。为了省租金，我会&#8203;尽快读完，疯狂的时候一天一本，现在回想起来，貌似还没有哪书能耗我多过一元的租金。这样时间长了，就养成了一目十行、过目就忘的本领。这也是我如今比较偏爱E文资料的原&#8203;因之一：技术资料都需要仔细琢磨，反复思考，如果是中文资料，我会习惯性的跳着看，经常看了半天不知道里面讲的是什么。于是就逼着自己看E文原著：E文没那么牛X，只能一&#8203;个单词一个单词的抠，一个分句一个分句的理解。这个习惯我是从大学开始养成的，在学校里看原著的时候被人发现了，要么被认为很牛B，要么被认为很装B。这里啰嗦这么久，只&#8203;是想顺便解释下。不过说回来，看了一些E文原著后，感觉国人的译著和原著相差还是蛮大的。<br />
    <br />
    <br />
    哦，忘了说，晚上回到桃源村，我又去光顾了那家粥店，本只想喝喝粥的，但是觉得光点粥不太好意思，于是点了份韭菜盒子，最后肚揣三碗八宝粥，惬意而归。心里琢磨着，以后找&#8203;媳妇，得好好调教下，至少得能煲一手好甜粥吧。<br />
<br />
    最后给我的朋友们提个醒：运动之前先热热身，拉伸下肌肉。前阵子打球，没热身就上场拼，晚上休息才发现腰扭伤了，现在还隐隐作痛的。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[小面包真好]]></title>
			<link>http://boxcounter.com/showthread.php?tid=69</link>
			<pubDate>Thu, 27 Oct 2011 08:18:54 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=69</guid>
			<description><![CDATA[boxcounter,<br />
2008, November 30<br />
<br />
    昨晚遇到一系列的怪事，记下来，等老了慢慢回味:<br />
    <br />
    我坐电梯，电梯在十四楼突然卡住了，我只好从电梯的顶窗爬出来。就在这个时候电梯突然又动起来了，我很恐惧的拍打周围的铁墙壁，声音很闷，没人理我。我只好紧紧的抓住面前&#8203;一个类似把手的东西，听天由命。然后突然发现我跟着电梯平安的到达了地面，而且我直接就站到了地面。还没等我把心放回心窝里，突然又发现地震了，然后赶紧往庇护所跑，遇到&#8203;了黄师父等。然后我们就惶恐的呆在庇护所里，透过窗户我看见外面的两座摩天大楼从中间断成两截，上面的一截就接连在我面前轰然倒下。这个时候我才反应过来，干净吼着跟大伙&#8203;一起跑到外面的空地上，惊恐的看着庇护所，庆幸的是庇护所安然无事。<br />
    <br />
    然后我又突然想起我的行李，我的钱包、手机还留在庇护所里，这个时候大伙也都反应过来，都嚷嚷的着要冲进去拿回自己的东西。我安抚了半天，最终达成协议，由我和黄师父回去&#8203;把大家值钱的东西都拿回来，其他人安全起见就留在空地上。等把东西都拿出来，我才想起要给某MM打电话问问她是否安好，于是紧张兮兮的打电话过去，得知她一切安好，心里顿&#8203;感踏实了不少。挂了电话，我就四处乱瞅，突然发现头顶上很高很高的地方的建筑天顶要倒了（不知道咋描述这个建筑，可以这么想，我们在一个“王”字形的庞然建筑里，我们呆的&#8203;具体位置就是中间那一横，天顶指的是上面一横，地面就是最底下一横），于是大家又紧张兮兮的想办法赶紧下到地面。<br />
    <br />
    就在这节骨眼，我醒了。MD，原来是个梦。<br />
<br />
    感觉饥肠辘辘，以我质朴的心灵揣测，我应该是被饿醒的。很是后悔，就因为自己肚子饿，就抛弃了黄师父等，留他们孤零零的享受地震。再一想，MD，活着的感觉真好。于是晃悠&#8203;到客厅连吃了5个小面包，喝了大半瓶的水，感觉好多了。然后一边感谢赐予我美好生活的爸妈、各路神仙、兄弟、姐妹还有自己，一边踱步到窗边，看着14层楼下的芸芸几辆ta&#8203;xi来来往往，感觉特别踏实，然后又倒头昏睡过去。<br />
    <br />
    再醒来时，天已经大亮，仍觉得不可思议，这应该是我自小做过的感受最真实的梦了。我经常在梦里可以感觉到自己是在做梦，于是很享受的赖在梦里不醒，但这次在这次梦中，我始&#8203;终感觉到紧张和惊恐，一丝都没有察觉是个梦。<br />
    <br />
    OK，这次也算是很真实的感受了下地震，收获不少，最大的收获是：还活着的感觉真好；饿醒了有小面包吃，真好。<br />
    <br />
    <br />
    以前经常开玩笑：<br />
        我：经历过地震没？<br />
        某：没~<br />
        我：那你的生活的乐趣少了 1/4。经历过火山没？<br />
        某：没~<br />
        我：那你的生命的乐趣少 2/4。经历过龙卷风没？<br />
        某：没~<br />
        我：那你的生命的乐趣少了 3/4。经历过海啸没？<br />
        某：没~<br />
        我：那你跟咸鱼没什么分别了。<br />
    现在我总算是保住了我生活乐趣的 1/4~<br />
    <br />
    总结：<br />
        （1） 电梯重新动起来时，我是踩着电梯厢的，怎么后来就直接安全的踏上地面了？ 这个我要好好研究下<br />
        （2） 本梦的出场人员中，我貌似没有看到Quack、BT姐、mrcool、村长，估计是地震前就没义气的跑了，B4他们~<br />
        （3） 地震中，我居然只想到给MM打电话，没想到给家里人打，实在是不孝，深刻检讨。]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, November 30<br />
<br />
    昨晚遇到一系列的怪事，记下来，等老了慢慢回味:<br />
    <br />
    我坐电梯，电梯在十四楼突然卡住了，我只好从电梯的顶窗爬出来。就在这个时候电梯突然又动起来了，我很恐惧的拍打周围的铁墙壁，声音很闷，没人理我。我只好紧紧的抓住面前&#8203;一个类似把手的东西，听天由命。然后突然发现我跟着电梯平安的到达了地面，而且我直接就站到了地面。还没等我把心放回心窝里，突然又发现地震了，然后赶紧往庇护所跑，遇到&#8203;了黄师父等。然后我们就惶恐的呆在庇护所里，透过窗户我看见外面的两座摩天大楼从中间断成两截，上面的一截就接连在我面前轰然倒下。这个时候我才反应过来，干净吼着跟大伙&#8203;一起跑到外面的空地上，惊恐的看着庇护所，庆幸的是庇护所安然无事。<br />
    <br />
    然后我又突然想起我的行李，我的钱包、手机还留在庇护所里，这个时候大伙也都反应过来，都嚷嚷的着要冲进去拿回自己的东西。我安抚了半天，最终达成协议，由我和黄师父回去&#8203;把大家值钱的东西都拿回来，其他人安全起见就留在空地上。等把东西都拿出来，我才想起要给某MM打电话问问她是否安好，于是紧张兮兮的打电话过去，得知她一切安好，心里顿&#8203;感踏实了不少。挂了电话，我就四处乱瞅，突然发现头顶上很高很高的地方的建筑天顶要倒了（不知道咋描述这个建筑，可以这么想，我们在一个“王”字形的庞然建筑里，我们呆的&#8203;具体位置就是中间那一横，天顶指的是上面一横，地面就是最底下一横），于是大家又紧张兮兮的想办法赶紧下到地面。<br />
    <br />
    就在这节骨眼，我醒了。MD，原来是个梦。<br />
<br />
    感觉饥肠辘辘，以我质朴的心灵揣测，我应该是被饿醒的。很是后悔，就因为自己肚子饿，就抛弃了黄师父等，留他们孤零零的享受地震。再一想，MD，活着的感觉真好。于是晃悠&#8203;到客厅连吃了5个小面包，喝了大半瓶的水，感觉好多了。然后一边感谢赐予我美好生活的爸妈、各路神仙、兄弟、姐妹还有自己，一边踱步到窗边，看着14层楼下的芸芸几辆ta&#8203;xi来来往往，感觉特别踏实，然后又倒头昏睡过去。<br />
    <br />
    再醒来时，天已经大亮，仍觉得不可思议，这应该是我自小做过的感受最真实的梦了。我经常在梦里可以感觉到自己是在做梦，于是很享受的赖在梦里不醒，但这次在这次梦中，我始&#8203;终感觉到紧张和惊恐，一丝都没有察觉是个梦。<br />
    <br />
    OK，这次也算是很真实的感受了下地震，收获不少，最大的收获是：还活着的感觉真好；饿醒了有小面包吃，真好。<br />
    <br />
    <br />
    以前经常开玩笑：<br />
        我：经历过地震没？<br />
        某：没~<br />
        我：那你的生活的乐趣少了 1/4。经历过火山没？<br />
        某：没~<br />
        我：那你的生命的乐趣少 2/4。经历过龙卷风没？<br />
        某：没~<br />
        我：那你的生命的乐趣少了 3/4。经历过海啸没？<br />
        某：没~<br />
        我：那你跟咸鱼没什么分别了。<br />
    现在我总算是保住了我生活乐趣的 1/4~<br />
    <br />
    总结：<br />
        （1） 电梯重新动起来时，我是踩着电梯厢的，怎么后来就直接安全的踏上地面了？ 这个我要好好研究下<br />
        （2） 本梦的出场人员中，我貌似没有看到Quack、BT姐、mrcool、村长，估计是地震前就没义气的跑了，B4他们~<br />
        （3） 地震中，我居然只想到给MM打电话，没想到给家里人打，实在是不孝，深刻检讨。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[日记080917]]></title>
			<link>http://boxcounter.com/showthread.php?tid=68</link>
			<pubDate>Thu, 27 Oct 2011 08:18:02 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=68</guid>
			<description><![CDATA[boxcounter,<br />
2008, September 17<br />
<br />
    1. 梨花版的quack <br />
       通常我们在聚餐时，都会趁着上菜前的一段时间大肆YY一番，天南地北、歪瓜裂枣，无所不吹。这天也不例外，大家YY到了情书，有人提到quack同学善情诗，quack同&#8203;学谦虚了一番，然后颇为得意的说：<br />
      “我不用写，我往那一站，就是一首情诗。”<br />
       mrcool小小声的接了句：“是啊，梨花体~”<br />
       一席人爆笑不止。<br />
<br />
       作为男主角，quack同学事后以完全不记得为由怀疑此事的真实性。但本报道还是得到了其家属的鼎力支持，在这里严重感谢BT姐。<br />
<br />
        <br />
    2. 音乐：<br />
       个人感觉不错的：<br />
       《乱红》<br />
       《绿野仙踪》<br />
       《 いきものがかり-ブルーバード》<br />
       《画心》]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, September 17<br />
<br />
    1. 梨花版的quack <br />
       通常我们在聚餐时，都会趁着上菜前的一段时间大肆YY一番，天南地北、歪瓜裂枣，无所不吹。这天也不例外，大家YY到了情书，有人提到quack同学善情诗，quack同&#8203;学谦虚了一番，然后颇为得意的说：<br />
      “我不用写，我往那一站，就是一首情诗。”<br />
       mrcool小小声的接了句：“是啊，梨花体~”<br />
       一席人爆笑不止。<br />
<br />
       作为男主角，quack同学事后以完全不记得为由怀疑此事的真实性。但本报道还是得到了其家属的鼎力支持，在这里严重感谢BT姐。<br />
<br />
        <br />
    2. 音乐：<br />
       个人感觉不错的：<br />
       《乱红》<br />
       《绿野仙踪》<br />
       《 いきものがかり-ブルーバード》<br />
       《画心》]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[牢骚、键盘和音乐]]></title>
			<link>http://boxcounter.com/showthread.php?tid=67</link>
			<pubDate>Thu, 27 Oct 2011 08:17:11 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=67</guid>
			<description><![CDATA[boxcounter,<br />
2008, August 15<br />
<br />
      貌似又好些天没写东西了，貌似最近一直没心思写东西，比如这篇就是觉得实在得写点什么才写的。最近对什么都缺乏兴趣，总觉得没精神，脑子貌似都不好使了，有时候说话都不利&#8203;索，时不时会为一个简单的词想半天，还有时候会前言不搭后语，不知道是不是无意中伤了脑神经~~BigC也说我白头发又多了不少，NND，真乱。<br />
    不废话了，进入主题：<br />
<br />
    1.我的键盘<br />
<br />
     在公司里，我用的是款多彩的K8080，这款本来是键鼠套装，但是我已经有了一只很喜欢的罗技鼠了，所以就只用键盘。感觉这款键盘很不错，虽然是仿制品。优点很多：<br />
    1.键程短，弹力不错，敲起来很有感觉。<br />
    2.键帽做了平滑的处理，更舒服，敲字的时候更精准。<br />
    3.敲击的声音较小，对于跟我这种喜欢死命敲键盘的同处一办公室的人来说算是个福音~ <br />
    4.去掉了Power、Sleep、Wakeup这三个我从来都不会正经用到，但是却经常一不小心就按到~~  每次都好烦好烦~~~<br />
<br />
    这里发发牢骚，我不懂那些设计键盘的人是怎么想的，这几个键本来多数普通用户就不常用，干嘛非要做到键盘上？还有的键盘更让人无语，Power键就在'F12'键的旁边，&#8203;一不小心就按到，让我数次抓狂。  所以我每拿到一款键盘，首先就把Power键给取下来~  而K8080就完全去掉了这三个键，太明智了。  扯远一点，我挺喜欢WIN这个辅助键，之前用过一段时间的IBM T42，没法用类似WIN+D这种很实用的快捷键让我很是郁闷。所以后来联想把这个键加到Thinkpad机型的时候，我还是蛮高兴的，不过最近听了mrcool，gla&#8203;cier不少关于X61、T60的抱怨，为联想的模具设计和制作工艺汗颜~<br />
  <br />
    前些天，在家里攒了台台式机，买键盘的时候就专门去买K8080的原型 - DELL 8115。DELL还有一款8135，是8115的升级版，多了很多功能键，多了个托盘，造型也时尚了不少，可惜我用键鼠都喜欢精简的，套用一句广告：“简约而不简单”。&#8203;感觉这款也不错，仔细的瞧了瞧，制作工艺没话说，相比之下，K8080就逊色了些，我甚至能看出K8080上某些键帽的大小有些不一样~~  但是最可惜的它的键帽还是经典设计，没有像K8080做平滑处理，让我失望了一把。所以K8080虽然是模仿出来的，但看得出多彩还是费了番心思的。<br />
<br />
    2.音乐<br />
    近几个月都在用qqmusic听音乐，的确好用。以前用千千静听，听歌都是上baidu top 100一首一首的载回来，听完后再一首一首的把不喜欢的删除，挺累的。而QQMusic就挺好，在线听，觉得喜欢再去百度上下（QQMusic上可以下载，可惜要绿钻），&#8203;不过有点不习惯的是，QQMusic的排行榜里没有BaiDu Top 100，而内置的排行榜更新又慢，经常一个多星期过去了，还是那些歌。<br />
    最近淘到的喜欢的歌有：<br />
   《即使知道要见面》 - Sara(泰国)<br />
          这首歌是泰语的，听求不懂，但是第一次听到的时候就觉得旋律不错，后来专门搜了歌词，歌词也不错<br />
<br />
    《你不像她》          - 南拳妈妈<br />
          以前一直不喜欢南拳妈妈，我比较排斥靠大腕突然间就火箭般蹿出来的歌手，不过最近发现他们的这首歌老是在排行榜的前几名，好奇心使然，试听了下，觉得蛮不错，所以回头就把&#8203;他们所有的专辑都翻出来听了听。<br />
<br />
<br />
[attach=22]<br />
<br />
DELL 8115<br />
<br />
[attach=23]<br />
<br />
K8080<br />
<br />
[attach=24]<br />
<br />
相对于普通键盘的键帽，K8080的键帽做了平滑处理<br />
<br />
[attach=25]<br />
<br />
公司里用的罗技鼠，很不错，就是小了点。下次换鼠标就买适合大手掌的MX518好了。<br />
<br />
[attach=26]<br />
<br />
办公的小窝<br />
<br />
[boxcounter,2011-10-27：迁移blog时所有照片都丢失了]]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, August 15<br />
<br />
      貌似又好些天没写东西了，貌似最近一直没心思写东西，比如这篇就是觉得实在得写点什么才写的。最近对什么都缺乏兴趣，总觉得没精神，脑子貌似都不好使了，有时候说话都不利&#8203;索，时不时会为一个简单的词想半天，还有时候会前言不搭后语，不知道是不是无意中伤了脑神经~~BigC也说我白头发又多了不少，NND，真乱。<br />
    不废话了，进入主题：<br />
<br />
    1.我的键盘<br />
<br />
     在公司里，我用的是款多彩的K8080，这款本来是键鼠套装，但是我已经有了一只很喜欢的罗技鼠了，所以就只用键盘。感觉这款键盘很不错，虽然是仿制品。优点很多：<br />
    1.键程短，弹力不错，敲起来很有感觉。<br />
    2.键帽做了平滑的处理，更舒服，敲字的时候更精准。<br />
    3.敲击的声音较小，对于跟我这种喜欢死命敲键盘的同处一办公室的人来说算是个福音~ <br />
    4.去掉了Power、Sleep、Wakeup这三个我从来都不会正经用到，但是却经常一不小心就按到~~  每次都好烦好烦~~~<br />
<br />
    这里发发牢骚，我不懂那些设计键盘的人是怎么想的，这几个键本来多数普通用户就不常用，干嘛非要做到键盘上？还有的键盘更让人无语，Power键就在'F12'键的旁边，&#8203;一不小心就按到，让我数次抓狂。  所以我每拿到一款键盘，首先就把Power键给取下来~  而K8080就完全去掉了这三个键，太明智了。  扯远一点，我挺喜欢WIN这个辅助键，之前用过一段时间的IBM T42，没法用类似WIN+D这种很实用的快捷键让我很是郁闷。所以后来联想把这个键加到Thinkpad机型的时候，我还是蛮高兴的，不过最近听了mrcool，gla&#8203;cier不少关于X61、T60的抱怨，为联想的模具设计和制作工艺汗颜~<br />
  <br />
    前些天，在家里攒了台台式机，买键盘的时候就专门去买K8080的原型 - DELL 8115。DELL还有一款8135，是8115的升级版，多了很多功能键，多了个托盘，造型也时尚了不少，可惜我用键鼠都喜欢精简的，套用一句广告：“简约而不简单”。&#8203;感觉这款也不错，仔细的瞧了瞧，制作工艺没话说，相比之下，K8080就逊色了些，我甚至能看出K8080上某些键帽的大小有些不一样~~  但是最可惜的它的键帽还是经典设计，没有像K8080做平滑处理，让我失望了一把。所以K8080虽然是模仿出来的，但看得出多彩还是费了番心思的。<br />
<br />
    2.音乐<br />
    近几个月都在用qqmusic听音乐，的确好用。以前用千千静听，听歌都是上baidu top 100一首一首的载回来，听完后再一首一首的把不喜欢的删除，挺累的。而QQMusic就挺好，在线听，觉得喜欢再去百度上下（QQMusic上可以下载，可惜要绿钻），&#8203;不过有点不习惯的是，QQMusic的排行榜里没有BaiDu Top 100，而内置的排行榜更新又慢，经常一个多星期过去了，还是那些歌。<br />
    最近淘到的喜欢的歌有：<br />
   《即使知道要见面》 - Sara(泰国)<br />
          这首歌是泰语的，听求不懂，但是第一次听到的时候就觉得旋律不错，后来专门搜了歌词，歌词也不错<br />
<br />
    《你不像她》          - 南拳妈妈<br />
          以前一直不喜欢南拳妈妈，我比较排斥靠大腕突然间就火箭般蹿出来的歌手，不过最近发现他们的这首歌老是在排行榜的前几名，好奇心使然，试听了下，觉得蛮不错，所以回头就把&#8203;他们所有的专辑都翻出来听了听。<br />
<br />
<br />
[attach=22]<br />
<br />
DELL 8115<br />
<br />
[attach=23]<br />
<br />
K8080<br />
<br />
[attach=24]<br />
<br />
相对于普通键盘的键帽，K8080的键帽做了平滑处理<br />
<br />
[attach=25]<br />
<br />
公司里用的罗技鼠，很不错，就是小了点。下次换鼠标就买适合大手掌的MX518好了。<br />
<br />
[attach=26]<br />
<br />
办公的小窝<br />
<br />
[boxcounter,2011-10-27：迁移blog时所有照片都丢失了]]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[被朋友点名鸟~]]></title>
			<link>http://boxcounter.com/showthread.php?tid=66</link>
			<pubDate>Thu, 27 Oct 2011 08:15:21 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=66</guid>
			<description><![CDATA[boxcounter,<br />
2008, June 17<br />
<br />
     朋友在QZONE点名，于是作答。本来这个游戏是要继续传递下去的，但是我有两个原则：<br />
     1. 群发的消息，一律不回<br />
     2. 要求我必须发给多少人，否则怎么怎么样的。这种短信、消息，一律终结。<br />
     所以这个游戏，我就不点名了。<br />
<br />
很多问题都是“首要”、“最”，很难排序，于是我就把前几位都做为答案<br />
<br />
1、上次哭在什么时候？ <br />
   几年前第一次听《矜持》的时候。第二天，在一个女孩子的陪同下，为另外一个女孩痛哭。<br />
<br />
2、说出点你名的朋友的三个优点？ <br />
   乖巧，人好，眼睛很漂亮，笑起来更漂亮。<br />
<br />
3、如果给你一次机会，你想从自己多大那一年从头过起？ <br />
   可惜没有这么个机会<br />
   <br />
4、相信爱情吗？ <br />
   还相信<br />
   <br />
5、现阶段最大的愿望是什么？ <br />
   买房买车包二奶<br />
<br />
6、觉得最享受的是什么？ <br />
   她沉沉的睡在我怀里；<br />
   听着音乐，看着书；<br />
   和一群大学的狐朋狗友一起打游戏；<br />
   打完篮球后，洗完澡、穿得清爽的去西师后面的小火锅店吃小火锅<br />
   还有很多，就不列举了。<br />
  <br />
<br />
7、你最想去的地方？为什么？ <br />
   家，想家。<br />
<br />
8、你的首要择偶条件是什么？ <br />
   女的、活的、善良、不傻、专一、不丑（如果可以选择的话，希望耐看一点）<br />
   <br />
9、你觉得最合适你结婚的年龄是什么时候？ <br />
    遇到合适的人的时候<br />
<br />
10、幸福的事的定义是什么？ <br />
    让我幸福的事<br />
<br />
11、你是一个固执的人吗？ <br />
    要看你有没有合理的理由说服我<br />
    <br />
12、可以选择的话，你选择结婚，还是不结婚？ <br />
    结婚<br />
    <br />
13、出去后，你想干什么？（我的问题，这难道就是所谓的梦想）？<br />
    这个问题很无敌，我开始以为是给监狱里的朋友做的题~<br />
<br />
14、你在意你的男友或女友有异性朋友吗？ <br />
    看人，对方如果是我觉得可靠的，就不太在意。但是如果不是什么好人，那就给我断干净，免得我急。<br />
<br />
15、你打算生几个孩子？男的还是女的？ <br />
    这个得靠孩子他（她、他们、她们）妈<br />
<br />
16、当朋友误解你的时候，你会怎么办？ <br />
    我讨厌误解，会尽量把自己的想法、为什么有这样的想法告诉他，如果他实在理解不了，那我也很无奈。<br />
<br />
17、幻想你到30岁的时候，你会是个怎样的人? <br />
    我也很想知道。<br />
<br />
18、你最想留住哪个城市生活？ <br />
    深圳、珠海<br />
<br />
19、你觉得你对你现在的生活状态满意吗？ 为什么会有这样的想法？ <br />
    还不错。父母过得还不错，自己做着自己想做的事，身边有几个好朋友，能互相帮助，能互相理解。<br />
<br />
20、你做过的最浪漫的事情？（嘿嘿，，可以说得仔细点哦） <br />
    这个得问她<br />
<br />
Ok，完成了朋友的任务，收工。]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, June 17<br />
<br />
     朋友在QZONE点名，于是作答。本来这个游戏是要继续传递下去的，但是我有两个原则：<br />
     1. 群发的消息，一律不回<br />
     2. 要求我必须发给多少人，否则怎么怎么样的。这种短信、消息，一律终结。<br />
     所以这个游戏，我就不点名了。<br />
<br />
很多问题都是“首要”、“最”，很难排序，于是我就把前几位都做为答案<br />
<br />
1、上次哭在什么时候？ <br />
   几年前第一次听《矜持》的时候。第二天，在一个女孩子的陪同下，为另外一个女孩痛哭。<br />
<br />
2、说出点你名的朋友的三个优点？ <br />
   乖巧，人好，眼睛很漂亮，笑起来更漂亮。<br />
<br />
3、如果给你一次机会，你想从自己多大那一年从头过起？ <br />
   可惜没有这么个机会<br />
   <br />
4、相信爱情吗？ <br />
   还相信<br />
   <br />
5、现阶段最大的愿望是什么？ <br />
   买房买车包二奶<br />
<br />
6、觉得最享受的是什么？ <br />
   她沉沉的睡在我怀里；<br />
   听着音乐，看着书；<br />
   和一群大学的狐朋狗友一起打游戏；<br />
   打完篮球后，洗完澡、穿得清爽的去西师后面的小火锅店吃小火锅<br />
   还有很多，就不列举了。<br />
  <br />
<br />
7、你最想去的地方？为什么？ <br />
   家，想家。<br />
<br />
8、你的首要择偶条件是什么？ <br />
   女的、活的、善良、不傻、专一、不丑（如果可以选择的话，希望耐看一点）<br />
   <br />
9、你觉得最合适你结婚的年龄是什么时候？ <br />
    遇到合适的人的时候<br />
<br />
10、幸福的事的定义是什么？ <br />
    让我幸福的事<br />
<br />
11、你是一个固执的人吗？ <br />
    要看你有没有合理的理由说服我<br />
    <br />
12、可以选择的话，你选择结婚，还是不结婚？ <br />
    结婚<br />
    <br />
13、出去后，你想干什么？（我的问题，这难道就是所谓的梦想）？<br />
    这个问题很无敌，我开始以为是给监狱里的朋友做的题~<br />
<br />
14、你在意你的男友或女友有异性朋友吗？ <br />
    看人，对方如果是我觉得可靠的，就不太在意。但是如果不是什么好人，那就给我断干净，免得我急。<br />
<br />
15、你打算生几个孩子？男的还是女的？ <br />
    这个得靠孩子他（她、他们、她们）妈<br />
<br />
16、当朋友误解你的时候，你会怎么办？ <br />
    我讨厌误解，会尽量把自己的想法、为什么有这样的想法告诉他，如果他实在理解不了，那我也很无奈。<br />
<br />
17、幻想你到30岁的时候，你会是个怎样的人? <br />
    我也很想知道。<br />
<br />
18、你最想留住哪个城市生活？ <br />
    深圳、珠海<br />
<br />
19、你觉得你对你现在的生活状态满意吗？ 为什么会有这样的想法？ <br />
    还不错。父母过得还不错，自己做着自己想做的事，身边有几个好朋友，能互相帮助，能互相理解。<br />
<br />
20、你做过的最浪漫的事情？（嘿嘿，，可以说得仔细点哦） <br />
    这个得问她<br />
<br />
Ok，完成了朋友的任务，收工。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[日记（080420-080421）]]></title>
			<link>http://boxcounter.com/showthread.php?tid=65</link>
			<pubDate>Thu, 27 Oct 2011 08:14:30 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=65</guid>
			<description><![CDATA[boxcounter,<br />
2008, April 22<br />
<br />
       这两天的经历颇为离奇，值得一记。  <br />
<br />
<br />
       周日，跆拳道课上，脚趾踢出了血。上完课，拖着疲惫的小身子骨回家，MRcool正在勤劳的拖地，地板瞠亮瞠亮的，20分钟后，我就在这块瞠亮瞠亮的地板上来了个连环摔（&#8203;摔到地上后，还左右前后各撞了一下），手掌心割了条长长的口子。<br />
      <br />
       晚上，同Mrcool，Glacier贤伉俪逛山姆会员店，看到一名很符合自己审美观的MM，我很少能看到一个女孩就舍不得转眼睛~ 正在流口水的时候发现她的膝盖旁边站着个小乖小乖小女孩不停的喊着什么，貌似是“妈妈”~  （不过我至今无法相信她已经当妈妈了）。<br />
       <br />
       晚上回来的路上接了MM的电话，情迷意乱之下把钱包留在了计程车上，下车的时候还一个劲的跟死机师傅说“谢谢啊”~<br />
<br />
<br />
       昨天，花了约莫4个小时的时间补卡，累得半死~ 值得高兴的是，在招行总部遇到一个MM跑过来贴着我坐，近得一直闻着她身上的香味。<br />
<br />
<br />
       晚上，喝完冰后陪Glacier、Mrcool取钱的时候，鬼迷心窍的想查查刚补的卡是否OK，找了个貌似工作正常的ATM机，刚把卡插到一半，界面显示“本机因故障，暂&#8203;停服务”，赶紧往外拔卡，结果手一哆嗦，把卡又往里送了一小截。但是看见还有一小截卡露在外面，松了一口气，镇定的去找ZC借指甲剪，回头却看见Mrcool一脸憨笑的说&#8203;：”吞了~“ 顿时泪流满面~<br />
<br />
总结：<br />
1. 春天来了，我的春天也来了。这句话通俗的讲，就是，发春的季节到了~<br />
2. Mrcool和自己的经历告诉我们：不是本命年，也一样可以很倒霉。<br />
3. Mrcool去年写了篇总结《我的2007》，我衷心的希望自己不会在年底也写这么个总结，阿门。]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, April 22<br />
<br />
       这两天的经历颇为离奇，值得一记。  <br />
<br />
<br />
       周日，跆拳道课上，脚趾踢出了血。上完课，拖着疲惫的小身子骨回家，MRcool正在勤劳的拖地，地板瞠亮瞠亮的，20分钟后，我就在这块瞠亮瞠亮的地板上来了个连环摔（&#8203;摔到地上后，还左右前后各撞了一下），手掌心割了条长长的口子。<br />
      <br />
       晚上，同Mrcool，Glacier贤伉俪逛山姆会员店，看到一名很符合自己审美观的MM，我很少能看到一个女孩就舍不得转眼睛~ 正在流口水的时候发现她的膝盖旁边站着个小乖小乖小女孩不停的喊着什么，貌似是“妈妈”~  （不过我至今无法相信她已经当妈妈了）。<br />
       <br />
       晚上回来的路上接了MM的电话，情迷意乱之下把钱包留在了计程车上，下车的时候还一个劲的跟死机师傅说“谢谢啊”~<br />
<br />
<br />
       昨天，花了约莫4个小时的时间补卡，累得半死~ 值得高兴的是，在招行总部遇到一个MM跑过来贴着我坐，近得一直闻着她身上的香味。<br />
<br />
<br />
       晚上，喝完冰后陪Glacier、Mrcool取钱的时候，鬼迷心窍的想查查刚补的卡是否OK，找了个貌似工作正常的ATM机，刚把卡插到一半，界面显示“本机因故障，暂&#8203;停服务”，赶紧往外拔卡，结果手一哆嗦，把卡又往里送了一小截。但是看见还有一小截卡露在外面，松了一口气，镇定的去找ZC借指甲剪，回头却看见Mrcool一脸憨笑的说&#8203;：”吞了~“ 顿时泪流满面~<br />
<br />
总结：<br />
1. 春天来了，我的春天也来了。这句话通俗的讲，就是，发春的季节到了~<br />
2. Mrcool和自己的经历告诉我们：不是本命年，也一样可以很倒霉。<br />
3. Mrcool去年写了篇总结《我的2007》，我衷心的希望自己不会在年底也写这么个总结，阿门。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[日记（2008-03-11）]]></title>
			<link>http://boxcounter.com/showthread.php?tid=64</link>
			<pubDate>Thu, 27 Oct 2011 08:12:56 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=64</guid>
			<description><![CDATA[boxcounter,<br />
2008, March 11<br />
<br />
   每次在BLOG上胡乱涂鸦的时候老是为取什么名字而烦恼，比如“二三事”之类的名字都是实在想不出该叫什么而随便用的，今天觉得还是直接用“日记”好了。<br />
   提起日记，我想起了高三时候，语文老师突然要我们写日记，记录高三紧张“丰富”的每一天，每天都要交。我现在想起来都很佩服那些日记经常能得“优”的同学，能把吃了学，学&#8203;了吃的高三生活写得那么梦幻，实在是难得。我个人对“日记”的理解是：每日生活中有意义的事，而对于高三的学上，上学读书当然是最有意义的事（不过私下里，当时我绝得打篮&#8203;球、翘课打传奇更有意义），所以老实的我老老实实地把日记写成这样： <br />
<br />
<br />
早上7点：起床、刷牙、洗脸、吃早餐<br />
早上7点半：上学去<br />
早上8点：上课<br />
中午12点：放学回家<br />
中午12点半：吃饭、午休<br />
下午1点半：起床、洗脸、上课<br />
下午2点：上课<br />
下午5点半：下课、吃临时晚餐、打篮球<br />
晚上6：50：上晚自习<br />
晚上9点：放学、回家<br />
晚上9点半：吃饭、做作业<br />
晚上11点：洗脚睡觉<br />
  这就是当时我的日记的标准格式，写了三天后，语文老师抽了个课间休息熏陶了下我。又写了三天，语文老师平静的告诉我，下周起不用交日记了。我觉得当时他应该对我绝望了。很&#8203;感激他没有像其他老师那样，因为没有写好日记而罚我多做作业。<br />
<br />
  3月8号那天，协同mrcool全家、BT姐上街，准备过个和谐奥运的妇女节。先逛了赛博电脑城，我最喜欢瞅键鼠套装，正当我对着razer那7、8百的键盘流口水的时候&#8203;，突然发现一款razer标价400左右的鼠标居然几乎所有的配机工作人员人手一个，顿时感觉天旋地转了，决定以后键鼠套装不买这个牌子了。然后就是狂逛，在太阳百货的K&#8203;ANGWEI点里喜获一条XXXXL的运动裤，喜出望外，自从升级到1.8X后，好久都没穿过脚跟能踩到裤脚的裤子了。就这么一直逛啊逛，终于逛到了晚上6点，大家都顶不&#8203;住饥饿了，找了家粤菜馆一顿猛吃。吃的很开心，因为不是自己买的单。晚上9点50，终于到家了。总结一下，这一天逛了12个小时，破了我的历史记录，值得大书特书。<br />
  <br />
  最近还有一件值得高兴的事：火箭19连胜了，虽然我最喜欢的还是有kobe的湖人。<br />
<br />
  昨天听歌，找到自己喜欢的几首：<br />
 <br />
  阿桑的《受了点伤》、《叶子》，张栋梁的《小乌龟》， 马天宇的《依然在一起》， 罗文裕的《爱情漫游》。<br />
 <br />
  最后说一句，SaBlog的自动保存功能让我相当的郁闷，用IE8写这篇BLOG的时候，想看看那款鼠标是不是叫razer，就在搜索框里搜索，结果直接就把当前页给定位&#8203;过去了，点“返回”发现写的内容全没了，当时正写到妇女节那一段，我那个绝望~~撞墙的心都有了]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, March 11<br />
<br />
   每次在BLOG上胡乱涂鸦的时候老是为取什么名字而烦恼，比如“二三事”之类的名字都是实在想不出该叫什么而随便用的，今天觉得还是直接用“日记”好了。<br />
   提起日记，我想起了高三时候，语文老师突然要我们写日记，记录高三紧张“丰富”的每一天，每天都要交。我现在想起来都很佩服那些日记经常能得“优”的同学，能把吃了学，学&#8203;了吃的高三生活写得那么梦幻，实在是难得。我个人对“日记”的理解是：每日生活中有意义的事，而对于高三的学上，上学读书当然是最有意义的事（不过私下里，当时我绝得打篮&#8203;球、翘课打传奇更有意义），所以老实的我老老实实地把日记写成这样： <br />
<br />
<br />
早上7点：起床、刷牙、洗脸、吃早餐<br />
早上7点半：上学去<br />
早上8点：上课<br />
中午12点：放学回家<br />
中午12点半：吃饭、午休<br />
下午1点半：起床、洗脸、上课<br />
下午2点：上课<br />
下午5点半：下课、吃临时晚餐、打篮球<br />
晚上6：50：上晚自习<br />
晚上9点：放学、回家<br />
晚上9点半：吃饭、做作业<br />
晚上11点：洗脚睡觉<br />
  这就是当时我的日记的标准格式，写了三天后，语文老师抽了个课间休息熏陶了下我。又写了三天，语文老师平静的告诉我，下周起不用交日记了。我觉得当时他应该对我绝望了。很&#8203;感激他没有像其他老师那样，因为没有写好日记而罚我多做作业。<br />
<br />
  3月8号那天，协同mrcool全家、BT姐上街，准备过个和谐奥运的妇女节。先逛了赛博电脑城，我最喜欢瞅键鼠套装，正当我对着razer那7、8百的键盘流口水的时候&#8203;，突然发现一款razer标价400左右的鼠标居然几乎所有的配机工作人员人手一个，顿时感觉天旋地转了，决定以后键鼠套装不买这个牌子了。然后就是狂逛，在太阳百货的K&#8203;ANGWEI点里喜获一条XXXXL的运动裤，喜出望外，自从升级到1.8X后，好久都没穿过脚跟能踩到裤脚的裤子了。就这么一直逛啊逛，终于逛到了晚上6点，大家都顶不&#8203;住饥饿了，找了家粤菜馆一顿猛吃。吃的很开心，因为不是自己买的单。晚上9点50，终于到家了。总结一下，这一天逛了12个小时，破了我的历史记录，值得大书特书。<br />
  <br />
  最近还有一件值得高兴的事：火箭19连胜了，虽然我最喜欢的还是有kobe的湖人。<br />
<br />
  昨天听歌，找到自己喜欢的几首：<br />
 <br />
  阿桑的《受了点伤》、《叶子》，张栋梁的《小乌龟》， 马天宇的《依然在一起》， 罗文裕的《爱情漫游》。<br />
 <br />
  最后说一句，SaBlog的自动保存功能让我相当的郁闷，用IE8写这篇BLOG的时候，想看看那款鼠标是不是叫razer，就在搜索框里搜索，结果直接就把当前页给定位&#8203;过去了，点“返回”发现写的内容全没了，当时正写到妇女节那一段，我那个绝望~~撞墙的心都有了]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[二三事]]></title>
			<link>http://boxcounter.com/showthread.php?tid=63</link>
			<pubDate>Thu, 27 Oct 2011 08:12:12 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=63</guid>
			<description><![CDATA[boxcounter,<br />
2008, February 28<br />
<br />
  有一段时间没更新blog了，期间还尝试着把blog程序换成了Wordpress，无奈没耐心认真的玩转它，反而在用的时候更怀念现在用的这个，于是又换回来了。失去后&#8203;才想起也许当初应该珍惜。<br />
<br />
  我写的东西一般分为两种：乱七八糟、想到哪写到哪的胡诌，和技术学习上的感悟、心得。这段时间没更新blog也算是这两方面都没啥好说。年前正感叹狗X运真好，居然在这个&#8203;朝着火车站排队人群里扔块砖就能砸死7、8个“黄牛”的年代里买到了票，结果来了场很不给面子的雪。技术学习上呢，最近主要是在学文件驱动，啃了一个多月了，写的程序仍然&#8203;是半死不活的，经常弹出蓝屏吓人，每次都会安慰自己“蓝屏的，好喝的”~~  有了些经验、感悟，但是自己都不能保证是正确的，所以也就无所可说的。<br />
<br />
  前些天终于下定决心要把跟我同岁的多梦症给好好治治，跑到宝安的一家中医馆去查了查。结果很吓人，“肠胃、肝脏很湿热，不能喝酒、熬夜”~  于是老老实实的买了几副中药，买好了药罐，慢慢熬。医生嘱咐：4碗水煎成一碗，结果我很争气的把四碗水煎成了两碗半~药很贵，于是只好全喝完。也许有人会说2碗半不算啥，&#8203;但是哥们我得告诉你，晚饭我吃的是汤面~~  这还没完，医生好心的给我开了副补药，配合猪心隔水炖，睡前喝。我很听话，在喝完药没多久又喝了钵猪心汤，喝的时候我很郁闷：丫的早知道不买这么大个的猪心了，这么多水~&#8203;~~<br />
<br />
  最近主要在听三首歌曲：<br />
  张惠妹的《记住》、林俊杰的《不懂》，这两首基本上是用的同一曲调，词不同。还有一首是马天宇的《依然在一起》。<br />
<br />
     《依然在一起》<br />
手心仍有一丝温柔残留<br />
孤独的夜是谁让我等候<br />
何时微笑变成一种奢求<br />
就算时间倒流也无法挽留<br />
那些因为年轻犯的错<br />
就像秋天的落叶早已经随风而过<br />
但有些话我始终不能说<br />
如果我们依然在一起<br />
错过的甜蜜是否还能继续<br />
曾经一起取暖的外衣<br />
丢失在哪里<br />
如果我们依然在一起<br />
再黑的夜晚我也无需躲避<br />
一段永远封存的记忆<br />
随风而去]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, February 28<br />
<br />
  有一段时间没更新blog了，期间还尝试着把blog程序换成了Wordpress，无奈没耐心认真的玩转它，反而在用的时候更怀念现在用的这个，于是又换回来了。失去后&#8203;才想起也许当初应该珍惜。<br />
<br />
  我写的东西一般分为两种：乱七八糟、想到哪写到哪的胡诌，和技术学习上的感悟、心得。这段时间没更新blog也算是这两方面都没啥好说。年前正感叹狗X运真好，居然在这个&#8203;朝着火车站排队人群里扔块砖就能砸死7、8个“黄牛”的年代里买到了票，结果来了场很不给面子的雪。技术学习上呢，最近主要是在学文件驱动，啃了一个多月了，写的程序仍然&#8203;是半死不活的，经常弹出蓝屏吓人，每次都会安慰自己“蓝屏的，好喝的”~~  有了些经验、感悟，但是自己都不能保证是正确的，所以也就无所可说的。<br />
<br />
  前些天终于下定决心要把跟我同岁的多梦症给好好治治，跑到宝安的一家中医馆去查了查。结果很吓人，“肠胃、肝脏很湿热，不能喝酒、熬夜”~  于是老老实实的买了几副中药，买好了药罐，慢慢熬。医生嘱咐：4碗水煎成一碗，结果我很争气的把四碗水煎成了两碗半~药很贵，于是只好全喝完。也许有人会说2碗半不算啥，&#8203;但是哥们我得告诉你，晚饭我吃的是汤面~~  这还没完，医生好心的给我开了副补药，配合猪心隔水炖，睡前喝。我很听话，在喝完药没多久又喝了钵猪心汤，喝的时候我很郁闷：丫的早知道不买这么大个的猪心了，这么多水~&#8203;~~<br />
<br />
  最近主要在听三首歌曲：<br />
  张惠妹的《记住》、林俊杰的《不懂》，这两首基本上是用的同一曲调，词不同。还有一首是马天宇的《依然在一起》。<br />
<br />
     《依然在一起》<br />
手心仍有一丝温柔残留<br />
孤独的夜是谁让我等候<br />
何时微笑变成一种奢求<br />
就算时间倒流也无法挽留<br />
那些因为年轻犯的错<br />
就像秋天的落叶早已经随风而过<br />
但有些话我始终不能说<br />
如果我们依然在一起<br />
错过的甜蜜是否还能继续<br />
曾经一起取暖的外衣<br />
丢失在哪里<br />
如果我们依然在一起<br />
再黑的夜晚我也无需躲避<br />
一段永远封存的记忆<br />
随风而去]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[感受上海地铁]]></title>
			<link>http://boxcounter.com/showthread.php?tid=62</link>
			<pubDate>Thu, 27 Oct 2011 08:10:38 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=62</guid>
			<description><![CDATA[boxcounter,<br />
2008, January 4<br />
<br />
  这两天在上海乘坐了几次地铁，颇有感触，所以专门用一篇 blog 来记录。<br />
  <br />
  昨天早上是8点15到锦江乐园地铁站等车的，找了人相对少的候车口排队，在我前面约莫有十七八个人。锦江乐园站是没有玻璃护窗的，人面前就是两条铁轨。黄色警戒线离月台边&#8203;缘约莫有一米的距离，这个距离还是蛮安全的，可惜的是它被人们无视了：我前面的十七八个站成3排，而第4排的我刚刚踩在警戒线上，第一排的人基本上都是脚尖靠在月台边缘上&#8203;，我很担心后面的人一不留神就把他们给挤下去。。。<br />
  <br />
  眼见着地铁进站了，候车的人们分别摆出两种姿态：<br />
  一、紧紧背包，调整双脚的宽度，貌似想站的更稳。<br />
  二、紧紧背包，重心稍稍前倾，双肘、或前胸贴着前面人的后背。<br />
  <br />
  按照挤车的习惯，我也摆出了第二种姿势，mrcool同学看到了，告诉我：你不用挤，后面的人会帮你挤的~~ 我顿悟姿势一的原理~~~于是也调整下脚间距，按首挺胸，紧紧的抱住本本包。<br />
  <br />
  果不其然，车门一开，就感受到一股力如排山倒海般拍到后背，刚调整好的重心立刻就没了~~上车的还好，一次能上个4、5个，身材苗条的话还能多挤一个。可是苦了下车的人了&#8203;，一约莫1米75的哥们，双手把包举过头顶，试图以一己之力抗衡众人~~~我感叹了一句：在上海，如果40岁了还没有私家车，就退休吧，您哪还有力气挤地铁啊。。。又想了&#8203;想：不对，不用退休，可以每天早点来排队，让后面的人帮你挤就可以了。<br />
  <br />
  另外有一个新发现：上海地铁月台上维持秩序的工作人员相对于深圳地铁的工作人员来说，要多干一件事：在列车门关不上的时候，把卡在门口的人给硬塞进去~~<br />
  <br />
  就这样，我终于挤上了第四列地铁，在车厢里，我想起了高中历史书上的一个片段：当年美国人从非洲把奴隶运送回国的时候，把上百个奴隶塞进一艘小船。感同身受~<br />
  <br />
  我可以不扶任何东西，在列车加、减速的时候稳稳的站住，甚至尝试用金鸡独立的姿势站了一会，很有安全感，一点都不用担心摔倒。<br />
  <br />
  我的左手边是一个身材很娇小的女士，被挤成一个很别扭的姿势，我决定帮助她。于是我试图用力往右挤，给她空间，在经过两三次努力后，我放弃了~~我想起了一个名词：不可抗&#8203;力。<br />
  <br />
  一路上其他的都还蛮和谐，而且很幸运的时候我下车的时候，车厢里的人已经不都了，而且外面排队的人也很少，所以很顺利的下车了。<br />
  <br />
  另：今天早上7点15去排队，发现人出奇的少，这让我有些失落。]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, January 4<br />
<br />
  这两天在上海乘坐了几次地铁，颇有感触，所以专门用一篇 blog 来记录。<br />
  <br />
  昨天早上是8点15到锦江乐园地铁站等车的，找了人相对少的候车口排队，在我前面约莫有十七八个人。锦江乐园站是没有玻璃护窗的，人面前就是两条铁轨。黄色警戒线离月台边&#8203;缘约莫有一米的距离，这个距离还是蛮安全的，可惜的是它被人们无视了：我前面的十七八个站成3排，而第4排的我刚刚踩在警戒线上，第一排的人基本上都是脚尖靠在月台边缘上&#8203;，我很担心后面的人一不留神就把他们给挤下去。。。<br />
  <br />
  眼见着地铁进站了，候车的人们分别摆出两种姿态：<br />
  一、紧紧背包，调整双脚的宽度，貌似想站的更稳。<br />
  二、紧紧背包，重心稍稍前倾，双肘、或前胸贴着前面人的后背。<br />
  <br />
  按照挤车的习惯，我也摆出了第二种姿势，mrcool同学看到了，告诉我：你不用挤，后面的人会帮你挤的~~ 我顿悟姿势一的原理~~~于是也调整下脚间距，按首挺胸，紧紧的抱住本本包。<br />
  <br />
  果不其然，车门一开，就感受到一股力如排山倒海般拍到后背，刚调整好的重心立刻就没了~~上车的还好，一次能上个4、5个，身材苗条的话还能多挤一个。可是苦了下车的人了&#8203;，一约莫1米75的哥们，双手把包举过头顶，试图以一己之力抗衡众人~~~我感叹了一句：在上海，如果40岁了还没有私家车，就退休吧，您哪还有力气挤地铁啊。。。又想了&#8203;想：不对，不用退休，可以每天早点来排队，让后面的人帮你挤就可以了。<br />
  <br />
  另外有一个新发现：上海地铁月台上维持秩序的工作人员相对于深圳地铁的工作人员来说，要多干一件事：在列车门关不上的时候，把卡在门口的人给硬塞进去~~<br />
  <br />
  就这样，我终于挤上了第四列地铁，在车厢里，我想起了高中历史书上的一个片段：当年美国人从非洲把奴隶运送回国的时候，把上百个奴隶塞进一艘小船。感同身受~<br />
  <br />
  我可以不扶任何东西，在列车加、减速的时候稳稳的站住，甚至尝试用金鸡独立的姿势站了一会，很有安全感，一点都不用担心摔倒。<br />
  <br />
  我的左手边是一个身材很娇小的女士，被挤成一个很别扭的姿势，我决定帮助她。于是我试图用力往右挤，给她空间，在经过两三次努力后，我放弃了~~我想起了一个名词：不可抗&#8203;力。<br />
  <br />
  一路上其他的都还蛮和谐，而且很幸运的时候我下车的时候，车厢里的人已经不都了，而且外面排队的人也很少，所以很顺利的下车了。<br />
  <br />
  另：今天早上7点15去排队，发现人出奇的少，这让我有些失落。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[新年的第一天]]></title>
			<link>http://boxcounter.com/showthread.php?tid=61</link>
			<pubDate>Thu, 27 Oct 2011 08:09:32 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=61</guid>
			<description><![CDATA[boxcounter,<br />
2008, January 1<br />
<br />
  今天是2008年的第一天，新年新气象：<br />
<br />
  早上睡到10点，然后起来收拾行李。mrcool同学提示，今天上海-1-6摄氏度~所以穿上了一件厚厚的冬衣，前些天回老家，舅妈给买的，喜欢<br />
<br />
  12点50，登上去上海的飞机，飞机上空姐提示：今天上海-1-7摄氏度，mrcool这个骗子~~<br />
<br />
  在昏睡前，夸了一句东航的空姐MM还蛮漂亮的，结果被mrcool这厮鄙视了~~（其实我真的觉得还不错，起码不难看~）<br />
<br />
  下午4点，到达虹桥机场，坐了半个小时的公车，然后见识了传说中“不用扶也能站的很稳”的上海地铁~果然很稳~差点把我挤出车舱~<br />
<br />
  晚上六点，终于到了下榻的宾馆，放下行李，就跟随mrcool来到一条小吃街，都是烧烤、炸烤之类的东西，很合胃口。还专门去吃了念叨已久的煎饺，结果很是失望，除了皮就&#8203;是白菜。。。<br />
<br />
  最后，在这新年的第一天，借用一下mrcool同学最近常挂在嘴边上的一句话：“希望2008年能好一些”~~~]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2008, January 1<br />
<br />
  今天是2008年的第一天，新年新气象：<br />
<br />
  早上睡到10点，然后起来收拾行李。mrcool同学提示，今天上海-1-6摄氏度~所以穿上了一件厚厚的冬衣，前些天回老家，舅妈给买的，喜欢<br />
<br />
  12点50，登上去上海的飞机，飞机上空姐提示：今天上海-1-7摄氏度，mrcool这个骗子~~<br />
<br />
  在昏睡前，夸了一句东航的空姐MM还蛮漂亮的，结果被mrcool这厮鄙视了~~（其实我真的觉得还不错，起码不难看~）<br />
<br />
  下午4点，到达虹桥机场，坐了半个小时的公车，然后见识了传说中“不用扶也能站的很稳”的上海地铁~果然很稳~差点把我挤出车舱~<br />
<br />
  晚上六点，终于到了下榻的宾馆，放下行李，就跟随mrcool来到一条小吃街，都是烧烤、炸烤之类的东西，很合胃口。还专门去吃了念叨已久的煎饺，结果很是失望，除了皮就&#8203;是白菜。。。<br />
<br />
  最后，在这新年的第一天，借用一下mrcool同学最近常挂在嘴边上的一句话：“希望2008年能好一些”~~~]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[收获]]></title>
			<link>http://boxcounter.com/showthread.php?tid=60</link>
			<pubDate>Thu, 27 Oct 2011 08:08:49 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=60</guid>
			<description><![CDATA[boxcounter,<br />
2007, December 6<br />
<br />
  上周日，我参加了几年的深圳市跆拳道锦标赛，套用小学生写作文的套路，情况应该是这样：”我校XX年级XX班同学boxcounter，在比赛中奋力拼搏，以顽强的拼搏精&#8203;神，摘取了本届深圳市跆拳道锦标赛成人组72-78公斤级的铜牌~“<br />
<br />
  算了算，去年12月开始跟着刘教练学跆拳道，到现在正好一年了，这一年的学习收获颇多，真的很感激教练这一年来每堂课辛辛苦苦的付出。为了培养我们的实战技巧，还专门请来&#8203;多个门派的高手来指点、切磋。这里也感谢高教练，一位同样痴迷格斗、要求严格的好老师。也感谢黄师傅：刚开始练跆拳道的时候，只是抱着边玩边学的想法，所以人少的时候会偷&#8203;懒不去，有一次开玩笑的时候，黄师傅无意的说了句”跆拳道很锻炼人的意志，要坚持“，这句让之后的我开始认真的对待每堂课。<br />
<br />
  也感谢那天支持我的好友，比赛那天我的啦啦队那叫一个壮观，公司里在深圳的几乎全都去了，还有怀秋、旺哥，拖家带口给我加油。我比赛的时候，给我的加油声是整个体育馆最响&#8203;的，BT姐说当时体育馆里人都往他们这边看～<br />
<br />
  放上一张颁奖时黄师傅帮照的照片，我总结了下特点：很黑（人）、很白（牙齿）～<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=5" target="_blank">takquandao.jpg</a> (Size: 685.69 KB / Downloads: 19)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[boxcounter,<br />
2007, December 6<br />
<br />
  上周日，我参加了几年的深圳市跆拳道锦标赛，套用小学生写作文的套路，情况应该是这样：”我校XX年级XX班同学boxcounter，在比赛中奋力拼搏，以顽强的拼搏精&#8203;神，摘取了本届深圳市跆拳道锦标赛成人组72-78公斤级的铜牌~“<br />
<br />
  算了算，去年12月开始跟着刘教练学跆拳道，到现在正好一年了，这一年的学习收获颇多，真的很感激教练这一年来每堂课辛辛苦苦的付出。为了培养我们的实战技巧，还专门请来&#8203;多个门派的高手来指点、切磋。这里也感谢高教练，一位同样痴迷格斗、要求严格的好老师。也感谢黄师傅：刚开始练跆拳道的时候，只是抱着边玩边学的想法，所以人少的时候会偷&#8203;懒不去，有一次开玩笑的时候，黄师傅无意的说了句”跆拳道很锻炼人的意志，要坚持“，这句让之后的我开始认真的对待每堂课。<br />
<br />
  也感谢那天支持我的好友，比赛那天我的啦啦队那叫一个壮观，公司里在深圳的几乎全都去了，还有怀秋、旺哥，拖家带口给我加油。我比赛的时候，给我的加油声是整个体育馆最响&#8203;的，BT姐说当时体育馆里人都往他们这边看～<br />
<br />
  放上一张颁奖时黄师傅帮照的照片，我总结了下特点：很黑（人）、很白（牙齿）～<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><img src="images/attachtypes/image.gif" border="0" alt=".jpg" />&nbsp;&nbsp;<a href="attachment.php?aid=5" target="_blank">takquandao.jpg</a> (Size: 685.69 KB / Downloads: 19)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
	</channel>
</rss>
