<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SoftRCE.net &#187; gz1x</title>
	<atom:link href="http://www.softrce.net/archives/author/gz1x/feed" rel="self" type="application/rss+xml" />
	<link>http://www.softrce.net</link>
	<description>Software Reverse Code Engineering</description>
	<lastBuildDate>Tue, 13 Sep 2011 06:58:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Think Different</title>
		<link>http://www.softrce.net/archives/296</link>
		<comments>http://www.softrce.net/archives/296#comments</comments>
		<pubDate>Thu, 11 Mar 2010 05:01:06 +0000</pubDate>
		<dc:creator>gz1x</dc:creator>
				<category><![CDATA[华山论剑（Watering）]]></category>
		<category><![CDATA[Think Different]]></category>
		<category><![CDATA[价值观]]></category>
		<category><![CDATA[创新]]></category>

		<guid isPermaLink="false">http://www.softrce.net/?p=296</guid>
		<description><![CDATA[本来有大堆的话想说，在iPad推出之后，可是想说的太多以至于理不出头绪。 想起乔布斯在1997年重回苹果担任CEO之后，推出了著名的《Think Different》广告，于是想贴上下面这段话： 向那些疯狂的家伙们致敬。 那些我行我素的家伙。 那些桀骜不驯的家伙。 那些惹事生非的家伙。 那些方孔中的圆桩。 他们总是异想天开， 既不喜欢循规蹈矩， 也不尊重既成事实。 你尽可以赞美他们，否定他们，引用他们， 质疑他们，颂扬抑或是诋毁他们。 不过惟独不能漠视他们。 因为他们进行着变革。 他们推动着人类的进程。 他们是别人眼里的疯子， 却是我们眼中的天才。 因为，只有疯狂到认为 自己能够改变世界的人， 才能真正做到这一点。 Here’s to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the square holes. The ones who see things differently. They’re not fond of rules. And they have no respect [...]]]></description>
			<content:encoded><![CDATA[<p>本来有大堆的话想说，在iPad推出之后，可是想说的太多以至于理不出头绪。<br />
想起乔布斯在1997年重回苹果担任CEO之后，推出了著名的《Think Different》广告，于是想贴上下面这段话：</p>
<p><span id="more-296"></span></p>
<blockquote><p>向那些疯狂的家伙们致敬。<br />
那些我行我素的家伙。<br />
那些桀骜不驯的家伙。<br />
那些惹事生非的家伙。<br />
那些方孔中的圆桩。<br />
他们总是异想天开，<br />
既不喜欢循规蹈矩，<br />
也不尊重既成事实。<br />
你尽可以赞美他们，否定他们，引用他们，<br />
质疑他们，颂扬抑或是诋毁他们。<br />
不过惟独不能漠视他们。<br />
因为他们进行着变革。<br />
他们推动着人类的进程。<br />
他们是别人眼里的疯子，<br />
却是我们眼中的天才。<br />
因为，只有疯狂到认为<br />
自己能够改变世界的人，<br />
才能真正做到这一点。 </p>
<p>Here’s to the crazy ones.<br />
The misfits.<br />
The rebels.<br />
The troublemakers.<br />
The round pegs in the square holes.<br />
The ones who see things differently.<br />
They’re not fond of rules.<br />
And they have no respect for the status quo.<br />
You can quote them, disagree with them, glorify or vilify them.<br />
About the only thing you can’t do is ignore them.<br />
Because they change things.<br />
They push the human race forward.<br />
And while some see them as the crazy ones,<br />
We see genius.<br />
Because the people who are crazy enough to think<br />
they can change the world,<br />
Are the ones who do. </p></blockquote>
<p>&#8212;&#8212;&#8212;&#8211;</p>
<p>而那些我能想到的字眼：核心价值观，创新理念，创新技能，用户体验&#8230;由于想说的太多，就变成了也许什么都不用说。<br />
技术是工具，想改变世界，首先改变理念。</p>
<hr /><h2>Comments</h2><ul><li><a href="http://www.softrce.net/archives/296">2010年03月13日</a>, robinh00d writes: 只能学习</li><li><a href="http://www.softrce.net/archives/296">2010年03月15日</a>, Lewis writes: 家伙们</li></ul><hr /><small>Copyright &copy; 2008<br /> This feed is for personal, non-commercial use only. <br /> The use of this feed on other websites breaches copyright. If this content is not in your news reader, it makes the page you are viewing an infringement of the copyright. (Digital Fingerprint:<br /> 8e761b2ea8edc3ca311452b020051837)</small><h3  class="related_post_title">随机日志</h3><ul class="related_post"><li>2008年10月22日 -- <a href="http://www.softrce.net/archives/15" title="构造无人之境: Exploiting Realtek RTL8139单芯片以太网控制器">构造无人之境: Exploiting Realtek RTL8139单芯片以太网控制器</a></li><li>2008年10月19日 -- <a href="http://www.softrce.net/archives/13" title="[POC]基于IO Packet隐藏文件和注册表，过磁盘解析和总线解析">[POC]基于IO Packet隐藏文件和注册表，过磁盘解析和总线解析</a></li><li>2011年09月13日 -- <a href="http://www.softrce.net/archives/405" title="Microsoft Windows NDISTAPI本地权限提升漏洞（MS11-062)">Microsoft Windows NDISTAPI本地权限提升漏洞（MS11-062)</a></li><li>2009年05月1日 -- <a href="http://www.softrce.net/archives/96" title="暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞">暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞</a></li><li>2009年04月30日 -- <a href="http://www.softrce.net/archives/63" title="Native Application之键盘处理">Native Application之键盘处理</a></li><li>2011年05月18日 -- <a href="http://www.softrce.net/archives/392" title="Microsoft Windows Vista/Server 2008 “nsiproxy.sys” Local Kernel DoS Vulnerability">Microsoft Windows Vista/Server 2008 “nsiproxy.sys” Local Kernel DoS Vulnerability</a></li><li>2010年09月13日 -- <a href="http://www.softrce.net/archives/337" title="金山毒霸2011内核溢出漏洞">金山毒霸2011内核溢出漏洞</a></li><li>2010年02月21日 -- <a href="http://www.softrce.net/archives/256" title="Step deeply into NDIS6 LightWeight Filter, part 1">Step deeply into NDIS6 LightWeight Filter, part 1</a></li><li>2009年02月1日 -- <a href="http://www.softrce.net/archives/23" title="SoftRCE的Mail Server开通了！">SoftRCE的Mail Server开通了！</a></li><li>2008年10月19日 -- <a href="http://www.softrce.net/archives/14" title="Vista Bootmgr/Winload使用的大部分选项ID">Vista Bootmgr/Winload使用的大部分选项ID</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.softrce.net/archives/296/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Steve Jobs在斯坦福大学毕业典礼上的演讲</title>
		<link>http://www.softrce.net/archives/288</link>
		<comments>http://www.softrce.net/archives/288#comments</comments>
		<pubDate>Mon, 01 Mar 2010 04:18:17 +0000</pubDate>
		<dc:creator>gz1x</dc:creator>
				<category><![CDATA[华山论剑（Watering）]]></category>
		<category><![CDATA[Stay foolish]]></category>
		<category><![CDATA[Stay hungry]]></category>
		<category><![CDATA[Steve Jobs]]></category>
		<category><![CDATA[演讲]]></category>

		<guid isPermaLink="false">http://www.softrce.net/?p=288</guid>
		<description><![CDATA[很荣幸和大家一道参加这所世界上最好的一座大学的毕业典礼。我大学没毕业，说实话，这是我第一次离大学毕业典礼这么近。今天我想给大家讲三个我自己的故事，不讲别的，也不讲大道理，就讲三个故事。 
  第一个故事讲的是点与点之间的关系。我在里德学院（Reed College）只读了六个月就退学了，此后便在学校里旁听，又过了大约一年半，我彻底离开。那么，我为什么退学呢？ 
]]></description>
			<content:encoded><![CDATA[<p> &#8212;&#8212;&#8211;</p>
<p>视频地址，中英文字幕：</p>
<p><a href="http://v.youku.com/v_show/id_XMTM3OTM5OTA0.html">http://v.youku.com/v_show/id_XMTM3OTM5OTA0.html</a></p>
<p>&#8212;&#8212;&#8212;</p>
<p>    很荣幸和大家一道参加这所世界上最好的一座大学的毕业典礼。我大学没毕业，说实话，这是我第一次离大学毕业典礼这么近。今天我想给大家讲三个我自己的故事，不讲别的，也不讲大道理，就讲三个故事。</p>
<p><span id="more-288"></span>    第一个故事讲的是点与点之间的关系。我在里德学院（Reed College）只读了六个月就退学了，此后便在学校里旁听，又过了大约一年半，我彻底离开。那么，我为什么退学呢？<br />
    这得从我出生前讲起。我的生母是一名年轻的未婚在校研究生，她决定将我送给别人收养。她非常希望收养我的是有大学学历的人，所以把一切都安排好了，我一出生就交给一对律师夫妇收养。没想到我落地的霎那间，那对夫妇却决定收养一名女孩。就这样，我的养父母—当时他们还在登记册上排队等著呢—半夜三更接到一个电话: “我们这儿有一个没人要的男婴，你们要么？”“当然要”他们回答。但是，我的生母后来发现我的养母不是大学毕业生，我的养父甚至连中学都没有毕业，所以她拒绝在最后的收养文件上签字。不过，没过几个月她就心软了，因为我的养父母许诺日后一定送我上大学。<br />
    17 年后，我真的进了大学。当时我很天真，选了一所学费几乎和斯坦福大学一样昂贵的学校，当工人的养父母倾其所有的积蓄为我支付了大学学费。读了六个月后，我却看不出上学有什么意义。我既不知道自己这一生想干什么，也不知道大学是否能够帮我弄明白自己想干什么。这时，我就要花光父母一辈子节省下来的钱了。所以，我决定退学，并且坚信日后会证明我这样做是对的。当年做出这个决定时心里直打鼓，但现在回想起来，这还真是我有生以来做出的最好的决定之一。从退学那一刻起，我就可以不再选那些我毫无兴趣的必修课，开始旁听一些看上去有意思的课。 那些日子一点儿都不浪漫。我没有宿舍，只能睡在朋友房间的地板上。我去退还可乐瓶，用那五分钱的押金来买吃的。每个星期天晚上我都要走七英里，到城那头的黑尔－科里施纳礼拜堂去，只为了吃每周才能享用一次的美餐。我喜欢这样，我凭著好奇心和直觉所干的这些事情，有许多后来都证明是无价之宝。我给大家举个例子:<br />
    当时，里德学院的美术课大概是全国最好的。校园里所有的公告栏和每个抽屉标签上的字都写得非常漂亮。当时我已经退学，不用正常上课，所以我决定选一门美术课，学学怎么写好字。我学习写带短截线和不带短截线的印刷字体，根据不同字母组合调整其间距，以及怎样把版式调整得好上加好。这门课太棒了，既有历史价值，又有艺术造诣，这一点科学就做不到，而我觉得它妙不可言。<br />
    当时我并不指望美术书法在以后的生活中能有什么实用价值。但是，十年之后，我们在设计第一台 Macintosh 计算机时，它一下子浮现在我眼前。于是，我们把这些东西全都设计进了计算机中。这是第一台有这么漂亮的文字版式的计算机。要不是我当初在大学里偶然选了这么一门课，Macintosh 计算机绝不会有那么多种印刷字体或间距安排合理的字号。要不是Windows 照搬了Macintosh，个人电脑可能不会有这些字体和字号。要不是退了学，我决不会碰巧选了这门书法课，个人电脑也可能不会有现在这些漂亮的版式了。当然，我在大学里不可能从这一点上看到它与将来的关系。十年之后再回头看，两者之间的关系就非常、非常清楚了。 你们同样不可能从现在这个点上看到将来；只有回头看时，才会发现它们之间的关系。所以，要相信这些点迟早会连接到一起。你们必须信赖某些东西—直觉、归宿、生命，还有业力，等等。这样做从来没有让我的希望落空过，而且还彻底改变了我的生活。</p>
<p>    我的第二个故事是关于好恶与得失。幸运的是，我在很小的时候就发现自己喜欢做什么。我在20岁时和沃兹（Woz，苹果公司创始人之一Wozon的昵称）在我父母的车库里办起了苹果公司。我们干得很卖力，十年后，苹果公司就从车库里我们两个人发展成为一个拥有 20 亿元资产、4,000 名员工的大企业。那时，我们刚刚推出了我们最好的产品— Macintosh 电脑—那是在第 9 年，我刚满 30 岁。可后来，我被解雇了。你怎么会被自己办的公司解雇呢？是这样，随著苹果公司越做越大，我们聘了一位我认为非常有才华的人与我一道管理公司。在开始的一年多里，一切都很顺利。可是，随后我俩对公司前景的看法开始出现分歧，最后我俩反目了。这时，董事会站在了他那一边，所以在 30 岁那年，我离开了公司，而且这件事闹得满城风雨。我成年后的整个生活重心都没有了，这使我心力交瘁。<br />
    一连几个月，我真的不知道应该怎么办。我感到自己给老一代的创业者丢了脸—因为我扔掉了交到自己手里的接力棒。我去见了戴维•帕卡德（David Packard，惠普公司创始人之一—译注）和鲍勃•诺伊斯（Bob Noyce，英特尔公司创建者之一），想为把事情搞得这么糟糕说声道歉。这次失败弄得沸沸扬扬的，我甚至想过逃离硅谷。但是，渐渐地，我开始有了一个想法—我仍然热爱我过去做的一切。在苹果公司发生的这些风波丝毫没有改变这一点。我虽然被拒之门外，但我仍然深爱我的事业。于是，我决定从头开始。<br />
    虽然当时我并没有意识到，但事实证明，被苹果公司炒鱿鱼是我一生中碰到的最好的事情。尽管前景未卜，但从头开始的轻松感取代了保持成功的沉重感。这使我进入了一生中最富有创造力的时期之一。 在此后的五年里，我开了一家名叫 NeXT 的公司和一家叫皮克斯的公司，我还爱上一位了不起的女人，后来娶了她。皮克斯公司推出了世界上第一部用电脑制作的动画片《玩具总动员》（Toy Story），它现在是全球最成功的动画制作室。世道轮回，苹果公司买下 NeXT 后，我又回到了苹果公司，我们在 NeXT 公司开发的技术成了苹果公司这次重新崛起的核心。我和劳伦娜（Laurene）也建立了美满的家庭。<br />
    我确信，如果不是被苹果公司解雇，这一切决不可能发生。这是一剂苦药，可我认为苦药利于病。有时生活会当头给你一棒，但不要灰心。我坚信让我一往无前的唯一力量就是我热爱我所做的一切。所以，一定得知道自己喜欢什么，选择爱人时如此，选择工作时同样如此。工作将是生活中的一大部分，让自己真正满意的唯一办法，是做自己认为是有意义的工作；做有意义的工作的唯一办法，是热爱自己的工作。你们如果还没有发现自己喜欢什么，那就不断地去寻找，不要急于做出决定。就像一切要凭著感觉去做的事情一样，一旦找到了自己喜欢的事，感觉就会告诉你。就像任何一种美妙的东西，历久弥新。所以说，要不断地寻找，直到找到自己喜欢的东西。不要半途而废。</p>
<p>     我的第三个故事与死亡有关。17 岁那年，我读到过这样一段话，大意是:“如果把每一天都当作生命的最后一天，总有一天你会如愿以偿。”我记住了这句话，从那时起，33 年过去了，我每天早晨都对著镜子自问: “假如今天是生命的最后一天，我还会去做今天要做的事吗？”如果一连许多天我的回答都是“不”，我知道自己应该有所改变了。<br />
    让我能够做出人生重大抉择的最主要办法是，记住生命随时都有可能结束。因为几乎所有的东西—所有对自身之外的希求、所有的尊严、所有对困窘和失败的恐惧—在死亡来临时都将不复存在，只剩下真正重要的东西。记住自己随时都会死去，这是我所知道的防止患得患失的最好方法。你已经一无所有了，还有什么理由不跟著自己的感觉走呢。<br />
    大约一年前，我被诊断患了癌症。那天早上七点半，我做了一次扫描检查，结果清楚地表明我的胰腺上长了一个瘤子，可那时我连胰腺是什么还不知道呢！医生告诉我说，几乎可以确诊这是一种无法治愈的恶性肿瘤，我最多还能活 3 到 6 个月。医生建议我回去把一切都安排好，其实这是在暗示“准备后事”。也就是说，把今后十年要跟孩子们说的事情在这几个月内嘱咐完；也就是说，把一切都安排妥当，尽可能不给家人留麻烦；也就是说，去跟大家诀别。<br />
     那一整天里，我的脑子一直没离开这个诊断。到了晚上，我做了一次组织切片检查，他们把一个内窥镜通过喉咙穿过我的胃进入肠子，用针头在胰腺的瘤子上取了一些细胞组织。当时我用了麻醉剂，陪在一旁的妻子后来告诉我，医生在显微镜里看了细胞之后叫了起来，原来这是一种少见的可以通过外科手术治愈的恶性肿瘤。我做了手术，现在好了。<br />
    这是我和死神离得最近的一次，我希望也是今后几十年里最近的一次。有了这次经历之后，现在我可以更加实在地和你们谈论死亡，而不是纯粹纸上谈兵，那就是: 谁都不愿意死。就是那些想进天堂的人也不愿意死后再进。然而，死亡是我们共同的归宿，没人能摆脱。我们注定会死，因为死亡很可能是生命最好的一项发明。它推进生命的变迁，旧的不去，新的不来。现在，你们就是新的，但在不久的将来，你们也会逐渐成为旧的，也会被淘汰。对不起，话说得太过分了，不过这是千真万确的。<br />
    你们的时间都有限，所以不要按照别人的意愿去活，这是浪费时间。不要囿于成见，那是在按照别人设想的结果而活。不要让别人观点的聒噪声淹没自己的心声。最主要的是，要有跟著自己感觉和直觉走的勇气。无论如何，感觉和直觉早就知道你到底想成为什么样的人，其他都是次要的。<br />
    我年轻时有一本非常好的刊物，叫《全球概览》（The Whole Earth Catalog），这是我那代人的宝书之一，创办人名叫斯图尔特•布兰德（Stewart Brand），就住在离这儿不远的门洛帕克市。他用诗一般的语言把刊物办得生动活泼。那是 20 世纪 60 年代末，还没有个人电脑和桌面印刷系统，全靠打字机、剪刀和宝丽莱照相机（Polaroid）。它就像一种纸质的 Google，却比 Google 早问世了 35 年。这份刊物太完美了，查阅手段齐备、构思不凡。<br />
    斯图尔特和他的同事们出了好几期《全球概览》，到最后办不下去时，他们出了最后一期。那是 20 世纪 70 年代中期，我也就是你们现在的年纪。最后一期的封底上是一张清晨乡间小路的照片，就是那种爱冒险的人等在那儿搭便车的那种小路。照片下面写道: 求知若饥，大智若愚(Stay hungry, Stay foolish)。那是他们停刊前的告别辞。<br />
    求知若饥，大智若愚。这也是我一直想做到的。眼下正值诸位大学毕业、开始新生活之际，我同样愿大家: 求知若饥，大智若愚。</p>
<hr /><h2>Comments</h2><ul><li><a href="http://www.softrce.net/archives/288">2010年03月2日</a>, <a href='http://hi.baidu.com/hankebao' rel='external nofollow' class='url'>hankebao</a> writes: 很早前看过，在vc下载的。大概是05年之前了吧。</li><li><a href="http://www.softrce.net/archives/288">2010年03月2日</a>, gz1x writes: 就是05年的，不过这篇演讲可谓是无与伦比，里面的很多话都让人感触良多，所以放上来。</li><li><a href="http://www.softrce.net/archives/288">2010年03月4日</a>, Azy writes: 不错。</li></ul><hr /><small>Copyright &copy; 2008<br /> This feed is for personal, non-commercial use only. <br /> The use of this feed on other websites breaches copyright. If this content is not in your news reader, it makes the page you are viewing an infringement of the copyright. (Digital Fingerprint:<br /> 8e761b2ea8edc3ca311452b020051837)</small><h3  class="related_post_title">随机日志</h3><ul class="related_post"><li>2008年09月29日 -- <a href="http://www.softrce.net/archives/9" title="文章预告：Exploiting Windows Device Drivers">文章预告：Exploiting Windows Device Drivers</a></li><li>2008年10月15日 -- <a href="http://www.softrce.net/archives/12" title="About Handling Nmi">About Handling Nmi</a></li><li>2009年05月15日 -- <a href="http://www.softrce.net/archives/136" title="ActiveX 控件组件的Fuzz和利用">ActiveX 控件组件的Fuzz和利用</a></li><li>2008年10月22日 -- <a href="http://www.softrce.net/archives/15" title="构造无人之境: Exploiting Realtek RTL8139单芯片以太网控制器">构造无人之境: Exploiting Realtek RTL8139单芯片以太网控制器</a></li><li>2010年05月7日 -- <a href="http://www.softrce.net/archives/310" title="IoRegisterDriverReinitialization 和IoRegisterBootDriverReinitialization">IoRegisterDriverReinitialization 和IoRegisterBootDriverReinitialization</a></li><li>2008年10月19日 -- <a href="http://www.softrce.net/archives/14" title="Vista Bootmgr/Winload使用的大部分选项ID">Vista Bootmgr/Winload使用的大部分选项ID</a></li><li>2009年05月16日 -- <a href="http://www.softrce.net/archives/140" title="静态分析驱动的一点技巧">静态分析驱动的一点技巧</a></li><li>2009年06月1日 -- <a href="http://www.softrce.net/archives/192" title="BEIH/F：总线枚举接口劫持/伪造">BEIH/F：总线枚举接口劫持/伪造</a></li><li>2008年11月16日 -- <a href="http://www.softrce.net/archives/18" title="今天又地震～～">今天又地震～～</a></li><li>2011年04月8日 -- <a href="http://www.softrce.net/archives/381" title="Microsoft Windows xp AFD.sys Local Kernel DoS Vulnerability">Microsoft Windows xp AFD.sys Local Kernel DoS Vulnerability</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.softrce.net/archives/288/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Step deeply into NDIS6 LightWeight Filter, part 1</title>
		<link>http://www.softrce.net/archives/256</link>
		<comments>http://www.softrce.net/archives/256#comments</comments>
		<pubDate>Sun, 21 Feb 2010 11:07:58 +0000</pubDate>
		<dc:creator>gz1x</dc:creator>
				<category><![CDATA[独孤九剑（Kernel）]]></category>
		<category><![CDATA[LightWeight Filter]]></category>
		<category><![CDATA[LWF]]></category>
		<category><![CDATA[NDIS6]]></category>

		<guid isPermaLink="false">http://www.softrce.net/?p=256</guid>
		<description><![CDATA[我们从NDIS的驱动栈开始，系统在启动的时候(IoInitSystem...)会加载系统驱动，典型的比如卷过滤驱动Volsnap是从IopInitializeBootDrivers的IopInitializeBuiltinDriver中启动的，一般的Filter Driver则是在IopInitializeSystemDrivers的时候加载的，而各层的DriverEntry的顺序并一定按栈自底向上走(比如TCPIP调用NdisRegisterProtocolDriver，比Miniport的注册早)，但是各自初始化完了，NDIS会接管开始调整栈结构，依次调用Miniport的MiniportInitializeEx，LightWeight Filter的FilterAttach，到最后的Protocol的ProtocolBindAdapterEx。]]></description>
			<content:encoded><![CDATA[<p>  &#8212;&#8212;&#8212;-</p>
<p>[NOTE]: 本文基于WIN7，基于一个NDIS LWF Monitor项目。 </p>
<p>  我们从NDIS的驱动栈开始，系统在启动的时候(IoInitSystem&#8230;)会加载系统驱动，典型的比如卷过滤驱动Volsnap是从IopInitializeBootDrivers的IopInitializeBuiltinDriver中启动的，一般的Filter Driver则是在IopInitializeSystemDrivers的时候加载的，而各层的DriverEntry的顺序不一定按栈自底向上走(比如TCPIP调用NdisRegisterProtocolDriver，比Miniport的注册早)，但是各自初始化完了，NDIS会接管开始调整栈结构，依次调用Miniport的MiniportInitializeEx，LightWeight Filter的FilterAttach，到最后的Protocol的ProtocolBindAdapterEx。</p>
<p> <span id="more-256"></span></p>
<p> <span style="color: #0000ff"> <span style="text-decoration: underline">{DriverEntry}</span></span></p>
<p>  挑我们感兴趣的，LWF的DriverEntry，略过初始化全局变量，读注册表等等，剩下关键点有两个：</p>
<p>  <span style="color: #0000ff">1) NdisFRegisterFilterDriver</span></p>
<p>       NdisFRegisterFilterDriver函数本身到底做了什么？</p>
<p>        1) 填充一个NDIS_FILTER_DRIVER_BLOCK；<br />
        2) 调用SetOptionsHandler，返回成功则继续把填充的结构链接进ndisFilterDriverList；<br />
        3) 检查下层Miniport是否可以把Filter Attach上去，如果Filter都加载了，那么Queue一个BindWorkitem，让Protocol有机会进行绑定。</p>
<p>       [NOTE1]: SetOptionsHandler先于FilterAttach，是第一个被调用的入口函数。但是实际上SetOptionsHandler在目前的WIN版本中只是STUB，能做什么大家自己发掘。<br />
       [NOTE2]: NdisFRegisterFilterDriver的第四个参数是个OUT宏修饰的类型，它返回的实际上就是填充的PNDIS_FILTER_DRIVER_BLOCK。</p>
<p>  <span style="color: #0000ff">2) NdisRegisterDeviceEx</span></p>
<p>        一般情况下，驱动开发人员会在DriverEntry里创建Device方便与应用层通讯。<br />
        而在LWF的DriverEntry里，你可以使用NdisRegisterDeviceEx创建一个Root Device以供通信，典型的用途是IRP_MJ_DEVICE_CONTROL枚举所有的网络接口。</p>
<p>        值得大书一笔的是，NdisRegisterDeviceEx创建的Device，要获取DeviceExtension(开发人员定义的那部分)必须使用NdisGetDeviceReservedExtension。原因在于，NdisRegisterDeviceEx在申请Extension的空间后，会自己预先创建一个类似DeviceExtension Header的结构加在你定义的DeviceExtension前面。</p>
<p>        具体NdisRegisterDeviceEx会做什么？略过其他情况，我们只关心Filter Driver里调用这个函数。</p>
<p>        首先，它从第一个参数NdisObjectHandle(记得刚才我们说过，这个参数实际上就是一个PNDIS_FILTER_DRIVER_BLOCK)里获取DriverObject；<br />
        然后，IoCreateDevice，IoCreateSymbolicLink，之后拿到DeviceObject-&gt;DeviceExtension，填充它的开头的0xA0部分，0xA0之后是用户自己定义的部分，在偏移0&#215;14的存放着一个指针，指向0xA0之后，而NdisGetDeviceReservedExtension正是获取DeviceObject-&gt;DeviceExtension + 0&#215;14这个指针。<br />
        另外，0&#215;0偏移是个Type，被赋值为9(我不太清楚到底是什么，应该是和CDO关联的)，而传入的参数DeviceAttribute.MajorFunctions将被拷贝到偏移0&#215;18处。<br />
        在这个函数内部有个地方是要值得注意的，如果是Filter Driver调用的这个函数，那么会有这么一句：<br />
          memset(DriverObject-&gt;MajorFunction, ndisDummyIrpHandler, sizeof(DriverObject-&gt;MajorFunction));<br />
        作用显而易见，而在ndisDummyIrpHandler函数里会判断Type，是17的放过，是9的则调用DeviceExtension + 0&#215;18处的MajorFunction。</p>
<p>        之后在FilterAttach里我们会再解释上面没提到的其他偏移值，这里先Mark。</p>
<p>  /////////////////////////////////</p>
<p>  对于NDIS6 Filter来说，NDIS_FILTER_DRIVER_CHARACTERISTICS是整个Filter的主体。</p>
<p>  [NOTE]: 关于Filter状态的入口函数是必须提供的，包括：FilterAttach，FilterDetach，FilterRestart，FilterPause。</p>
<p><span style="color: #0000ff"><span style="text-decoration: underline">  {FilterAttach}</span></span></p>
<p> <span style="color: #0000ff"> Q1: FilterAttach函数的调用过程?</span></p>
<p>   撇开问题，我们先回过头去看NDIS驱动栈的构造初期，有几个函数，我们看看他们都具体做了什么：</p>
<p>     NdisRegisterProtocolDriver(NDIS6)，NdisFRegisterFilterDriver(NDIS6)，NdisMRegisterMiniportDriver(NDIS6)，NdisMRegisterMiniport，NdisIMRegisterLayeredMiniport，NdisRegisterProtocol等</p>
<p>   首先看Miniport，我们以NdisMRegisterMiniportDriver为例，NDIS5或者之前的NdisMRegisterMiniport等会调用ndisRegisterMiniportDriver，但是函数内部过程都是类似的。</p>
<p>    1) 调用IoAllocateDriverObjectExtension创建一个NDIS_M_DRIVER_BLOCK结构，填充之；<br />
    2) 填充DriverObject-&gt;MajorFunction，将ndisPnPAddDevice赋值给DriverObject-&gt;DriverExtension-&gt;AddDevice；<br />
    3) 调用SetOptionsHandler，将NDIS_M_DRIVER_BLOCK链接进ndisMiniDriverList。</p>
