<?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>Sun, 20 May 2012 20:39:42 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[关于STATUS_INVALID_DEVICE_OBJECT_PARAMETER和STATUS_MOUNT_POINT_NOT_RESOLVED]]></title>
			<link>http://boxcounter.com/showthread.php?tid=86</link>
			<pubDate>Sun, 20 May 2012 10:51:16 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=86</guid>
			<description><![CDATA[boxcounter<br />
2012-05-20 周日<br />
<br />
很久之前，我写了篇<a href="http://www.boxcounter.com/showthread.php?tid=38" target="_blank">关于STATUS_INVALID_DEVICE_OBJECT_PARAMETER的blog</a>，里面提到使用STATUS_REPARSE的FsFilter（后简称为R-FsFilter）对上层FsFilter造成的恶劣干扰。<br />
<br />
这两天看Alex Carp的文章，发现事情貌似有转机。具体参考他的<a href="http://fsfilters.blogspot.com/2012/02/reparsing-to-different-volume-in-win7.html" target="_blank">Reparsing to a Different Volume in Win7 and Win8</a>（需要爬墙）。<br />
<br />
我总结一下：<br />
目前的win8提供了一种新的ECP和相应的数据结构，保证在返回STATUS_MOUNT_POINT_NOT_RESOLVED的时候开发者可以获得目标FO的FLT&#8203;_FILE_NAME_INFORMATION和FLT_INSTANCE。<br />
用我那篇blog的原型就是，当驱动A调用FltCreateFile失败后（Alex的文章里只提到了STATUS_MOUNT_POINT_NOT_RESOLVED&#8203;，但我猜测对STATUS_INVALID_DEVICE_OBJECT_PARAMETER应该也是适用的，我还没有动手测试，只是看IopCheckTopDevic&#8203;eHint的实现做出的猜测），可以从ECP中获取到本次打开操作的目标FO的FLT_FILE_NAME_INFORMATION和FLT_INSTANCE，然后再次&#8203;FltCreateFile就可以了。<br />
<br />
说来简单，但实际上影响挺大的，这相当于要求所有的FsFilter开发者在调用FltCreateFile时都处理这种错误。仅仅是因为目标系统里可能会存在一个R-FsFilter。<br />
<br />
相信不会有太多的开发者会多写这些代码。<br />
而且这个错误对上层FsFilter的开发者来说根本就不是问题。如果在客户机上出现这种问题，完全可以如此解释：“你看，卸载您安装的这个产品（姑且称为T）的驱动后，&#8203;我公司的产品就能正常工作了。但是只要一安装它，我公司的产品就出问题了，你看你看，另一个公司的产品也不能工作了。这明显是T的问题，跟我公司的产品没有半毛钱关系。”&#8203;<br />
<br />
悲催的是R-FsFilter开发者，知道问题有解决方案，但是却不能在自己的代码里解决……。<br />
<br />
或者，R-FsFilter开发者在开发完之后，再多写一个紧贴着它的上层驱动，专门处理STATUS_MOUNT_POINT_NOT_RESOLVED/STATUS_INVALID_DEVICE_OBJECT_PARAMETER？这要求必须使用支持固定加载层次的minifilter框架，并且MS要足够给面子提供&#8203;两个相邻的Altitude，不过以我之前申请Altitude的经验，貌似有些难度。<br />
<br />
另外推荐Alex-Cap的几篇关于reparse技术的博文。其实他blog的每篇技术文章都推荐仔细阅读，我几乎备份了他所有的博文……<br />
<br />
注：由于本人能力有限，行文难免有错，请不吝赐教邮件联系（ns.boxcounter[a]gmail.com，博客里垃圾回复太多了，人工删不过来，所以禁用回复功能了），感谢。]]></description>
			<content:encoded><![CDATA[boxcounter<br />
2012-05-20 周日<br />
<br />
很久之前，我写了篇<a href="http://www.boxcounter.com/showthread.php?tid=38" target="_blank">关于STATUS_INVALID_DEVICE_OBJECT_PARAMETER的blog</a>，里面提到使用STATUS_REPARSE的FsFilter（后简称为R-FsFilter）对上层FsFilter造成的恶劣干扰。<br />
<br />
这两天看Alex Carp的文章，发现事情貌似有转机。具体参考他的<a href="http://fsfilters.blogspot.com/2012/02/reparsing-to-different-volume-in-win7.html" target="_blank">Reparsing to a Different Volume in Win7 and Win8</a>（需要爬墙）。<br />
<br />
我总结一下：<br />
目前的win8提供了一种新的ECP和相应的数据结构，保证在返回STATUS_MOUNT_POINT_NOT_RESOLVED的时候开发者可以获得目标FO的FLT&#8203;_FILE_NAME_INFORMATION和FLT_INSTANCE。<br />
用我那篇blog的原型就是，当驱动A调用FltCreateFile失败后（Alex的文章里只提到了STATUS_MOUNT_POINT_NOT_RESOLVED&#8203;，但我猜测对STATUS_INVALID_DEVICE_OBJECT_PARAMETER应该也是适用的，我还没有动手测试，只是看IopCheckTopDevic&#8203;eHint的实现做出的猜测），可以从ECP中获取到本次打开操作的目标FO的FLT_FILE_NAME_INFORMATION和FLT_INSTANCE，然后再次&#8203;FltCreateFile就可以了。<br />
<br />
说来简单，但实际上影响挺大的，这相当于要求所有的FsFilter开发者在调用FltCreateFile时都处理这种错误。仅仅是因为目标系统里可能会存在一个R-FsFilter。<br />
<br />
相信不会有太多的开发者会多写这些代码。<br />
而且这个错误对上层FsFilter的开发者来说根本就不是问题。如果在客户机上出现这种问题，完全可以如此解释：“你看，卸载您安装的这个产品（姑且称为T）的驱动后，&#8203;我公司的产品就能正常工作了。但是只要一安装它，我公司的产品就出问题了，你看你看，另一个公司的产品也不能工作了。这明显是T的问题，跟我公司的产品没有半毛钱关系。”&#8203;<br />
<br />
悲催的是R-FsFilter开发者，知道问题有解决方案，但是却不能在自己的代码里解决……。<br />
<br />
或者，R-FsFilter开发者在开发完之后，再多写一个紧贴着它的上层驱动，专门处理STATUS_MOUNT_POINT_NOT_RESOLVED/STATUS_INVALID_DEVICE_OBJECT_PARAMETER？这要求必须使用支持固定加载层次的minifilter框架，并且MS要足够给面子提供&#8203;两个相邻的Altitude，不过以我之前申请Altitude的经验，貌似有些难度。<br />
<br />
另外推荐Alex-Cap的几篇关于reparse技术的博文。其实他blog的每篇技术文章都推荐仔细阅读，我几乎备份了他所有的博文……<br />
<br />
注：由于本人能力有限，行文难免有错，请不吝赐教邮件联系（ns.boxcounter[a]gmail.com，博客里垃圾回复太多了，人工删不过来，所以禁用回复功能了），感谢。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[2012-5-4的一些唠叨]]></title>
			<link>http://boxcounter.com/showthread.php?tid=85</link>
			<pubDate>Tue, 08 May 2012 17:42:28 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=85</guid>
			<description><![CDATA[趁着五一假期，把年假请了回家探亲。<br />
<br />
    老爹修佛，从开始修到如今5年多，时间虽不长，但是很虔诚。最近的四年大部分时间都在当阳玉泉寺修行。目前受的是菩萨戒。<br />
<br />
    我回家，老爹自然想熏陶熏陶我，于是每天我在家陪他聊天，聊不了多久他就会聊到佛相关的话题上，然后就开始强烈建议我看看一些佛学论坛，是真正的论坛，不是网络BBS。里&#8203;面是一些修佛居士在里面忏悔自己做过的错事，或者讲述自己的心得等等。一般我会非强烈抗议然后逃之夭夭。有时候实在溜不掉就只好从这些佛学相关视屏里挑点清淡的，比如主题&#8203;为修佛或者某位法师传记类的连续剧。看得次数最多的是《百年虚云》，讲的是晚清虚云法师一生的，片子是他的弟子释本焕长老监制拍摄的，也就是深圳弘法寺的本焕长老。目前玉&#8203;泉寺主持也是虚云法师的弟子。<br />
<br />
    我只看了个开头，从虚云法师出生到他出家修行约莫十年的光景。有一段让我点想法想唠叨。<br />
<br />
    虚云法师是在娶妻2年后从家中逃离，然后出家。没有事先告知父母，只是妻子偷听得知了这一事情。出家后，父母妻妾四处找寻，多年后终于寻访到他的下落。但是虚云法师坚决的&#8203;拒绝掉了所有的探访，其妻设计见到了他，也被他坚决请回。他的父亲当时是一名官员，于是使用了一些手段想强行带他走，于是虚云法师只好跑到庙的后山，找个洞继续修行。最后&#8203;他的父亲年事高、身体差，辞官回家前颤巍巍的爬上后山呼唤他，想见他最后一面。虚云法师心有不忍，但也最终没有见父亲。最后，辞官、有病的父亲回老家后为了治病耗尽了家里&#8203;所有的财产，连最后一栋老房子也卖了，虚云法师的母亲和妻妾都决定出家。后面的情节我没有再看下去了。<br />
<br />
    我想唠叨的是，虚云法师这种做法该如何解读？<br />
<br />
    我问过我老爹，明显我老爹没有纠结过这段情节，只好喃喃回答：“虚云法师是为了度众生”，话外之音应该就是所谓“舍小家为大家”。<br />
<br />
    但是我的理解是，连自己的生身父母都不在乎的人，他会在乎别人的父母，会在乎众生？或者说，会有多在乎众生？换句话说，“一屋不扫，何以扫天下？”。当年苏东坡和朋友（经&#8203;查证，是章惇，参见《帝国政界往事》）一起去到一处险景游玩，有一条深涧，朋友抓着树藤荡到对面的石壁上提了类似“XX与XXX到此一游”的字，然后荡回来。苏东坡感叹，&#8203;如果这个朋友当政，苍生可能要受苦了。苏东坡的解释是，他连自己的命都不在乎，又怎么会在乎别人的命。最后的事实也确实如东坡先生所感叹。<br />
<br />
    我所了解的各种宗教信仰、思想，都明确的肯定孝道。诸如儒、天主、基督、佛，前三者就不用说了，佛家《地藏经》主要就是讲孝道的。<br />
<br />
    按我的想法，一个虔诚的信徒，应该在尽完孝道之后，再去修自己的行。退一步说，即便做不到服侍双亲于身前直至双亲离世，也应该做好充足的准备（如几亩薄田，几名家仆等）后&#8203;，再离开。<br />
<br />
    电视中（我不清楚现实中是否如此）虚云法师的这种做法最后的结果是这么的凄惨，我不清楚是监制本焕大师有意为之以凸显虚云法师心怀佛祖心怀苍生之胸怀，还是只是想原原本本&#8203;的呈现出事实。但是就我而言，我想到了建国初期风靡全国的“光荣事迹”：某某为了练好最后一炉钢、割完最后一拢麦，连临终的父母都顾不上看一眼，让亲人抱憾离世。这种做法&#8203;我觉得是完完全全彻彻底底的混蛋做法，其背后隐藏的是一种畸形的思想推动力。借用迂阔的儒家说法，这有悖人伦。这种做法我能接受的原因底线是：如果不这么做会导致千千万万&#8203;个生命、家庭受到惨痛的损失。比如：你是一名正在领导卫国战争的高级将领，离岗奔丧可能会导致国破家亡。<br />
<br />
    也许虚云法师也许真能做到决然拒老父却又慈悲度苍生，但我真心不认为这种做法值得信徒称道。<br />
<br />
    这个想法就先唠叨到这，目前就这么些想法，以后想到别的了再补充。<br />
<br />
    还有一个跟佛家相关的问题。<br />
<br />
    有不少修佛人被问道修佛的原因，或者向别人传道时候，都会说：“修佛能死后入西方极乐世界”。这种说法是不是也是一种利益诱惑？<br />
<br />
    另外我还见过这样的传道：把原本“信佛，佛祖保佑你”布道成“不信佛，佛祖就惩罚你”，不知道天上的佛祖看到如此信徒，是不是也会有一种淡淡的忧伤于胸中。也许参差不齐的&#8203;信徒才是佛家宗旨的最大破坏源。<br />
<br />
    其实原本还有一个话题想说说的，结果写到这里记不起来主题是什么了……以后想起来再侃吧。<br />
<br />
    注：我并不反对宗教信仰，比如说我其实很支持我父母信佛，老人有精神寄托是件好事，积德行善总是好的。我也不是坚定的科学主义者，世间貌似有不少事情无法用现在的科学来解&#8203;释。科学与宗教也许只是解释这个世界的不同方法。对于带有所谓“迷信思想”的宗教信仰，我的态度是，不全信，也不完全不信。]]></description>
			<content:encoded><![CDATA[趁着五一假期，把年假请了回家探亲。<br />
<br />
    老爹修佛，从开始修到如今5年多，时间虽不长，但是很虔诚。最近的四年大部分时间都在当阳玉泉寺修行。目前受的是菩萨戒。<br />
<br />
    我回家，老爹自然想熏陶熏陶我，于是每天我在家陪他聊天，聊不了多久他就会聊到佛相关的话题上，然后就开始强烈建议我看看一些佛学论坛，是真正的论坛，不是网络BBS。里&#8203;面是一些修佛居士在里面忏悔自己做过的错事，或者讲述自己的心得等等。一般我会非强烈抗议然后逃之夭夭。有时候实在溜不掉就只好从这些佛学相关视屏里挑点清淡的，比如主题&#8203;为修佛或者某位法师传记类的连续剧。看得次数最多的是《百年虚云》，讲的是晚清虚云法师一生的，片子是他的弟子释本焕长老监制拍摄的，也就是深圳弘法寺的本焕长老。目前玉&#8203;泉寺主持也是虚云法师的弟子。<br />
<br />
    我只看了个开头，从虚云法师出生到他出家修行约莫十年的光景。有一段让我点想法想唠叨。<br />
<br />
    虚云法师是在娶妻2年后从家中逃离，然后出家。没有事先告知父母，只是妻子偷听得知了这一事情。出家后，父母妻妾四处找寻，多年后终于寻访到他的下落。但是虚云法师坚决的&#8203;拒绝掉了所有的探访，其妻设计见到了他，也被他坚决请回。他的父亲当时是一名官员，于是使用了一些手段想强行带他走，于是虚云法师只好跑到庙的后山，找个洞继续修行。最后&#8203;他的父亲年事高、身体差，辞官回家前颤巍巍的爬上后山呼唤他，想见他最后一面。虚云法师心有不忍，但也最终没有见父亲。最后，辞官、有病的父亲回老家后为了治病耗尽了家里&#8203;所有的财产，连最后一栋老房子也卖了，虚云法师的母亲和妻妾都决定出家。后面的情节我没有再看下去了。<br />
<br />
    我想唠叨的是，虚云法师这种做法该如何解读？<br />
<br />
    我问过我老爹，明显我老爹没有纠结过这段情节，只好喃喃回答：“虚云法师是为了度众生”，话外之音应该就是所谓“舍小家为大家”。<br />
<br />
    但是我的理解是，连自己的生身父母都不在乎的人，他会在乎别人的父母，会在乎众生？或者说，会有多在乎众生？换句话说，“一屋不扫，何以扫天下？”。当年苏东坡和朋友（经&#8203;查证，是章惇，参见《帝国政界往事》）一起去到一处险景游玩，有一条深涧，朋友抓着树藤荡到对面的石壁上提了类似“XX与XXX到此一游”的字，然后荡回来。苏东坡感叹，&#8203;如果这个朋友当政，苍生可能要受苦了。苏东坡的解释是，他连自己的命都不在乎，又怎么会在乎别人的命。最后的事实也确实如东坡先生所感叹。<br />
<br />
    我所了解的各种宗教信仰、思想，都明确的肯定孝道。诸如儒、天主、基督、佛，前三者就不用说了，佛家《地藏经》主要就是讲孝道的。<br />
<br />
    按我的想法，一个虔诚的信徒，应该在尽完孝道之后，再去修自己的行。退一步说，即便做不到服侍双亲于身前直至双亲离世，也应该做好充足的准备（如几亩薄田，几名家仆等）后&#8203;，再离开。<br />
<br />
    电视中（我不清楚现实中是否如此）虚云法师的这种做法最后的结果是这么的凄惨，我不清楚是监制本焕大师有意为之以凸显虚云法师心怀佛祖心怀苍生之胸怀，还是只是想原原本本&#8203;的呈现出事实。但是就我而言，我想到了建国初期风靡全国的“光荣事迹”：某某为了练好最后一炉钢、割完最后一拢麦，连临终的父母都顾不上看一眼，让亲人抱憾离世。这种做法&#8203;我觉得是完完全全彻彻底底的混蛋做法，其背后隐藏的是一种畸形的思想推动力。借用迂阔的儒家说法，这有悖人伦。这种做法我能接受的原因底线是：如果不这么做会导致千千万万&#8203;个生命、家庭受到惨痛的损失。比如：你是一名正在领导卫国战争的高级将领，离岗奔丧可能会导致国破家亡。<br />
<br />
    也许虚云法师也许真能做到决然拒老父却又慈悲度苍生，但我真心不认为这种做法值得信徒称道。<br />
<br />
    这个想法就先唠叨到这，目前就这么些想法，以后想到别的了再补充。<br />
<br />
    还有一个跟佛家相关的问题。<br />
<br />
    有不少修佛人被问道修佛的原因，或者向别人传道时候，都会说：“修佛能死后入西方极乐世界”。这种说法是不是也是一种利益诱惑？<br />
<br />
    另外我还见过这样的传道：把原本“信佛，佛祖保佑你”布道成“不信佛，佛祖就惩罚你”，不知道天上的佛祖看到如此信徒，是不是也会有一种淡淡的忧伤于胸中。也许参差不齐的&#8203;信徒才是佛家宗旨的最大破坏源。<br />
<br />
    其实原本还有一个话题想说说的，结果写到这里记不起来主题是什么了……以后想起来再侃吧。<br />
<br />
    注：我并不反对宗教信仰，比如说我其实很支持我父母信佛，老人有精神寄托是件好事，积德行善总是好的。我也不是坚定的科学主义者，世间貌似有不少事情无法用现在的科学来解&#8203;释。科学与宗教也许只是解释这个世界的不同方法。对于带有所谓“迷信思想”的宗教信仰，我的态度是，不全信，也不完全不信。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[一个内核资源泄漏样本]]></title>
			<link>http://boxcounter.com/showthread.php?tid=84</link>
			<pubDate>Thu, 05 Apr 2012 14:43:44 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=84</guid>
			<description><![CDATA[开发过程中，我习惯会一直开着verifier进行测试，绝大部分非逻辑错误都能被揪出来。<br />
这两天测试部的同事反馈说貌似驱动有资源泄漏，我第一反应是“不会吧，有资源泄漏verifer早崩了”。<br />
测试了一下，发现还真是驱动嫌疑最大，于是开启verifer和压力测试工具，跑了一会，停掉驱动。发现没有bsod，一脑子不理解。<br />
看了下驱动停止后，内核内存情况：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>0: kd&gt; !poolused 7<br />
&nbsp;&nbsp; Sorting by&nbsp;&nbsp;NonPaged Pool Consumed<br />
<br />
&nbsp;&nbsp;Pool Used:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NonPaged&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Paged<br />
 Tag&nbsp;&nbsp;&nbsp;&nbsp;Allocs&nbsp;&nbsp;&nbsp;&nbsp;Frees&nbsp;&nbsp;&nbsp;&nbsp; Diff&nbsp;&nbsp;&nbsp;&nbsp; Used *&nbsp;&nbsp;Allocs&nbsp;&nbsp;&nbsp;&nbsp;Frees&nbsp;&nbsp;&nbsp;&nbsp; Diff&nbsp;&nbsp;&nbsp;&nbsp; Used<br />
 Proc&nbsp;&nbsp;&nbsp;&nbsp;12980&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;12979&nbsp;&nbsp;8618056 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;Process objects , Binary: nt!ps<br />
 LSwi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;2576384 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;initial work context <br />
 SePa&nbsp;&nbsp; 955604&nbsp;&nbsp; 942626&nbsp;&nbsp;&nbsp;&nbsp;12978&nbsp;&nbsp;2247904 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;&nbsp;&nbsp;Process audit image names and captured polity structures , Binary: nt!se<br />
 TCPt&nbsp;&nbsp;&nbsp;&nbsp;47617&nbsp;&nbsp;&nbsp;&nbsp;47580&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 37&nbsp;&nbsp;1423848 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;TCP/IP network protocol , Binary: TCP<br />
 SeTd&nbsp;&nbsp; 372125&nbsp;&nbsp; 359104&nbsp;&nbsp;&nbsp;&nbsp;13021&nbsp;&nbsp; 833344 *&nbsp;&nbsp;372125&nbsp;&nbsp; 359104&nbsp;&nbsp;&nbsp;&nbsp;13021&nbsp;&nbsp;1145088&nbsp;&nbsp;&nbsp;&nbsp;Security Token dynamic part , Binary: nt!se<br />
 .... 省略若干不相干信息<br />
 SEY6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY6', please update pooltag.txt<br />
 SEYC&nbsp;&nbsp;1448369&nbsp;&nbsp;1448369&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYC', please update pooltag.txt<br />
 SEYB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 47738&nbsp;&nbsp;&nbsp;&nbsp;47738&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYB', please update pooltag.txt<br />
 SEY5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY5', please update pooltag.txt<br />
 SEYA&nbsp;&nbsp;&nbsp;&nbsp;46294&nbsp;&nbsp;&nbsp;&nbsp;46294&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYA', please update pooltag.txt<br />
 SEY4&nbsp;&nbsp;1186033&nbsp;&nbsp;1186033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY4', please update pooltag.txt<br />
 SEY3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY3', please update pooltag.txt<br />
 SEY9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 47008&nbsp;&nbsp;&nbsp;&nbsp;47008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY9', please update pooltag.txt<br />
 SEY2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY2', please update pooltag.txt<br />
 SEY1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 54507&nbsp;&nbsp;&nbsp;&nbsp;54507&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY1', please update pooltag.txt<br />
 SEYD&nbsp;&nbsp;1419958&nbsp;&nbsp;1419958&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYD', please update pooltag.txt<br />
 .... 省略若干不相干信息<br />
 TOTAL&nbsp;&nbsp;&nbsp;&nbsp;79306657 79234060&nbsp;&nbsp;&nbsp;&nbsp;72597 22806272 38472704 38412253&nbsp;&nbsp;&nbsp;&nbsp;60451 29841272</code></div></div>
<br />
其中SEY?就是我的驱动使用的tag，发现没有泄漏，更一头雾水了。<br />
最后瞅到第一行，nnd，'Proc'这个tag明显有问题，基本没释放。<br />
检查了一下代码，发现之前从网上摘的一段获取进程路径的函数，里面的错误结束分支没有释放EPREOCESS和句柄……<br />
赶紧改掉了，这个bug存在了好多年啊，横跨我的几个驱动，之前从osr上摘下来的时候只是稍微调整了一下功能，没有再仔细审查……<br />
警钟警钟~ <br />
有从我那篇<a href="http://www.boxcounter.com/showthread.php?tid=36" target="_blank">《驱动中获取进程完整路径名</a>》里拷代码的朋友也赶紧更新吧，对不住大伙~<br />
<br />
两点体会：<br />
1. 别偷懒。不是自己写的代码更要仔细检查，哪怕出自osr这种权威级论坛。<br />
2. verifer不是万能的（至少在win2k3之前的版本），别偷懒。<br />
3. 别偷懒。]]></description>
			<content:encoded><![CDATA[开发过程中，我习惯会一直开着verifier进行测试，绝大部分非逻辑错误都能被揪出来。<br />
这两天测试部的同事反馈说貌似驱动有资源泄漏，我第一反应是“不会吧，有资源泄漏verifer早崩了”。<br />
测试了一下，发现还真是驱动嫌疑最大，于是开启verifer和压力测试工具，跑了一会，停掉驱动。发现没有bsod，一脑子不理解。<br />
看了下驱动停止后，内核内存情况：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>0: kd&gt; !poolused 7<br />
&nbsp;&nbsp; Sorting by&nbsp;&nbsp;NonPaged Pool Consumed<br />
<br />
&nbsp;&nbsp;Pool Used:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NonPaged&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Paged<br />
 Tag&nbsp;&nbsp;&nbsp;&nbsp;Allocs&nbsp;&nbsp;&nbsp;&nbsp;Frees&nbsp;&nbsp;&nbsp;&nbsp; Diff&nbsp;&nbsp;&nbsp;&nbsp; Used *&nbsp;&nbsp;Allocs&nbsp;&nbsp;&nbsp;&nbsp;Frees&nbsp;&nbsp;&nbsp;&nbsp; Diff&nbsp;&nbsp;&nbsp;&nbsp; Used<br />
 Proc&nbsp;&nbsp;&nbsp;&nbsp;12980&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;12979&nbsp;&nbsp;8618056 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;Process objects , Binary: nt!ps<br />
 LSwi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;2576384 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;initial work context <br />
 SePa&nbsp;&nbsp; 955604&nbsp;&nbsp; 942626&nbsp;&nbsp;&nbsp;&nbsp;12978&nbsp;&nbsp;2247904 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;&nbsp;&nbsp;Process audit image names and captured polity structures , Binary: nt!se<br />
 TCPt&nbsp;&nbsp;&nbsp;&nbsp;47617&nbsp;&nbsp;&nbsp;&nbsp;47580&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 37&nbsp;&nbsp;1423848 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;TCP/IP network protocol , Binary: TCP<br />
 SeTd&nbsp;&nbsp; 372125&nbsp;&nbsp; 359104&nbsp;&nbsp;&nbsp;&nbsp;13021&nbsp;&nbsp; 833344 *&nbsp;&nbsp;372125&nbsp;&nbsp; 359104&nbsp;&nbsp;&nbsp;&nbsp;13021&nbsp;&nbsp;1145088&nbsp;&nbsp;&nbsp;&nbsp;Security Token dynamic part , Binary: nt!se<br />
 .... 省略若干不相干信息<br />
 SEY6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY6', please update pooltag.txt<br />
 SEYC&nbsp;&nbsp;1448369&nbsp;&nbsp;1448369&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYC', please update pooltag.txt<br />
 SEYB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 47738&nbsp;&nbsp;&nbsp;&nbsp;47738&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYB', please update pooltag.txt<br />
 SEY5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY5', please update pooltag.txt<br />
 SEYA&nbsp;&nbsp;&nbsp;&nbsp;46294&nbsp;&nbsp;&nbsp;&nbsp;46294&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYA', please update pooltag.txt<br />
 SEY4&nbsp;&nbsp;1186033&nbsp;&nbsp;1186033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY4', please update pooltag.txt<br />
 SEY3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY3', please update pooltag.txt<br />
 SEY9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 47008&nbsp;&nbsp;&nbsp;&nbsp;47008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY9', please update pooltag.txt<br />
 SEY2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY2', please update pooltag.txt<br />
 SEY1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp; 54507&nbsp;&nbsp;&nbsp;&nbsp;54507&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEY1', please update pooltag.txt<br />
 SEYD&nbsp;&nbsp;1419958&nbsp;&nbsp;1419958&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;UNKNOWN pooltag 'SEYD', please update pooltag.txt<br />
 .... 省略若干不相干信息<br />
 TOTAL&nbsp;&nbsp;&nbsp;&nbsp;79306657 79234060&nbsp;&nbsp;&nbsp;&nbsp;72597 22806272 38472704 38412253&nbsp;&nbsp;&nbsp;&nbsp;60451 29841272</code></div></div>
<br />
其中SEY?就是我的驱动使用的tag，发现没有泄漏，更一头雾水了。<br />
最后瞅到第一行，nnd，'Proc'这个tag明显有问题，基本没释放。<br />
检查了一下代码，发现之前从网上摘的一段获取进程路径的函数，里面的错误结束分支没有释放EPREOCESS和句柄……<br />
赶紧改掉了，这个bug存在了好多年啊，横跨我的几个驱动，之前从osr上摘下来的时候只是稍微调整了一下功能，没有再仔细审查……<br />
警钟警钟~ <br />
有从我那篇<a href="http://www.boxcounter.com/showthread.php?tid=36" target="_blank">《驱动中获取进程完整路径名</a>》里拷代码的朋友也赶紧更新吧，对不住大伙~<br />
<br />
两点体会：<br />
1. 别偷懒。不是自己写的代码更要仔细检查，哪怕出自osr这种权威级论坛。<br />
2. verifer不是万能的（至少在win2k3之前的版本），别偷懒。<br />
3. 别偷懒。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[灵异现象？]]></title>
			<link>http://boxcounter.com/showthread.php?tid=83</link>
			<pubDate>Sun, 04 Mar 2012 15:11:58 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=83</guid>
			<description><![CDATA[前两天遇到一个灵异现象，记录下来。<br />
<br />
C代码<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>cchFullHeaderLen += strlen("Request-Line: ") +<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;strlen(pSessionData-&gt;HttpOpenReq.lpszVerb) +<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;strlen(" ") +<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;strlen(pSessionData-&gt;HttpOpenReq.lpszObjectName) +<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;(NULL != pSessionData-&gt;HttpOpenReq.lpszVersion) ? (strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion)) : 0 +<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;strlen("&#92;r&#92;n");</code></div></div>
<br />
调试的过程中发现，pSessionData-&gt;HttpOpenReq.lpszVersion为NULL，但是依然会执行“(strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion))”。<br />
<br />
确认不是编码错误后，反汇编调试：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>Boxr!MyFunction+0x2b2<br />
6a515742&nbsp;&nbsp;xor&nbsp;&nbsp;&nbsp;&nbsp; edx,edx<br />
6a515744&nbsp;&nbsp;cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ecx+23Ch],0<br />
6a51574b&nbsp;&nbsp;setne&nbsp;&nbsp; dl<br />
6a51574e&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp; esi,edx<br />
6a515750&nbsp;&nbsp;je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boxr!MyFunction+0x2ed (6a51577d)<br />
6a515752&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset Boxr!std::_Arithmetic_traits&lt;long double&gt;::_Rank+0xc88 (6a5fc0f8)<br />
6a515757&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;Boxr!strlen (6a5b5bd0)<br />
6a51575c&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp; esp,4</code></div></div>
<br />
其中ecx+23Ch就是pSessionData-&gt;HttpOpenReq.lpszVersion，查看如下：<br />
0:005&gt; dd ecx+23c<br />
0a27b18c  00000000 <br />
<br />
确认pSessionData-&gt;HttpOpenReq.lpszVersion确实为NULL。<br />
理论上6a515750处的跳转会执行的，但是没有。单步跟踪：<br />
<br />
<blockquote><cite>Quote:</cite>0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a515744 esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2b4:<br />
6a515744  cmp     dword ptr [ecx+23Ch],0 ds:0023:0a27b18c=00000000<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a51574b esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2bb:<br />
6a51574b  setne   dl<br />
<br />
0:005&gt; r zf<br />
zf=1<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a51574e esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2be:<br />
6a51574e  add     esi,edx<br />
<br />
0:005&gt; r zf<br />
zf=1<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a515750 esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl nz na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206<br />
Boxr!MyFunction+0x2c0:<br />
6a515750  je      Boxr!MyFunction+0x2ed (6a51577d) [br=0]<br />
<br />
0:005&gt; r zf<br />
zf=0</blockquote>
<br />
可以看出，原本是准备要跳转的，但是<br />
6a51574e  add     esi,edx<br />
这条指令改变了zf寄存器，于是没有跳转。<br />
<br />
那这条指令是干什么的呢？怎么会有这么一条指令？<br />
最开始怀疑是编译器优化出问题了。<br />
于是准备以发现编译器优化错误为主体写一篇BLOG。<br />
<br />
但是在整理本文的过程中，仔细分析了一遍汇编代码，发现，丫是个低级错误 —— 运算符优先级错误……<br />
实际上，C代码真正的执行逻辑是这样的：<br />
<br />
cchFullHeaderLen += <br />
<span style="color: #FF0000;">(</span>strlen("Request-Line: ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVerb) + strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszObjectName) + (NULL != pSessionData-&gt;HttpOpenReq.lpszVersion) <span style="color: #FF0000;">)</span> <br />
?<br />
 (strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion)) <br />
:<br />
 <span style="color: #FF0000;">(</span> 0 + strlen("\r\n") <span style="color: #FF0000;">)</span>;<br />
<br />
我的编码风格PPT又多了一条素材……]]></description>
			<content:encoded><![CDATA[前两天遇到一个灵异现象，记录下来。<br />
<br />
C代码<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>cchFullHeaderLen += strlen("Request-Line: ") +<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;strlen(pSessionData-&gt;HttpOpenReq.lpszVerb) +<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;strlen(" ") +<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;strlen(pSessionData-&gt;HttpOpenReq.lpszObjectName) +<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;(NULL != pSessionData-&gt;HttpOpenReq.lpszVersion) ? (strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion)) : 0 +<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;strlen("&#92;r&#92;n");</code></div></div>
<br />
调试的过程中发现，pSessionData-&gt;HttpOpenReq.lpszVersion为NULL，但是依然会执行“(strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion))”。<br />
<br />
确认不是编码错误后，反汇编调试：<br />
<br />
<div class="codeblock">
<div class="title">Code:<br />
</div><div class="body" dir="ltr"><code>Boxr!MyFunction+0x2b2<br />
6a515742&nbsp;&nbsp;xor&nbsp;&nbsp;&nbsp;&nbsp; edx,edx<br />
6a515744&nbsp;&nbsp;cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ecx+23Ch],0<br />
6a51574b&nbsp;&nbsp;setne&nbsp;&nbsp; dl<br />
6a51574e&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp; esi,edx<br />
6a515750&nbsp;&nbsp;je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boxr!MyFunction+0x2ed (6a51577d)<br />
6a515752&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset Boxr!std::_Arithmetic_traits&lt;long double&gt;::_Rank+0xc88 (6a5fc0f8)<br />
6a515757&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;Boxr!strlen (6a5b5bd0)<br />
6a51575c&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp; esp,4</code></div></div>
<br />
其中ecx+23Ch就是pSessionData-&gt;HttpOpenReq.lpszVersion，查看如下：<br />
0:005&gt; dd ecx+23c<br />
0a27b18c  00000000 <br />
<br />
确认pSessionData-&gt;HttpOpenReq.lpszVersion确实为NULL。<br />
理论上6a515750处的跳转会执行的，但是没有。单步跟踪：<br />
<br />
<blockquote><cite>Quote:</cite>0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a515744 esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2b4:<br />
6a515744  cmp     dword ptr [ecx+23Ch],0 ds:0023:0a27b18c=00000000<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a51574b esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2bb:<br />
6a51574b  setne   dl<br />
<br />
0:005&gt; r zf<br />
zf=1<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a51574e esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl zr na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246<br />
Boxr!MyFunction+0x2be:<br />
6a51574e  add     esi,edx<br />
<br />
0:005&gt; r zf<br />
zf=1<br />
<br />
0:005&gt; p<br />
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec<br />
eip=6a515750 esp=0485d518 ebp=0485d5f8 iopl=0         nv up ei pl nz na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206<br />
Boxr!MyFunction+0x2c0:<br />
6a515750  je      Boxr!MyFunction+0x2ed (6a51577d) [br=0]<br />
<br />
0:005&gt; r zf<br />
zf=0</blockquote>
<br />
可以看出，原本是准备要跳转的，但是<br />
6a51574e  add     esi,edx<br />
这条指令改变了zf寄存器，于是没有跳转。<br />
<br />
那这条指令是干什么的呢？怎么会有这么一条指令？<br />
最开始怀疑是编译器优化出问题了。<br />
于是准备以发现编译器优化错误为主体写一篇BLOG。<br />
<br />
但是在整理本文的过程中，仔细分析了一遍汇编代码，发现，丫是个低级错误 —— 运算符优先级错误……<br />
实际上，C代码真正的执行逻辑是这样的：<br />
<br />
cchFullHeaderLen += <br />
<span style="color: #FF0000;">(</span>strlen("Request-Line: ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVerb) + strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszObjectName) + (NULL != pSessionData-&gt;HttpOpenReq.lpszVersion) <span style="color: #FF0000;">)</span> <br />
?<br />
 (strlen(" ") + strlen(pSessionData-&gt;HttpOpenReq.lpszVersion)) <br />
:<br />
 <span style="color: #FF0000;">(</span> 0 + strlen("\r\n") <span style="color: #FF0000;">)</span>;<br />
<br />
我的编码风格PPT又多了一条素材……]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[日记之2012-2-22]]></title>
			<link>http://boxcounter.com/showthread.php?tid=82</link>
			<pubDate>Wed, 22 Feb 2012 22:16:54 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=82</guid>
			<description><![CDATA[今天是个好日子，值得写点什么。<br />
<br />
	早上mrcool同学Q上找我，说好久没看我更新BLOG了，写点吧。说话的语气让我不由得联想到了《记念刘和珍君》里的片段：<br />
<br />
<blockquote><cite>Quote:</cite>	 ……，遇见程君，前来问我道，“先生可曾为刘和珍写了一点什么没有？”我说“没有”。她就正告我，“先生还是写一点罢；刘和珍生前就很爱看先生的文章。” </blockquote>
<br />
	虽然情节差十万八千里，但是当时的断句确实让我想起了这段~<br />
<br />
	<br />
	最近生活比较平淡，这也让觉得“快乐要建立在别人的痛苦之上”这句话有时候还挺靠谱的 <img src="images/smilies/tongue.gif" style="vertical-align: middle;" border="0" alt="Tongue" title="Tongue" />：自从mrcool闪了之后，身边就很少发生什么惨事值得为之高兴了。于是大伙只好经常翻出“当年mrcool掉进下水道”，“当年mrcool……”等陈年记忆回味回味&#8203;，聊以助兴。<br />
<br />
	生活中总要有些比较貳的人才好玩，mrcool不在了，我把目光锁定在了媳妇身上~<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	张飞。<br />
	我：	- -| 是李逵，要多读点书，你就是吃了没文化的亏所以才这么容易被我骗到手 ……<br />
<br />
	隔了些日子，<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	李逵~<br />
	我：	你再想想？<br />
	媳妇：	~ 张飞。<br />
<br />
	又过了些日子，<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	李逵！<br />
	我：	你再想想？<br />
	媳妇：	就是李逵！你别想再糊弄我！<br />
<br />
	最近几个月，自己有了点改变，起因是几个月前给自己订的一个小任务。<br />
<br />
	大概是去年10月份，决定多花点时间练习下英语，就给自己下了个任务：每天看英文资讯，比如BBC新闻。<br />
<br />
	最开始的那些天是一天一篇长篇新闻，大概需要20分钟，不少生词。于是找了个小本，把遇到的生词都记下来。这个习惯坚持到了现在，4个月了，昨晚统计了一下，本子上记了4&#8203;00个单词。平均100个生词/月，3~4个/天，算下来速率不快，但是累积下来的成果还是挺丰硕的。现在看BBC上的新闻（通常看亚洲区新闻，特别是中国相关的）比较轻松了，有时候通篇下来都遇不到生词。<br />
<br />
	曾经在某个帖子里看一个旅美华人谈及学英语的时候提到常用单词约莫有2K~3K个。这样算下来。再坚持个1、2年也就能达到这个基本水准线了。不过这种学习方式仅适合我这&#8203;样不急着考英语等级的人。<br />
<br />
	另外，NBA.COM和英文原著的书也是挺好的学习素材。至于学习的方法，很笨很简单 —— 翻来覆去的背。我一般是在上班的路上背，反正闲着也是闲着。隔两天就从头背一遍。另外，感觉这种记单词的方法比抱着本单词册子背要高效一些，至少背的时候能大概想起这个单&#8203;词是在什么内容什么场景下出现的。目前这个400个单词记得都挺熟的，不管是英译汉还是汉译英。<br />
<br />
<br />
	貌似是11月的时候，也就是坚持了一个月后，看着小本子（当时一页最多只能记10个单词，而我习惯加上日期和空行，所以一页一般就6、7个单词。现在换大本了，一页通常能&#8203;记13个单词）上有点厚度的单词表，还是蛮有成就感的。不由得感叹坚持的力量真强大。<br />
<br />
	于是又给自己增加了点任务：锻炼身体。<br />
<br />
	最开始是每天晚上回家后做仰卧起坐、哑铃锻炼等等。坚持了两个星期，感觉太花时间了，几组轮下来，一个小时就过去了。于是开始精简，去掉哑铃项目，改成4*50仰卧起坐+&#8203;4*10仰卧抬腿（健身房里学的一种动作的简化版，没学名，姑且这么叫吧），后来增加到4*70+4*20，一直坚持到现在。效果挺好的，现在周末打球的时候跳投稳定性好&#8203;多了。<br />
<br />
	上周起又增加了一个哑铃项目，锻炼肩膀。晚上的时间是不够了，改到早上起床后做。目前才开始不到半个月，效果有待观察。<br />
<br />
<br />
	此外还有一个值得庆祝一下的小成就，从去年貌似4月开始一直坚持早起到现在。一般是7点起床，去年下半年因为媳妇上早自习的原因，坚持了半年的6点起床。起床后到出门上班&#8203;，大概有2个小时的时间，有时候拿来读书，有时候做分析。基本上都花在学习上了。<br />
<br />
<br />
	这几件事给我的警示很深刻。看起来小小的、不起眼的付出，坚持一段时间，回来再看，会发现收获颇丰。<br />
<br />
	也让我转变了一些态度，更愿意埋头多做一些灰土土朴实实的工作，慢慢积累。比如打篮球，高中时候喜欢艾佛森，于是就练有视觉效果的控球，练大幅度的晃动。在大学里的时候靠&#8203;着突破和抽风式的投篮还是能混混的。后来慢慢发现，球场上最NB的还是无解的中投和扎实的控球。现在周末都会老老实实的在楼下的破球场练几个小时的基本功，比如中投，基础&#8203;控球，上场了之后更多的进行无球跑动穿插，而不再是站着等球。感觉还是有些长进的。<br />
<br />
<br />
	总之，一句话：积硅步 以至千里 积小流 以成江海。<br />
<br />
	继续坚持下去，过段时间回头再看本文，也许会有更深刻的感触。<br />
<br />
													2012-2-22]]></description>
			<content:encoded><![CDATA[今天是个好日子，值得写点什么。<br />
<br />
	早上mrcool同学Q上找我，说好久没看我更新BLOG了，写点吧。说话的语气让我不由得联想到了《记念刘和珍君》里的片段：<br />
<br />
<blockquote><cite>Quote:</cite>	 ……，遇见程君，前来问我道，“先生可曾为刘和珍写了一点什么没有？”我说“没有”。她就正告我，“先生还是写一点罢；刘和珍生前就很爱看先生的文章。” </blockquote>
<br />
	虽然情节差十万八千里，但是当时的断句确实让我想起了这段~<br />
<br />
	<br />
	最近生活比较平淡，这也让觉得“快乐要建立在别人的痛苦之上”这句话有时候还挺靠谱的 <img src="images/smilies/tongue.gif" style="vertical-align: middle;" border="0" alt="Tongue" title="Tongue" />：自从mrcool闪了之后，身边就很少发生什么惨事值得为之高兴了。于是大伙只好经常翻出“当年mrcool掉进下水道”，“当年mrcool……”等陈年记忆回味回味&#8203;，聊以助兴。<br />
<br />
	生活中总要有些比较貳的人才好玩，mrcool不在了，我把目光锁定在了媳妇身上~<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	张飞。<br />
	我：	- -| 是李逵，要多读点书，你就是吃了没文化的亏所以才这么容易被我骗到手 ……<br />
<br />
	隔了些日子，<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	李逵~<br />
	我：	你再想想？<br />
	媳妇：	~ 张飞。<br />
<br />
	又过了些日子，<br />
	我：	“黑旋风”是谁？<br />
	媳妇：	李逵！<br />
	我：	你再想想？<br />
	媳妇：	就是李逵！你别想再糊弄我！<br />
<br />
	最近几个月，自己有了点改变，起因是几个月前给自己订的一个小任务。<br />
<br />
	大概是去年10月份，决定多花点时间练习下英语，就给自己下了个任务：每天看英文资讯，比如BBC新闻。<br />
<br />
	最开始的那些天是一天一篇长篇新闻，大概需要20分钟，不少生词。于是找了个小本，把遇到的生词都记下来。这个习惯坚持到了现在，4个月了，昨晚统计了一下，本子上记了4&#8203;00个单词。平均100个生词/月，3~4个/天，算下来速率不快，但是累积下来的成果还是挺丰硕的。现在看BBC上的新闻（通常看亚洲区新闻，特别是中国相关的）比较轻松了，有时候通篇下来都遇不到生词。<br />
<br />
	曾经在某个帖子里看一个旅美华人谈及学英语的时候提到常用单词约莫有2K~3K个。这样算下来。再坚持个1、2年也就能达到这个基本水准线了。不过这种学习方式仅适合我这&#8203;样不急着考英语等级的人。<br />
<br />
	另外，NBA.COM和英文原著的书也是挺好的学习素材。至于学习的方法，很笨很简单 —— 翻来覆去的背。我一般是在上班的路上背，反正闲着也是闲着。隔两天就从头背一遍。另外，感觉这种记单词的方法比抱着本单词册子背要高效一些，至少背的时候能大概想起这个单&#8203;词是在什么内容什么场景下出现的。目前这个400个单词记得都挺熟的，不管是英译汉还是汉译英。<br />
<br />
<br />
	貌似是11月的时候，也就是坚持了一个月后，看着小本子（当时一页最多只能记10个单词，而我习惯加上日期和空行，所以一页一般就6、7个单词。现在换大本了，一页通常能&#8203;记13个单词）上有点厚度的单词表，还是蛮有成就感的。不由得感叹坚持的力量真强大。<br />
<br />
	于是又给自己增加了点任务：锻炼身体。<br />
<br />
	最开始是每天晚上回家后做仰卧起坐、哑铃锻炼等等。坚持了两个星期，感觉太花时间了，几组轮下来，一个小时就过去了。于是开始精简，去掉哑铃项目，改成4*50仰卧起坐+&#8203;4*10仰卧抬腿（健身房里学的一种动作的简化版，没学名，姑且这么叫吧），后来增加到4*70+4*20，一直坚持到现在。效果挺好的，现在周末打球的时候跳投稳定性好&#8203;多了。<br />
<br />
	上周起又增加了一个哑铃项目，锻炼肩膀。晚上的时间是不够了，改到早上起床后做。目前才开始不到半个月，效果有待观察。<br />
<br />
<br />
	此外还有一个值得庆祝一下的小成就，从去年貌似4月开始一直坚持早起到现在。一般是7点起床，去年下半年因为媳妇上早自习的原因，坚持了半年的6点起床。起床后到出门上班&#8203;，大概有2个小时的时间，有时候拿来读书，有时候做分析。基本上都花在学习上了。<br />
<br />
<br />
	这几件事给我的警示很深刻。看起来小小的、不起眼的付出，坚持一段时间，回来再看，会发现收获颇丰。<br />
<br />
	也让我转变了一些态度，更愿意埋头多做一些灰土土朴实实的工作，慢慢积累。比如打篮球，高中时候喜欢艾佛森，于是就练有视觉效果的控球，练大幅度的晃动。在大学里的时候靠&#8203;着突破和抽风式的投篮还是能混混的。后来慢慢发现，球场上最NB的还是无解的中投和扎实的控球。现在周末都会老老实实的在楼下的破球场练几个小时的基本功，比如中投，基础&#8203;控球，上场了之后更多的进行无球跑动穿插，而不再是站着等球。感觉还是有些长进的。<br />
<br />
<br />
	总之，一句话：积硅步 以至千里 积小流 以成江海。<br />
<br />
	继续坚持下去，过段时间回头再看本文，也许会有更深刻的感触。<br />
<br />
													2012-2-22]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[TEB KPCR GS in x64]]></title>
			<link>http://boxcounter.com/showthread.php?tid=81</link>
			<pubDate>Wed, 08 Feb 2012 09:01:51 +0800</pubDate>
			<guid isPermaLink="false">http://boxcounter.com/showthread.php?tid=81</guid>
			<description><![CDATA[在x86中，如果折腾TEB或者KPCR，可能需要处理fs:[0x???]这样的地址，在x86中，咱们可以通过dg命令来手动查看：<br />
	kd&gt; dg @fs<br />
	                                  P Si Gr Pr Lo<br />
	Sel    Base     Limit     Type    l ze an es ng Flags<br />
	---- -------- -------- ---------- - -- -- -- -- --------<br />
	0030 <span style="color: #0000CD;">ffdff000</span> 00001fff Data RW Ac 0 Bg Pg P  Nl 00000c93<br />
	<br />
	<span style="color: #0000CD;">ffdff000</span>+0x???就是要找的地址了。<br />
	当然，也可以从GDTR开始从头完全手动找，不过要麻烦一些。<br />
<br />
	到了x64，TEB和KPCR都改由gs来索引了，上述dg或者GDTR方法就不灵了。<br />
	1: kd&gt; dg @gs<br />
                                                    P Si Gr Pr Lo<br />
	Sel        Base              Limit          Type    l ze an es ng Flags<br />
	---- ----------------- ----------------- ---------- - -- -- -- -- --------<br />
	002B <span style="color: #FF0000;">00000000`00000000</span> 00000000`ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3<br />
	Base为0是因为flat模式。<br />
	那么x64中我们如何手动查看gs:[0x???]呢？<br />
	<br />
	首先需要说明的是，在x64中，gs的base内容已经挪到MSR(Model-Specific Registers) (boxcounter: 可参考注1)，需要使用如下方法：<br />
	1: kd&gt; rdmsr <span style="color: #FF1493;">0xC0000101</span><br />
	msr[<span style="color: #FF1493;">c0000101</span>] = <span style="color: #FF0000;">fffff880`009f2000</span><br />
	此时gs:[0x???]指示的地址是fffff880`009f2000+0x???<br />
	其中<span style="color: #FF1493;">0xC0000101</span>就是gs的地址，每个MSR寄存器都有一个地址(boxcounter: 可参考注2)。<br />
	再来校验一下：<br />
	1: kd&gt; !pcr<br />
	KPCR for Processor 1 at <span style="color: #FF0000;">fffff880009f2000</span>:<br />
	...[省略余下无关输出内容]<br />
<br />
	注：<br />
	1. 出自《AMD64 Architecture Programmer's Manual Volume 2 [System Programming]》的“2.2.3 Segmentation”的“The FS and GS descriptor base-address fields are expanded to 64 bits and used in effective-address<br />
calculations. The 64 bits of base address are mapped to model-specific registers (MSRs), and can .only be loaded using the WRMSR instruction.”<br />
	2. 出自《Intel® 64 and IA-32 Architectures Software Developer's Manual [Volume 3B - System Programming Guide, Part 2]》中的“Appendix B Model-Specific Registers (MSRs)”的“Table B-2.  IA-32 Architectural MSRs (Contd.)”<br />
<br />
	参考资料：<br />
	1. AMD64 Architecture Programmer's Manual<br />
	2. Intel® 64 and IA-32 Architectures Software Developer's Manual]]></description>
			<content:encoded><![CDATA[在x86中，如果折腾TEB或者KPCR，可能需要处理fs:[0x???]这样的地址，在x86中，咱们可以通过dg命令来手动查看：<br />
	kd&gt; dg @fs<br />
	                                  P Si Gr Pr Lo<br />
	Sel    Base     Limit     Type    l ze an es ng Flags<br />
	---- -------- -------- ---------- - -- -- -- -- --------<br />
	0030 <span style="color: #0000CD;">ffdff000</span> 00001fff Data RW Ac 0 Bg Pg P  Nl 00000c93<br />
	<br />
	<span style="color: #0000CD;">ffdff000</span>+0x???就是要找的地址了。<br />
	当然，也可以从GDTR开始从头完全手动找，不过要麻烦一些。<br />
<br />
	到了x64，TEB和KPCR都改由gs来索引了，上述dg或者GDTR方法就不灵了。<br />
	1: kd&gt; dg @gs<br />
                                                    P Si Gr Pr Lo<br />
	Sel        Base              Limit          Type    l ze an es ng Flags<br />
	---- ----------------- ----------------- ---------- - -- -- -- -- --------<br />
	002B <span style="color: #FF0000;">00000000`00000000</span> 00000000`ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3<br />
	Base为0是因为flat模式。<br />
	那么x64中我们如何手动查看gs:[0x???]呢？<br />
	<br />
	首先需要说明的是，在x64中，gs的base内容已经挪到MSR(Model-Specific Registers) (boxcounter: 可参考注1)，需要使用如下方法：<br />
	1: kd&gt; rdmsr <span style="color: #FF1493;">0xC0000101</span><br />
	msr[<span style="color: #FF1493;">c0000101</span>] = <span style="color: #FF0000;">fffff880`009f2000</span><br />
	此时gs:[0x???]指示的地址是fffff880`009f2000+0x???<br />
	其中<span style="color: #FF1493;">0xC0000101</span>就是gs的地址，每个MSR寄存器都有一个地址(boxcounter: 可参考注2)。<br />
	再来校验一下：<br />
	1: kd&gt; !pcr<br />
	KPCR for Processor 1 at <span style="color: #FF0000;">fffff880009f2000</span>:<br />
	...[省略余下无关输出内容]<br />
<br />
	注：<br />
	1. 出自《AMD64 Architecture Programmer's Manual Volume 2 [System Programming]》的“2.2.3 Segmentation”的“The FS and GS descriptor base-address fields are expanded to 64 bits and used in effective-address<br />
calculations. The 64 bits of base address are mapped to model-specific registers (MSRs), and can .only be loaded using the WRMSR instruction.”<br />
	2. 出自《Intel® 64 and IA-32 Architectures Software Developer's Manual [Volume 3B - System Programming Guide, Part 2]》中的“Appendix B Model-Specific Registers (MSRs)”的“Table B-2.  IA-32 Architectural MSRs (Contd.)”<br />
<br />
	参考资料：<br />
	1. AMD64 Architecture Programmer's Manual<br />
	2. Intel® 64 and IA-32 Architectures Software Developer's Manual]]></content:encoded>
		</item>
		<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: 348)
<!-- 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: 348)
<!-- 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: 55)
<!-- 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: 71)
<!-- 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: 55)
<!-- 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: 55)
<!-- 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: 71)
<!-- 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: 55)
<!-- 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: 165)
<!-- 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: 165)
<!-- 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: 21)
<!-- 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: 23)
<!-- 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: 23)
<!-- 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: 21)
<!-- 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: 21)
<!-- 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: 19)
<!-- 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: 21)
<!-- 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: 23)
<!-- 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: 23)
<!-- 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: 21)
<!-- 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: 21)
<!-- 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: 19)
<!-- 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>
	</channel>
</rss>