<p>    [NOTE]: 同样的，NdisMRegisterMiniportDriver的第四个参数NdisMiniportDriverHandle其实就是PNDIS_M_DRIVER_BLOCK*类型。</p>
<p>    而在系统启动的过程中，将由PNP Mgr负责遍历并调用各PNP驱动的AddDevice，如：</p>
<p>      nt!KiThreadStartup+0&#215;19<br />
      nt!PspSystemThreadStartup+0x9e<br />
      nt!ExpWorkerThread+0x10d<br />
      nt!PnpDeviceActionWorker+0&#215;241<br />
      nt!PiProcessStartSystemDevices+0x6d<br />
      nt!PipProcessDevNodeTree+0x15d<br />
      nt!PipCallDriverAddDevice+0&#215;565<br />
      nt!PnpCallAddDevice+0xb9<br />
      nt!PpvUtilCallAddDevice+0&#215;19<br />
      ndis!ndisPnPAddDevice+0x5db<br />
      ndis!ndisAddDevice+0x6e4</p>
<p>    我们跟进ndisAddDevice，它做的事很多很繁琐：</p>
<p>     1) IoGetDriverObjectExtension获取Driver Extension，实际上就是之前的NDIS_M_DRIVER_BLOCK结构；<br />
     2) IoCreateDevice创建设备，然后IoAttachDeviceToDeviceStack，再IoCreateSymbolicLink；<br />
     3) 获取DeviceObject-&gt;DeviceExtension，按照NDIS_MINIPORT_BLOCK结构填充之，注意这里Type被赋值为17；<br />
     4) 调用ndisInitializeConfiguration进行配置信息的填充，其内部再调用ndisReadMiniportFilterList填充LWFilterList；<br />
     5) IoRegisterDeviceInterface注册一个设备接口；<br />
     6) 将填充完的NDIS_MINIPORT_BLOCK链接进ndisMiniportList。</p>
<p>   <span style="color: #000000">然后我们看NdisRegisterProtocolDriver：</span></p>
<p>    1) 分配一个NDIS_PROTOCOL_BLOCK结构，填充之；<br />
    2) 调用SetOptionsHandler，将填充完的NDIS_PROTOCOL_BLOCK链接进ndisProtocolList；<br />
    3) 调用ndisQueueWorkItem，入队一个工作者例程ndisCheckProtocolBindings。</p>
<p>   <span style="color: #0000ff">现在我们回到问题，FilterAttach是什么时候被调用的？</span>  </p>
<p>    nt!KiThreadStartup+0&#215;19<br />
    nt!PspSystemThreadStartup+0x9e<br />
    ndis!ndisWorkerThread+0xa4<br />
    ndis!ndisCheckProtocolBindings+0x11b<br />
    ndis!ndisCheckMiniportFilters+0&#215;105<br />
    ndis!ndisAttachFilterToMiniport+0xa9b<br />
     ndisFindFilterPosition<br />
     xxx!xxxFilterAttach</p>
<p>    我们看ndisAttachFilterToMiniport，它被调用的时候是这样的：<br />
      ndisAttachFilterToMiniport(CurFilterDriver, NULL, MiniBlock);<br />
    其中，MiniBlock来自ndisMiniDriverList里的MiniportQueue，CurFilterDriver来自ndisFilterDriverList。</p>
<p>    ndisFindFilterPosition原型如下：<br />
     BOOLEAN ndisFindFilterPosition(<br />
         IN PNDIS_MINIPORT_BLOCK NdisMiniBlock,<br />
         IN PUNICODE_STRING LowerFilterName,<br />
         IN PUNICODE_STRING UniqueName,<br />
         IN UCHAR FilterFlag,<br />
         OUT PUNICODE_STRING *RetName,        <br />
         OUT PNDIS_FILTER_BLOCK *LowerFilter,<br />
         OUT PNDIS_FILTER_BLOCK *HigherFilter<br />
         );<br />
-<br />
其中RetName依次经历MiniBlock-&gt;LWFilterList -&gt; FilterInstanceName -&gt; FilterModuleGuidName。</p>
<p>    ndisAttachFilterToMiniport会创建一个NDIS_FILTER_BLOCK结构，填充之后链接进ndisGlobalFilterList。<br />
    接下来是填充FilterAttach所需要的第三个参数NDIS_FILTER_ATTACH_PARAMETERS，基本上都是来自于MiniBlock，有兴趣的可以自己跟一下。<br />
    然后调用CurFilterDriver-&gt;DefaultFilterCharacteristics.AttachHandler，第一个参数就是创建的NDIS_FILTER_BLOCK，第二个参数是CurFilterDriver-&gt;FilterDriverContext，也就是NdisFRegisterFilterDriver的第二个参数返回值。</p>
<p>  <span style="color: #0000ff">Q2: FilterAttach函数该怎么写?</span></p>
<p>   代码只为演示，请勿直接使用。</p>
<p>-<br />
    NDIS_STATUS<br />
    NetmonFilterAttach(<br />
        IN NDIS_HANDLE NdisFilterHandle,<br />
        IN NDIS_HANDLE FilterDriverContext,<br />
        IN PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters<br />
        )<br />
    /*++</p>
<p>    Routine Description:</p>
<p>    Arguments:</p>
<p>    Return Value:</p>
<p>    &#8211;*/</p>
<p>    {<br />
        PMS_FILTER pFilter = NULL;<br />
        NDIS_STATUS Status = NDIS_STATUS_FAILURE;<br />
        NDIS_FILTER_ATTRIBUTES FilterAttributes;<br />
        WCHAR FilterLevel = L&#8217;0&#8242;;</p>
<p>        KdDebugIn(2);</p>
<p>        do<br />
        {<br />
            if (AttachParameters-&gt;FilterModuleGuidName-&gt;Length)<br />
            {<br />
                FilterLevel = AttachParameters-&gt;FilterModuleGuidName-&gt;Buffer[\<br />
                    ((AttachParameters-&gt;FilterModuleGuidName-&gt;Length - 1) &gt;&gt; 1)];<br />
            }</p>
<p>            if (FilterDriverContext != (NDIS_HANDLE)g_FilterDriverObject)<br />
            {<br />
                Status = NDIS_STATUS_INVALID_PARAMETER;<br />
                break;<br />
            }</p>
<p>            if (!g_AttachUpperLayers &amp;&amp; FilterLevel != L&#8217;0&#8242;)<br />
            {<br />
                if (g_NmDebug)<br />
                {<br />
                    DbgPrintEx(<br />
                        DPFLTR_IHVNETWORK_ID,<br />
                        0,<br />
                        “Discarding:%ws”,<br />
                        AttachParameters-&gt;FilterModuleGuidName-&gt;Buffer<br />
                        );<br />
                }</p>
<p>                Status = NDIS_STATUS_INVALID_PARAMETER;<br />
                break;<br />
            }</p>
<p>            if (AttachParameters-&gt;MiniportMediaType == NdisMediumWan)<br />
            {<br />
                if ((AttachParameters-&gt;BaseMiniportName-&gt;MaximumLength != 0&#215;24) ||<br />
                    (RtlCompareMemory(<br />
                    L”\\DEVICE\\NDISWANBH”,<br />
                    AttachParameters-&gt;BaseMiniportName-&gt;Buffer,<br />
                    0&#215;24) != 0&#215;24))<br />
                {<br />
                    break;<br />
                }<br />
            }<br />
            else<br />
            {<br />
                if (AttachParameters-&gt;MiniportMediaType == NdisMediumNative802_11 &amp;&amp;<br />
                    (FilterLevel != L&#8217;0&#8242;))<br />
                {<br />
                    Status = NDIS_STATUS_FAILURE;<br />
                    break;<br />
                }<br />
            }</p>
<p>            // Let&#8217;s Create Filter Modules..<br />
            //<br />
            {<br />
                if (NmCreateFilterModule(NdisFilterHandle, AttachParameters, &amp;pFilter)<br />
                    != NDIS_STATUS_SUCCESS)<br />
                {<br />
                    Status = NDIS_STATUS_RESOURCES;<br />
                    break;<br />
                }<br />
                else<br />
                {<br />
                    NdisZeroMemory(&amp;FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));</p>
<p>                    FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;<br />
                    FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);<br />
                    FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;<br />
                    FilterAttributes.Flags = 0; </p>
<p>                    Status = NdisFSetAttributes(<br />
                        NdisFilterHandle,<br />
                        pFilter,<br />
                        &amp;FilterAttributes<br />
                        );<br />
                    if (Status != NDIS_STATUS_SUCCESS)<br />
                    {<br />
                        break;<br />
                    }</p>
<p>                    NmInitializeMinipInfo(AttachParameters-&gt;MiniportMediaType, pFilter);</p>
<p>                    pFilter-&gt;State = FilterPaused;<br />
                    NmInitializeTimerSystem(pFilter);</p>
<p>                    FILTER_ACQUIRE_LOCK(&amp;g_FilterListLock, FALSE);<br />
                    InsertHeadList(&amp;g_FilterModuleList, &amp;pFilter-&gt;FilterModuleLink);<br />
                    FILTER_RELEASE_LOCK(&amp;g_FilterListLock, FALSE);<br />
                }<br />
            }</p>
<p>        } while (FALSE);</p>
<p>        return Status;<br />
    }<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>    1) FilterLevel是什么意思？</p>
<p>       FilterLevel取的是FilterModuleGuidName(形如{xxx-xxxx}-0001)的最后一个字符，它代表的是Filter所在的位置，或者粗略地理解成Filter的第几个实例。<br />
       在LWF的INF安装文件里一般要设置一个注册表值，如 HKR, Ndi,FilterClass,,XXX，FilterClass决定了LWF在整个栈里的位置，具体含义大家可以参考WDK。而在WIN7上默认有另外两个LWF存在，WfpLwf是最高层的ms_firewall_upper，另一个Psched是第二层的scheduler。当再一个LWF加入的时候，可能会插在整个栈的各层，比如某LWF Monitor就可能产生如下的布局：<br />
         {701D0081-81F3-494C-BEBB-B944C752E841}-{6E022F38-AB31-44C5-8206-2EB023EFF145}-0000<br />
         {701D0081-81F3-494C-BEBB-B944C752E841}-{B5F4D659-7DAA-4565-8E41-BE220ED60542}-0000 // Psched<br />
         {701D0081-81F3-494C-BEBB-B944C752E841}-{6E022F38-AB31-44C5-8206-2EB023EFF145}-0001<br />
         {701D0081-81F3-494C-BEBB-B944C752E841}-{B70D6460-3635-4D42-B866-B8AB1A24454C}-0000 // WfpLwf<br />
         {701D0081-81F3-494C-BEBB-B944C752E841}-{6E022F38-AB31-44C5-8206-2EB023EFF145}-0002</p>
<p>这个可以在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\XXX\Linkage\FilterList下看到。</p>
<p>        从上到下对应的是驱动栈的自底向上。{6E022F38-&#8230;}对应的是某LWF Monitor，{701D0081-&#8230;}是物理网卡。</p>
<p>       这样，FilterLevel对应的就是最后的那个字符，0、1或者2。</p>
<p>    2) FilterDriverContext之前已经解释过了，就是NdisFRegisterFilterDriver的第二个参数值，可具体灵活运用。</p>
<p>    3) g_AttachUpperLayers是在DriverEntry里初始化全局变量时从注册表读取的值，由用户设置，它标志着是不是启用类似{xxx}-0001的LWF实例。一般情况下，{xxx}-0000最贴近Miniport，如果只是监视或者嗅探Miniport上的数据，那么不要上层的那些Filter也是可以的。当然，如果您的Filter不只是Monitor，那就另当别论了。</p>
<p>    4) 接下来是两个判断，如果MiniportMediaType是NdisMediumWan，我们只Attach到NDISWANBH上，其他的不关心；<br />
        而另外一种情况，NdisMediumNative802_11，无线设备没有UpperLayer，如果FilterLevel不是0，那么我们返回。</p>
<p>    5) 排除上面的几种，剩下的Miniport都是我们关心的了，我们对每个都创建一个Filter Device，Attach上去。<br />
        创建成功之后，将DeviceExtension返回，也就是pFilter。然后必须调用NdisFSetAttributes，通知Lwf Miniport，这样pFilter才能被传给其他FilterXXX入口函数。</p>
<p>    6) InitializeMinipInfo会发OID向各个Miniport查询信息，保存到pFilter，并且向Miniport发OID设置Packet Filter以捕获数据；InitializeTimerSystem设置Timer，及时报告数据接收发送的状态信息以及其他的一些定时信息。</p>
<p>    7) g_FilterModuleList链表保存着每个Filter Device的上下文信息pFilter，也就是DeviceExtension。它可以用来给Root Device的IRP_MJ_DEVICE_CONTROL派发例程提供比如枚举所有网络接口的时候需要的相关信息。</p>
<p>   至于CreateFilterModule创建Filter Device，有几点想说明的：</p>
<p>    1) Filter Device的名字可以采用”前缀+[FilterModuleGuidName]“的形式，这样方便以后区分和处理；<br />
    2) 对AttachParameters-&gt;MiniportMediaType是NdisMediumNative802_11的情况，可以在这里处理，为无线设备创建专门的结构体记录；<br />
    3) Create Device的时候，你可以使用NdisRegisterDeviceEx，这样步骤会简单很多，但是以后访问内部成员会很费力；</p>
<p>       如果想自己IoCreateDevice，那就要注意仿造NdisRegisterDeviceEx的实现，注意DeviceExtensionSize的大小。</p>
<p>       在{DriverEntry}里，已经提到几个重点，DeviceExtension Header类似下面：</p>
<p>        /*0&#215;000*/NDIS_OBJECT_HEADER   Header;<br />
       /*0&#215;004*/LIST_ENTRY           FilterModuleLink;<br />
       /*0x00C*/NDIS_HANDLE          FilterHandle;<br />
       /*0&#215;010*/PDEVICE_OBJECT       FilterDeviceObject;<br />
       /*0&#215;014*/PVOID                UserDeviceExtention;</p>
<p>       /*0&#215;018*/PDRIVER_DISPATCH     DispatchTable[IRP_MJ_MAXIMUM_FUNCTION + 1];</p>
<p>       /*0&#215;088*/NDIS_STRING          DeviceName;<br />
       /*0&#215;090*/NDIS_STRING          SymbolicLinkName;<br />
       /*0&#215;098*/NDIS_STRING          GuidName;<br />
 </p>
<p>       (1) Header.Type 必须是 9，而且DispatchTable必须在DeviceExtension + 0&#215;18处，否则派发例程将得不到执行；<br />
       (2) pFilter必须包含以上除0&#215;14外的内容，UserExtention的就具体问题具体设计了；<br />
       (3) 什么时候DestroyFilterModule，这个可以使用引用数。</p>
<p>   当然，由于本驱动的特殊性，只是个Monitor而不是Modifier，所以比如NetBufferLists、NetBuffers pool的分配管理，读取Configuration等等，都没有涉及到，可以参考WDK的内容：Attaching a Filter Module。</p>
<p>下篇继续补完其他的FilterXXX入口函数，以及接受发送数据包时候的处理。</p>
<p>&#8212;&#8212;&#8212;</p>
<hr /><h2>Comments</h2><ul><li><a href="http://www.softrce.net/archives/256">2010年02月24日</a>, Lewis writes: 膜拜</li><li><a href="http://www.softrce.net/archives/256">2010年02月27日</a>, Luke writes: 可以做一些Modifier这方面的讨论与研究，比如IpDir，或者虚拟网关。</li></ul><hr /><h2>Related posts:</h2><ul><li><a href="http://www.softrce.net/archives/189" rel="bookmark" title="Permanent Link: 基于NDIS Filter 抓包">基于NDIS Filter 抓包</a></li></ul><hr /><small>Copyright &copy; 2008<br /> This feed is for personal, non-commercial use only. <br /> The use of this feed on other websites breaches copyright. If this content is not in your news reader, it makes the page you are viewing an infringement of the copyright. (Digital Fingerprint:<br /> 8e761b2ea8edc3ca311452b020051837)</small><h3  class="related_post_title">随机日志</h3><ul class="related_post"><li>2009年05月1日 -- <a href="http://www.softrce.net/archives/96" title="暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞">暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞</a></li><li>2008年09月30日 -- <a href="http://www.softrce.net/archives/10" title="[国庆礼]Exploiting Windows Device Drivers译文版">[国庆礼]Exploiting Windows Device Drivers译文版</a></li><li>2011年04月8日 -- <a href="http://www.softrce.net/archives/381" title="Microsoft Windows xp AFD.sys Local Kernel DoS Vulnerability">Microsoft Windows xp AFD.sys Local Kernel DoS Vulnerability</a></li><li>2010年01月12日 -- <a href="http://www.softrce.net/archives/213" title="MS07-014调试手记">MS07-014调试手记</a></li><li>2010年03月11日 -- <a href="http://www.softrce.net/archives/296" title="Think Different">Think Different</a></li><li>2009年04月26日 -- <a href="http://www.softrce.net/archives/1" title="SoftRCE再次回归上线">SoftRCE再次回归上线</a></li><li>2009年05月1日 -- <a href="http://www.softrce.net/archives/100" title="暴风影音2009(Config.dll)ActiveX远程栈溢出漏洞">暴风影音2009(Config.dll)ActiveX远程栈溢出漏洞</a></li><li>2008年10月19日 -- <a href="http://www.softrce.net/archives/14" title="Vista Bootmgr/Winload使用的大部分选项ID">Vista Bootmgr/Winload使用的大部分选项ID</a></li><li>2008年10月9日 -- <a href="http://www.softrce.net/archives/11" title="About the SMM rootkit">About the SMM rootkit</a></li><li>2009年05月5日 -- <a href="http://www.softrce.net/archives/126" title="[玩笑]某人不是会坐在被告席上吧？">[玩笑]某人不是会坐在被告席上吧？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.softrce.net/archives/256/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to adjust the Ace of device object</title>
		<link>http://www.softrce.net/archives/217</link>
		<comments>http://www.softrce.net/archives/217#comments</comments>
		<pubDate>Wed, 10 Feb 2010 08:28:03 +0000</pubDate>
		<dc:creator>gz1x</dc:creator>
				<category><![CDATA[独孤九剑（Kernel）]]></category>
		<category><![CDATA[ACE]]></category>
		<category><![CDATA[GroupSid]]></category>

		<guid isPermaLink="false">http://www.softrce.net/?p=217</guid>
		<description><![CDATA[一直想给以前弄的东西写点什么或者给KP贡献点代码文档什么的，但是苦于一直没有时间，换工作，换住处，换了很多东西，也就没闲的下来抛砖了，难得要过年了，扔一块试试水深。
直接扔关键代码，不想写太多的说明，本来这些代码也只是副产品,眼尖的应该能看出来这些代码的来处和用处。

PACCESS_ALLOWED_ACE
GetAceFromAcl(
    IN PACL Dacl,
    IN ULONG AceIndex
    )

<!--more--><!--more-->]]></description>
			<content:encoded><![CDATA[<p> <br />
直接扔关键代码，不想写太多的说明，本来这些代码也只是副产品，眼尖的应该能看出来这些代码的来处和去处。</p>
<p><span id="more-217"></span><!--more--><br />
===============</p>
<pre>PACCESS_ALLOWED_ACE
GetAceFromAcl(
    IN PACL Dacl,
    IN ULONG AceIndex
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    USHORT i = 0;
    PACCESS_ALLOWED_ACE Ace = NULL;

    if (Dacl &amp;&amp; AceIndex &lt; Dacl-&gt;AceCount)
    {
        for (Ace = FirstAce(Dacl); i &lt; AceIndex; Ace = NextAce(Ace))
        {
            if (Ace &gt;= (PACCESS_ALLOWED_ACE)((PUCHAR)Dacl + Dacl-&gt;AclSize))
            {
                break;
            }

            ++ i;   
        }

        if (i == AceIndex)
        {
            return Ace;
        }
    }

    return NULL;
}

BOOLEAN
NmCheckDaclForGroupSid(
    IN PACL Dacl
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{ 
    USHORT i = 0;
    USHORT gSidOffset, cSidOffset;
    BOOLEAN result = FALSE;
    PACCESS_ALLOWED_ACE pACE = NULL;
    SIZE_T retLong;

    if (g_GroupAce-&gt;Header.AceSize &gt;= (USHORT)(sizeof(ACCESS_ALLOWED_ACE)))
    {
        gSidOffset = g_GroupAce-&gt;Header.AceSize -
              (USHORT)(sizeof(ACCESS_ALLOWED_ACE));  

        if (Dacl-&gt;AceCount)
        {
            do
            {
                pACE = GetAceFromAcl(Dacl, i);

                if (pACE)
                {
                    cSidOffset = pACE-&gt;Header.AceSize -
                          (USHORT)(sizeof(ACCESS_ALLOWED_ACE));

                    if (gSidOffset == cSidOffset)
                    {
                        retLong = RtlCompareMemory(
                            &amp;(pACE-&gt;SidStart),
                            &amp;(g_GroupAce-&gt;SidStart),
                            cSidOffset
                            );

                        result = (cSidOffset == retLong);

                        if (result == TRUE)
                        {
                            return result;
                        }
                    }
                 }

                 ++ i;

            } while (i &lt; Dacl-&gt;AceCount);
        }
    }

    return result;
}

BOOLEAN
AddAceToAcl(
    IN PACL NewAcl,
    IN PACCESS_ALLOWED_ACE toAddAce
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{ 
    USHORT i = 0;
    PACCESS_ALLOWED_ACE Ace = FirstAce(NewAcl);

    if (NewAcl &amp;&amp; toAddAce)
    {
        if (NewAcl-&gt;AceCount)
        {
            for (NOTHING; i &lt; NewAcl-&gt;AceCount; Ace = NextAce(Ace))
            {
                if (Ace &gt;= (PACCESS_ALLOWED_ACE)((PUCHAR)NewAcl + NewAcl-&gt;AclSize))
                {
                    break;
                }

                ++ i;
            }
         }

         if ((PACCESS_ALLOWED_ACE)((PUCHAR)Ace + toAddAce-&gt;Header.AceSize) &gt;
                        (PACCESS_ALLOWED_ACE)((PUCHAR)NewAcl + NewAcl-&gt;AclSize))
         {
             return FALSE;
         }
         else
         {
             NdisMoveMemory(
                 Ace,
                 toAddAce,
                 toAddAce-&gt;Header.AceSize
                 );

             NewAcl-&gt;AceCount = i + 1;
         }
    }

    return TRUE;
}

NDIS_STATUS
NmModifyDacl(
    IN PACL oldDacl,
    OUT PACL* NewDacl
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    NDIS_STATUS result = NDIS_STATUS_SUCCESS;
    USHORT tSize;
    PACL tmpDacl = NULL;
    USHORT i = 0;
    PACCESS_DENIED_ACE pdACE = NULL;
    PACCESS_ALLOWED_ACE paACE = NULL;

    if (oldDacl)
    {
        tSize = oldDacl-&gt;AclSize + g_GroupAce-&gt;Header.AceSize;

        tmpDacl = (PACL)ExAllocatePoolWithTag(
            NonPagedPool,
            tSize,
            'dnTF'
            );
        if (tmpDacl)
        {
            tmpDacl-&gt;AclRevision = oldDacl-&gt;AclRevision;   
            tmpDacl-&gt;Sbz1 = oldDacl-&gt;Sbz1;
            tmpDacl-&gt;AceCount = 0;
            tmpDacl-&gt;AclSize = tSize;   
            tmpDacl-&gt;Sbz2 = oldDacl-&gt;Sbz2;

            if (oldDacl-&gt;AceCount)
            {
                do
                {
                    pdACE = (PACCESS_DENIED_ACE)GetAceFromAcl(
                        oldDacl,
                        i
                        );
                    if (pdACE-&gt;Header.AceType != ACCESS_DENIED_ACE_TYPE)
                    {
                        break;
                    }

                    AddAceToAcl(tmpDacl, (PACCESS_ALLOWED_ACE)pdACE);

                    ++ i;

                } while (i &lt; oldDacl-&gt;AceCount);    
             }

             AddAceToAcl(tmpDacl, g_GroupAce);

             while(i &lt; oldDacl-&gt;AceCount)
             {
                 paACE = GetAceFromAcl(oldDacl, i);

                 AddAceToAcl(tmpDacl, (PACCESS_ALLOWED_ACE)paACE);

                 ++ i;
             }

             *NewDacl= tmpDacl;
        }
    }   

    return result;
}

NDIS_STATUS
NmAddGroupAccessAce(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;

    ULONG csize = sizeof(SECURITY_DESCRIPTOR);
    PACL NewDdcl = NULL;
    HANDLE Handle = NULL;
    BOOLEAN DaclPresent, DaclDefaulted;
    PACL Dacl = NULL;

    if (DeviceObject &amp;&amp; g_GroupAce)
    {
        Status = ObOpenObjectByPointer(
            DeviceObject,
            OBJ_KERNEL_HANDLE,
            NULL,
            WRITE_DAC,
            0,
            0,
            &amp;Handle
            );
        if (Status == NDIS_STATUS_SUCCESS)
        {
            SecurityDescriptor = DeviceObject-&gt;SecurityDescriptor;

            Status = RtlGetDaclSecurityDescriptor(
                SecurityDescriptor,
                &amp;DaclPresent,
                &amp;Dacl,
                &amp;DaclDefaulted
                );
            if (Status == NDIS_STATUS_SUCCESS)
            {
                ASSERT(DaclPresent);
                ASSERT(Dacl != NULL);

                if (NmCheckDaclForGroupSid(Dacl) != TRUE)
                {
                    csize = RtlLengthSecurityDescriptor(SecurityDescriptor);

                    NewSecurityDescriptor = ExAllocatePoolWithTag(
                        NonPagedPool,
                        g_GroupAce-&gt;Header.AceSize + csize,
                        'dnTF'
                        );
                    if (NewSecurityDescriptor)
                    {
                        RtlCreateSecurityDescriptor(
                            NewSecurityDescriptor,
                            SECURITY_DESCRIPTOR_REVISION
                            );

                        Status = NmModifyDacl(
                            Dacl,
                            &amp;NewDdcl
                            );
                        if (Status == NDIS_STATUS_SUCCESS)
                        {
                            Status = RtlSetDaclSecurityDescriptor(
                                NewSecurityDescriptor,
                                TRUE,
                                NewDdcl,
                                FALSE
                                );
                            if (Status == NDIS_STATUS_SUCCESS)
                            {
                                Status = ZwSetSecurityObject(
                                    Handle,
                                    DACL_SECURITY_INFORMATION,
                                    NewSecurityDescriptor
                                    );
                            }
                        }
                    }
                }
            }
        }

        if (Handle)
        {
            ZwClose(Handle);
        }

        if (NewSecurityDescriptor)
        {
            ExFreePoolWithTag(NewSecurityDescriptor, 'dnTF');
        }

        if (NewDdcl)
        {
            ExFreePoolWithTag(NewDdcl, 'dnTF');
        }
    }

    return Status;
}</pre>
<p>===============</p>
<p>在RegisterDevice之后加上即可，对于g_GroupAce，这个查询注册表或者自己获取，这些都是因时而异。<br />
我这里是需要从注册表读过来的，然后加上去的：</p>
<p>===============</p>
<pre>PACCESS_ALLOWED_ACE g_GroupAce = NULL;

//...省略...

       InitializeObjectAttributes(
           &amp;ObjectAttributes,
           RegistryPath,
           OBJ_CASE_INSENSITIVE,
           NULL,
           NULL
           );

       Status = ZwOpenKey(
           &amp;hHandle,
           KEY_READ,
           &amp;ObjectAttributes
           );
       if (Status == STATUS_SUCCESS)
       {
           RtlInitUnicodeString(&amp;DestinationString, L"GroupSid");

           Status = ZwQueryValueKey(
               hHandle,
               &amp;DestinationString,
               KeyValueFullInformation,
               0,
               0,
               &amp;ResultLength
               );
           if (Status == STATUS_BUFFER_OVERFLOW ||
               Status == STATUS_BUFFER_TOO_SMALL)
           {
               pBuffer = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(
                   NonPagedPool,
                   ResultLength,
                   'dnTF'
                   );  
               if (pBuffer)
               {
                   Status = ZwQueryValueKey(
                       hHandle,
                       &amp;DestinationString,
                       KeyValueFullInformation,
                       pBuffer,
                       ResultLength,
                       &amp;ResultLength
                       );
                   if (Status == STATUS_SUCCESS)
                   {
                         g_GroupAce = (PACCESS_ALLOWED_ACE)ExAllocatePoolWithTag(
                              NonPagedPool,
                              pBuffer-&gt;DataLength + sizeof(ACCESS_ALLOWED_ACE),
                              'gamn'
                              );
                         if (g_GroupAce)
                         {
                              NdisZeroMemory(
                                  g_GroupAce,
                                  pBuffer-&gt;DataLength + sizeof(ACCESS_ALLOWED_ACE)
                                  );

                              g_GroupAce-&gt;Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
                              g_GroupAce-&gt;Header.AceFlags = 0;
                              g_GroupAce-&gt;Header.AceSize =
                                   (USHORT)(pBuffer-&gt;DataLength +
                                   sizeof(ACCESS_ALLOWED_ACE));

                              g_GroupAce-&gt;Mask = SYNCHRONIZE |
                                   READ_CONTROL | FILE_READ_ATTRIBUTES |
                                   FILE_READ_DATA | FILE_READ_EA;

                              NdisMoveMemory(
                                  (PVOID)&amp;(g_GroupAce-&gt;SidStart),
                                  (PVOID)((PUCHAR)pBuffer + pBuffer-&gt;DataOffset),
                                  pBuffer-&gt;DataLength
                                  );

//...省略...</pre>
<p>===============</p>
<p>PS: 排版很麻烦，我改了半天。下篇把这个工程的真正精华部分放上来大家探讨。</p>
<hr /><h2>Comments</h2><ul><li><a href="http://www.softrce.net/archives/217">2010年10月11日</a>, Lewis writes: 你丫的，没下文了！</li></ul><hr /><h2>Related posts:</h2><ul><li><a href="http://www.softrce.net/archives/10" rel="bookmark" title="Permanent Link: [国庆礼]Exploiting Windows Device Drivers译文版">[国庆礼]Exploiting Windows Device Drivers译文版</a></li><li><a href="http://www.softrce.net/archives/9" rel="bookmark" title="Permanent Link: 文章预告：Exploiting Windows Device Drivers">文章预告：Exploiting Windows Device Drivers</a></li><li><a href="http://www.softrce.net/archives/14" rel="bookmark" title="Permanent Link: Vista Bootmgr/Winload使用的大部分选项ID">Vista Bootmgr/Winload使用的大部分选项ID</a></li></ul><hr /><small>Copyright &copy; 2008<br /> This feed is for personal, non-commercial use only. <br /> The use of this feed on other websites breaches copyright. If this content is not in your news reader, it makes the page you are viewing an infringement of the copyright. (Digital Fingerprint:<br /> 8e761b2ea8edc3ca311452b020051837)</small><h3  class="related_post_title">随机日志</h3><ul class="related_post"><li>2010年01月12日 -- <a href="http://www.softrce.net/archives/213" title="MS07-014调试手记">MS07-014调试手记</a></li><li>2008年09月30日 -- <a href="http://www.softrce.net/archives/10" title="[国庆礼]Exploiting Windows Device Drivers译文版">[国庆礼]Exploiting Windows Device Drivers译文版</a></li><li>2009年05月5日 -- <a href="http://www.softrce.net/archives/126" title="[玩笑]某人不是会坐在被告席上吧？">[玩笑]某人不是会坐在被告席上吧？</a></li><li>2009年05月1日 -- <a href="http://www.softrce.net/archives/96" title="暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞">暴风影音2009(mps.dll)ActiveX远程栈溢出漏洞</a></li><li>2009年05月1日 -- <a href="http://www.softrce.net/archives/100" title="暴风影音2009(Config.dll)ActiveX远程栈溢出漏洞">暴风影音2009(Config.dll)ActiveX远程栈溢出漏洞</a></li><li>2009年05月16日 -- <a href="http://www.softrce.net/archives/140" title="静态分析驱动的一点技巧">静态分析驱动的一点技巧</a></li><li>2009年04月30日 -- <a href="http://www.softrce.net/archives/83" title="中国游戏中心游戏大厅ActiveX远程栈溢出漏洞">中国游戏中心游戏大厅ActiveX远程栈溢出漏洞</a></li><li>2009年01月10日 -- <a href="http://www.softrce.net/archives/21" title="容易被忽略的IDA快捷键">容易被忽略的IDA快捷键</a></li><li>2010年02月21日 -- <a href="http://www.softrce.net/archives/256" title="Step deeply into NDIS6 LightWeight Filter, part 1">Step deeply into NDIS6 LightWeight Filter, part 1</a></li><li>2010年08月3日 -- <a href="http://www.softrce.net/archives/320" title="SoftRCE官方T恤开始订购了~">SoftRCE官方T恤开始订购了~</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.softrce.net/archives/217/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

